bugfix
This commit is contained in:
commit
5c55a7b37f
3
3parties/dash.all.min.js
vendored
Normal file
3
3parties/dash.all.min.js
vendored
Normal file
File diff suppressed because one or more lines are too long
26174
3parties/hls.js
Normal file
26174
3parties/hls.js
Normal file
File diff suppressed because it is too large
Load Diff
@ -198,6 +198,7 @@ bricks.buildBind = async function(w, desc){
|
||||
return;
|
||||
}
|
||||
var event = desc.event;
|
||||
desc.event_widget = widget;
|
||||
await bricks.buildEventBind(w, widget, event, desc);
|
||||
}
|
||||
|
||||
|
||||
@ -1,7 +1,7 @@
|
||||
SOURCES=" page_data_loader.js factory.js uitypesdef.js utils.js uitype.js \
|
||||
i18n.js widget.js layout.js bricks.js image.js html.js splitter.js \
|
||||
jsoncall.js myoperator.js scroll.js menu.js popup.js camera.js modal.js running.js \
|
||||
markdown_viewer.js video.js audio.js toolbar.js tab.js \
|
||||
markdown_viewer.js audio.js toolbar.js tab.js \
|
||||
input.js registerfunction.js button.js accordion.js dataviewer.js \
|
||||
tree.js multiple_state_image.js dynamiccolumn.js form.js message.js conform.js \
|
||||
paging.js datagrid.js iframe.js cols.js echartsext.js \
|
||||
@ -10,7 +10,7 @@ SOURCES=" page_data_loader.js factory.js uitypesdef.js utils.js uitype.js \
|
||||
llm_dialog.js llm.js websocket.js datarow.js tabular.js continueaudio.js \
|
||||
line.js pie.js bar.js gobang.js period.js iconbarpage.js \
|
||||
keypress.js asr.js webspeech.js countdown.js progressbar.js \
|
||||
qaframe.js svg.js "
|
||||
qaframe.js svg.js videoplayer.js "
|
||||
echo ${SOURCES}
|
||||
cat ${SOURCES} > ../dist/bricks.js
|
||||
# uglifyjs --compress --mangle -- ../dist/bricks.js > ../dist/bricks.min.js
|
||||
|
||||
@ -81,7 +81,8 @@ bricks.Camera = class extends bricks.Popup {
|
||||
canvas.width = this.video.videoWidth;
|
||||
const context = canvas.getContext('2d');
|
||||
context.drawImage(this.video, 0, 0);
|
||||
this.imgw.set_url(canvas.toDataURL('image/jpeg'));
|
||||
this.dataurl = canvas.toDataURL('image/jpeg', 0.95);
|
||||
this.imgw.set_url(this.dataurl);
|
||||
this.task = schedule_once(this.show_picture.bind(this), this.task_period);
|
||||
this.show_cnt += 1;
|
||||
}
|
||||
@ -118,8 +119,7 @@ bricks.Camera = class extends bricks.Popup {
|
||||
}
|
||||
this.task_period = 0;
|
||||
this.task = null;
|
||||
var d = this.imgw.base64();
|
||||
this.dispatch('shot', d);
|
||||
this.dispatch('shot', this.dataurl);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@ -9,6 +9,14 @@ body {
|
||||
display: flex;
|
||||
}
|
||||
|
||||
.responsive-img {
|
||||
max-width: 100%; /* 限制最大宽度为容器 */
|
||||
width: 100%; /* 占满容器宽度 */
|
||||
height: auto; /* 高度自动,保持比例 */
|
||||
display: block; /* 避免底部留空隙 */
|
||||
object-fit: contain; /* 确保完整显示,而不是裁切 */
|
||||
}
|
||||
|
||||
pre {
|
||||
overflow-x: auto; /* 允许内容超出容器显示 */
|
||||
background-color: #b5e5e5;
|
||||
@ -32,6 +40,15 @@ hr {
|
||||
border-radius: 30%;
|
||||
background-color: #f5f5f5;
|
||||
}
|
||||
|
||||
.tabular {
|
||||
border-radius: 8px;
|
||||
padding: 5px;
|
||||
margin: 5px;
|
||||
background-color: #f5f5f5;
|
||||
border: 1px solid #888888;
|
||||
}
|
||||
|
||||
.card {
|
||||
border-radius: 8px;
|
||||
padding: 5px;
|
||||
@ -39,6 +56,12 @@ hr {
|
||||
background-color: #f5f5f5;
|
||||
border: 1px solid #888888;
|
||||
}
|
||||
|
||||
.card:hover {
|
||||
box-shadow: 0 4px 12px rgba(0, 0, 0, 0.6);
|
||||
border: 2px solid #ff8080;
|
||||
}
|
||||
|
||||
.subcard {
|
||||
background-color: #eeeeee;
|
||||
}
|
||||
@ -403,7 +426,7 @@ hr {
|
||||
flex-shrink: 0;
|
||||
}
|
||||
.tabular-row:nth-child(odd) {
|
||||
background-color: #5dfdfd;
|
||||
background-color: #efefef;
|
||||
}
|
||||
.tabular-row:nth-child(even) {
|
||||
background-color: #f9f9f9;
|
||||
@ -492,3 +515,72 @@ hr {
|
||||
align-self: center;
|
||||
}
|
||||
|
||||
.video-container {
|
||||
position: relative;
|
||||
width: 100%;
|
||||
height: auto;
|
||||
max-width: 1000px;
|
||||
overflow: hidden;
|
||||
border-radius: 12px;
|
||||
background: #000;
|
||||
}
|
||||
|
||||
.video-element {
|
||||
width: 100%;
|
||||
height: auto;
|
||||
display: block;
|
||||
}
|
||||
|
||||
.controls {
|
||||
position: absolute;
|
||||
bottom: 0;
|
||||
left: 0;
|
||||
right: 0;
|
||||
background: linear-gradient(to top, rgba(0,0,0,0.8), transparent);
|
||||
color: white;
|
||||
font-size: 14px;
|
||||
padding: 10px 15px;
|
||||
transition: opacity 0.3s;
|
||||
opacity: 0.9;
|
||||
}
|
||||
|
||||
.controls:hover {
|
||||
opacity: 1;
|
||||
}
|
||||
|
||||
.progress-container {
|
||||
margin-bottom: 10px;
|
||||
}
|
||||
|
||||
.progress-bar {
|
||||
width: 100%;
|
||||
accent-color: #ff0000;
|
||||
}
|
||||
|
||||
.controls-bottom {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 10px;
|
||||
flex-wrap: wrap;
|
||||
}
|
||||
|
||||
.play-pause, .mute, .fullscreen {
|
||||
background: none;
|
||||
border: none;
|
||||
color: white;
|
||||
font-size: 18px;
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
.volume, .playback-speed, .audio-track-select {
|
||||
font-size: 14px;
|
||||
padding: 2px;
|
||||
}
|
||||
|
||||
.time {
|
||||
font-family: monospace;
|
||||
}
|
||||
|
||||
.fullscreen {
|
||||
margin-left: auto;
|
||||
}
|
||||
|
||||
@ -34,6 +34,8 @@
|
||||
--->
|
||||
|
||||
<script src="{{entire_url('/bricks/3parties/recorder.wav.min.js')}}"></script>
|
||||
<script src="https://sage.opencomputing.cn/bricks/3parties/hls.js"></script>
|
||||
<script src="https://sage.opencomputing.cn/bricks/3parties/dash.all.min.js"></script>
|
||||
<script src="{{entire_url('/bricks/bricks.js')}}"></script>
|
||||
<script src="{{entire_url('/js/myapp.js')}}"></script>
|
||||
<script>
|
||||
|
||||
@ -10,24 +10,13 @@ bricks.Image = class extends bricks.JsWidget {
|
||||
constructor(opts){
|
||||
super(opts);
|
||||
this.opts = opts;
|
||||
this.options_parse();
|
||||
if (this.opts.url){
|
||||
this.set_url(this.opts.url);
|
||||
}
|
||||
}
|
||||
create(){
|
||||
this.dom_element = document.createElement('img');
|
||||
}
|
||||
options_parse(){
|
||||
if (this.opts.hasOwnProperty('url')){
|
||||
this.set_url(this.opts.url);
|
||||
}
|
||||
if (this.opts.hasOwnProperty('width')){
|
||||
this.width = this.opts.width;
|
||||
this.dom_element.style.width = this.width;
|
||||
}
|
||||
if (this.opts.hasOwnProperty('height')){
|
||||
this.height = this.opts.height;
|
||||
this.dom_element.style.height = this.height;
|
||||
}
|
||||
}
|
||||
removeBase64Header(base64String) {
|
||||
return base64String.replace(/^data:[^;]*;base64,/, '');
|
||||
}
|
||||
@ -51,8 +40,16 @@ bricks.Image = class extends bricks.JsWidget {
|
||||
}
|
||||
set_url(url){
|
||||
this.url = url;
|
||||
if (this.opts.default_url) {
|
||||
this.dom_element.onerror = this.set_default_url.bind(this)
|
||||
}
|
||||
this.dom_element.src = url;
|
||||
}
|
||||
set_default_url(){
|
||||
console.log('default_url', this.opts.default_url);
|
||||
this.dom_element.onerror = null;
|
||||
this.dom_element.src = this.opts.default_url;
|
||||
}
|
||||
}
|
||||
|
||||
bricks.Icon = class extends bricks.Image {
|
||||
|
||||
1
bricks/imgs/camera.svg
Normal file
1
bricks/imgs/camera.svg
Normal file
@ -0,0 +1 @@
|
||||
<svg t="1756730700908" class="icon" viewBox="0 0 1381 1024" version="1.1" xmlns="http://www.w3.org/2000/svg" p-id="5410" width="100%" height="100%"><path d="M690.604651 840.453953c-160.148837 0-290.232558-131.143442-290.232558-291.923348C400.372093 387.738791 530.455814 256.595349 690.604651 256.595349s290.232558 131.143442 290.232558 291.935256C980.837209 709.298605 850.753488 840.453953 690.604651 840.453953z m0-511.095069c-119.962791 0-217.6 98.208744-217.6 218.874046 0 120.665302 97.637209 218.874047 217.6 218.874047s217.6-98.208744 217.6-218.874047c0-120.665302-97.637209-218.874047-217.6-218.874046z" fill="#000000" p-id="5411"></path><path d="M1343.702326 1023.106977H37.506977c-19.944186 0-36.316279-16.467349-36.316279-36.530605V183.546047c0-20.063256 16.372093-36.530605 36.316279-36.530605h325.060465l110.437209-132.941395a35.816186 35.816186 0 0 1 27.981396-13.181024H881.116279c10.716279 0 20.837209 4.798512 27.981395 13.181024l110.43721 132.941395h325.060465c19.944186 0 36.316279 16.467349 36.316279 36.530605v803.030325c-0.893023 20.063256-16.967442 36.530605-37.209302 36.530605zM73.823256 950.045767h1233.860465V220.064744H1001.972093c-10.716279 0-20.837209-4.786605-27.981395-13.169116L863.553488 73.954233h-345.897674L407.218605 206.895628a35.816186 35.816186 0 0 1-27.981396 13.169116H73.823256V950.057674z" fill="${color}" p-id="5412"></path></svg>
|
||||
|
After Width: | Height: | Size: 1.3 KiB |
@ -516,7 +516,7 @@ bricks.UiImage =class extends bricks.VBox {
|
||||
"width":"90%"
|
||||
});
|
||||
camera.bring_to_top();
|
||||
camera.bind('shot', this.accept_photo.bind(this));
|
||||
camera.bind('shot', this.accept_photo.bind(this, camera));
|
||||
}
|
||||
accept_photo(camera, event){
|
||||
camera.dismiss();
|
||||
@ -527,6 +527,7 @@ bricks.UiImage =class extends bricks.VBox {
|
||||
url:event.params,
|
||||
width:'100%'
|
||||
});
|
||||
this.value = event.params
|
||||
this.add_widget(this.imgw);
|
||||
}
|
||||
handleFileSelect(event){
|
||||
@ -546,9 +547,8 @@ bricks.UiImage =class extends bricks.VBox {
|
||||
this.remove_widget(this.imgw);
|
||||
}
|
||||
this.value = e.target.result;
|
||||
console.log('this.value=', this.value);
|
||||
this.imgw = new bricks.Image({
|
||||
url:e.target.result,
|
||||
url:this.value,
|
||||
width:'100%'
|
||||
});
|
||||
this.add_widget(this.imgw);
|
||||
@ -560,20 +560,14 @@ bricks.UiImage =class extends bricks.VBox {
|
||||
fd.append(this.name, this.resultValue());
|
||||
}
|
||||
resultValue(){
|
||||
if (this.imgw){
|
||||
this.value = this.imgw.base64();
|
||||
if (this.value){
|
||||
return this.value;
|
||||
}
|
||||
return null;
|
||||
}
|
||||
getValue(){
|
||||
var ret = {}
|
||||
if (this.imgw){
|
||||
// ret[this.name] = this.imgw.base64()
|
||||
ret[this.name] = this.value;
|
||||
} else {
|
||||
ret[this.name] = null;
|
||||
}
|
||||
var ret = {};
|
||||
ret[this.name] = this.resultValue();
|
||||
return ret;
|
||||
}
|
||||
}
|
||||
@ -1104,7 +1098,7 @@ bricks.UiVideo =class extends bricks.UiStr {
|
||||
url: bricks_resource('imgs/right_arrow.svg')});
|
||||
this.add_widget(this.icon);
|
||||
this.icon.bind('click', this.play_audio.bind(this));
|
||||
this.player = new bricks.VideoPlayer({
|
||||
this.player = new bricks.Video({
|
||||
url:this.value
|
||||
});
|
||||
if (this.autoplay){
|
||||
|
||||
119
bricks/llm.js
119
bricks/llm.js
@ -75,7 +75,7 @@ bricks.ModelOutput = class extends bricks.VBox {
|
||||
this.filler.set_css('filler');
|
||||
this.content.add_widget(new bricks.BlankIcon({rate:2, flexShrink:0}));
|
||||
this.content.add_widget(this.filler);
|
||||
this.content.add_widget(new bricks.BlankIcon({rate:2, flexShrink:0}));
|
||||
// this.content.add_widget(new bricks.BlankIcon({rate:2, flexShrink:0}));
|
||||
this.build_estimate_widgets();
|
||||
}
|
||||
build_estimate_widgets(){
|
||||
@ -116,18 +116,19 @@ bricks.ModelOutput = class extends bricks.VBox {
|
||||
}
|
||||
async update_data(data){
|
||||
if (this.run) {
|
||||
this.received_content = '';
|
||||
this.received_reasoning_content = '';
|
||||
this.run.stop_timepass();
|
||||
this.content.remove_widget(this.run);
|
||||
if(this.textvoice){
|
||||
this.upstreaming = new bricks.UpStreaming({
|
||||
url:this.tts_url
|
||||
});
|
||||
this.upstreaming.go();
|
||||
}
|
||||
}
|
||||
if (this.upstreaming){
|
||||
this.upstreaming.send(data.content);
|
||||
if (data.content){
|
||||
this.received_content += data.content;
|
||||
}
|
||||
data.content = bricks.escapeSpecialChars(this.received_content);
|
||||
if (data.reasoning_content){
|
||||
this.received_reasoning_content += data.reasoning_content;
|
||||
}
|
||||
data.reasoning_content = bricks.escapeSpecialChars(this.received_reasoning_content);
|
||||
this.run = null;
|
||||
this.filler.clear_widgets();
|
||||
if (typeof this.output_view === 'string'){
|
||||
@ -151,9 +152,7 @@ bricks.ModelOutput = class extends bricks.VBox {
|
||||
}
|
||||
}
|
||||
finish(){
|
||||
if (this.upstreaming){
|
||||
this.upstreaming.finish();
|
||||
}
|
||||
console.log('finished')
|
||||
}
|
||||
}
|
||||
|
||||
@ -178,7 +177,6 @@ bricks.LlmModel = class extends bricks.JsWidget {
|
||||
constructor(llmio, opts){
|
||||
super(opts);
|
||||
this.llmio = llmio;
|
||||
this.messages = [];
|
||||
}
|
||||
render_title(){
|
||||
var w = new bricks.HBox({padding:'15px'});
|
||||
@ -188,8 +186,8 @@ bricks.LlmModel = class extends bricks.JsWidget {
|
||||
tip:this.opts.modelname,
|
||||
url:this.opts.icon||bricks_resource('imgs/llm.svg')
|
||||
});
|
||||
// var txt = new bricks.Text({text:this.opts.modelname});
|
||||
w.add_widget(img);
|
||||
// var txt = new bricks.Text({text:this.opts.modelname});
|
||||
// w.add_widget(txt);
|
||||
return w;
|
||||
}
|
||||
@ -203,30 +201,21 @@ bricks.LlmModel = class extends bricks.JsWidget {
|
||||
} else {
|
||||
d = objcopy(data);
|
||||
}
|
||||
var fmt = this.opts.user_message_format;
|
||||
if (fmt){
|
||||
var umsg = bricks.apply_data(fmt, inputdata2dic(data));
|
||||
this.messages.push(umsg);
|
||||
}
|
||||
if (data instanceof FormData){
|
||||
d.append('model', this.opts.model)
|
||||
d.append('llmid', this.opts.llmid)
|
||||
d.append('messages', JSON.stringify(this.messages));
|
||||
} else {
|
||||
d.messages = JSON.stringify(this.messages);
|
||||
d.model = this.opts.model;
|
||||
d.llmid = this.opts.llmid;
|
||||
}
|
||||
return d;
|
||||
}
|
||||
async model_inputed(data){
|
||||
if (!opts.use_session){
|
||||
this.messages = [];
|
||||
}
|
||||
var mout = new bricks.ModelOutput({
|
||||
textvoice:this.textvoice,
|
||||
tts_url:this.tts_url,
|
||||
icon:this.opts.icon,
|
||||
response_mode: this.opts.response_mode,
|
||||
model:this.opts.model,
|
||||
modelname:this.opts.modelname,
|
||||
estimate_url:this.llmio.estimate_url,
|
||||
@ -234,26 +223,17 @@ bricks.LlmModel = class extends bricks.JsWidget {
|
||||
this.llmio.o_w.add_widget(mout);
|
||||
if (this.response_mode == 'stream' || this.response_mode == 'async') {
|
||||
var d = this.inputdata2uploaddata(data);
|
||||
console.log('data_inouted=', data, 'upload_data=', d);
|
||||
var hr = new bricks.HttpResponseStream();
|
||||
var resp = await hr.post(this.opts.url, {params:d});
|
||||
await hr.handle_chunk(resp, this.chunk_response.bind(this, mout));
|
||||
this.chunk_ended();
|
||||
} else {
|
||||
var d = this.inputdata2uploaddata(data);
|
||||
console.log('data_inouted=', data, 'upload_data=', d);
|
||||
var hj = new bricks.HttpJson()
|
||||
var resp = await hj.post(this.opts.url, {params:d});
|
||||
if (this.response_mode == 'sync'){
|
||||
resp.content = bricks.escapeSpecialChars(resp.content)
|
||||
mout.update_data(resp);
|
||||
if (this.messages){
|
||||
var msg = this.llm_msg_format();
|
||||
var lmsg = bricks.apply_data(msg, resp);
|
||||
this.messages.push(lmsg)
|
||||
}
|
||||
} else {
|
||||
;
|
||||
}
|
||||
resp.content = bricks.escapeSpecialChars(resp.content)
|
||||
mout.update_data(resp);
|
||||
}
|
||||
}
|
||||
is_accept_source(source){
|
||||
@ -266,25 +246,24 @@ bricks.LlmModel = class extends bricks.JsWidget {
|
||||
return this.llm_message_format || {role:'assistant', content:"${content}"}
|
||||
}
|
||||
chunk_response(mout, l){
|
||||
var d = JSON.parse(l);
|
||||
if (! d.content || d.content == ''){
|
||||
return;
|
||||
l = l.trim();
|
||||
try {
|
||||
var d = JSON.parse(l);
|
||||
} catch(e){
|
||||
console.log(l, 'is not a json data');
|
||||
return
|
||||
}
|
||||
d.content = bricks.escapeSpecialChars(d.content);
|
||||
this.resp_data = d;
|
||||
if (this.opts.response_mode == 'async'){
|
||||
if(d.status != 'SUCCEEDED'){
|
||||
console.log('filter all message not successed');
|
||||
return;
|
||||
}
|
||||
}
|
||||
console.log('l=', l, 'd=', d);
|
||||
mout.update_data(d);
|
||||
// console.log('stream data=', d);
|
||||
}
|
||||
chunk_ended(){
|
||||
if (! this.messages) {
|
||||
console.log('this.messages is null !!!!!!!!!');
|
||||
return;
|
||||
}
|
||||
var msg = this.llm_msg_format();
|
||||
var txt = bricks.escapeSpecialChars(this.resp_data.content)
|
||||
this.resp_data.content = txt;
|
||||
var lmsg = bricks.apply_data(msg, this.resp_data);
|
||||
this.messages.push(lmsg);
|
||||
console.log('chunk end');
|
||||
}
|
||||
}
|
||||
bricks.LlmIO = class extends bricks.VBox {
|
||||
@ -378,8 +357,8 @@ bricks.LlmIO = class extends bricks.VBox {
|
||||
var sopts = {
|
||||
data_url:this.list_models_url,
|
||||
data_params:{
|
||||
mii:this.models[0].modelinstanceid,
|
||||
mti:this.models[0].modeltypeid
|
||||
llmid:this.models[0].llmid,
|
||||
llmcatelogid:this.models[0].llmcatelogid
|
||||
},
|
||||
data_method:'POST',
|
||||
col_cwidth: 24,
|
||||
@ -391,10 +370,24 @@ bricks.LlmIO = class extends bricks.VBox {
|
||||
},
|
||||
subwidgets:[
|
||||
{
|
||||
widgettype:"Title4",
|
||||
options:{
|
||||
text:"${name}"
|
||||
}
|
||||
widgettype: "HBox",
|
||||
options: {
|
||||
cheight: 2
|
||||
},
|
||||
subwidgets: [
|
||||
{
|
||||
widgettype:"Svg",
|
||||
options: {
|
||||
url:"/appbase/show_icon.dspy?id=${iconid}"
|
||||
}
|
||||
},
|
||||
{
|
||||
widgettype:"Title6",
|
||||
options:{
|
||||
text:"${name}"
|
||||
}
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
widgettype:"Filler",
|
||||
@ -437,8 +430,9 @@ bricks.LlmIO = class extends bricks.VBox {
|
||||
async add_new_model(event){
|
||||
event.preventDefault();
|
||||
event.stopPropagation();
|
||||
this.models.push(event.params);
|
||||
this.show_added_model(event.params);
|
||||
var llm = event.params;
|
||||
this.models.push(llm);
|
||||
this.show_added_model(llm);
|
||||
}
|
||||
async open_input_widget(event){
|
||||
event.preventDefault();
|
||||
@ -471,10 +465,7 @@ bricks.LlmIO = class extends bricks.VBox {
|
||||
await this.show_input(params);
|
||||
for(var i=0;i<this.llmmodels.length;i++){
|
||||
var lm = this.llmmodels[i];
|
||||
if (lm.is_accept_source('userinput')){
|
||||
schedule_once(lm.model_inputed.bind(lm, params), 0.01);
|
||||
// await lm.model_inputed(params);
|
||||
}
|
||||
schedule_once(lm.model_inputed.bind(lm, params), 0.01);
|
||||
};
|
||||
}
|
||||
async show_input(params){
|
||||
@ -485,7 +476,7 @@ bricks.LlmIO = class extends bricks.VBox {
|
||||
w.set_css(this.msg_css||'user_msg');
|
||||
w.set_css('filler');
|
||||
var img = new bricks.Svg({rate:2,url:this.user_icon||bricks_resource('imgs/chat-user.svg')});
|
||||
box.add_widget(new bricks.BlankIcon({rate:2, flexShrink:0}));
|
||||
// box.add_widget(new bricks.BlankIcon({rate:2, flexShrink:0}));
|
||||
box.add_widget(w);
|
||||
box.add_widget(img);
|
||||
this.o_w.add_widget(box);
|
||||
|
||||
@ -23,21 +23,24 @@ bricks.Menu = class extends bricks.VBox {
|
||||
return cp;
|
||||
}
|
||||
async menu_clicked(event){
|
||||
console.log(event);
|
||||
let e = event.target;
|
||||
let opts = event.params;
|
||||
var t;
|
||||
var popts;
|
||||
if (this.target == 'PopupWindow'){
|
||||
var target = opts.target || this.target;
|
||||
var popup_options = opts.popup_options || this.popup_options;
|
||||
if (target == 'PopupWindow'){
|
||||
popts = bricks.get_popupwindow_default_options();
|
||||
bricks.extend(popts, this.popup_options || {});
|
||||
bricks.extend(popts, popup_options || {});
|
||||
popts.icon = opts.icon;
|
||||
popts.title = opts.label || opts.name
|
||||
t = new bricks.PopupWindow(popts);
|
||||
} else if (this.target == 'Popup'){
|
||||
popts = bricks.get_popup_default_options();
|
||||
bricks.extend(popts, this.popup_options || {});
|
||||
bricks.extend(popts, popup_options || {});
|
||||
t = new bricks.Popup(popts);
|
||||
} else {
|
||||
t = bricks.getWidgetById(this.target);
|
||||
t = bricks.getWidgetById(target);
|
||||
}
|
||||
if (t){
|
||||
var desc = {
|
||||
@ -64,18 +67,41 @@ bricks.Menu = class extends bricks.VBox {
|
||||
let subw = this.create_menuitem(item);
|
||||
if (item.hasOwnProperty('items')){
|
||||
var itw = new bricks.VBox({});
|
||||
w.add_widget(itw);
|
||||
let w1 = this.create_submenu_container();
|
||||
itw.add_widget(subw);
|
||||
itw.add_widget(w1);
|
||||
this.create_children(w1, item.items);
|
||||
subw.bind('click', this.items_toggle_hide.bind(this, w1));
|
||||
w.add_widget(itw);
|
||||
} else if(item.submenu){
|
||||
var itw = new bricks.VBox({});
|
||||
let w1 = this.create_submenu_container();
|
||||
w1.submenu_loaded = false;
|
||||
w1.submenu_url = item.submenu;
|
||||
itw.add_widget(subw);
|
||||
itw.add_widget(w1);
|
||||
w.add_widget(itw);
|
||||
subw.bind('click', this.load_submenu.bind(this, w1));
|
||||
} else {
|
||||
subw.bind('click', this.regen_menuitem_event.bind(this, item))
|
||||
w.add_widget(subw);
|
||||
}
|
||||
}
|
||||
}
|
||||
async get_submenu_items(url){
|
||||
var jc = new bricks.HttpJson();
|
||||
var d = await jc.get(url);
|
||||
return d.options.items;
|
||||
}
|
||||
async load_submenu(container, event){
|
||||
event.stopPropagation();
|
||||
if (! container.submenu_loaded){
|
||||
var items = await this.get_submenu_items(container.submenu_url);
|
||||
this.create_children(container, items);
|
||||
container.submenu_loaded = true;
|
||||
}
|
||||
container.toggle_hide();
|
||||
}
|
||||
items_toggle_hide(w, event){
|
||||
w.toggle_hide();
|
||||
event.stopPropagation();
|
||||
|
||||
@ -105,7 +105,7 @@ bricks.QAFrame = class extends bricks.VBox {
|
||||
console.log('show_courseware(), d=', d);
|
||||
switch(d.type){
|
||||
case 'video':
|
||||
w = new bricks.VideoPlayer({
|
||||
w = new bricks.Video({
|
||||
width:'100%',
|
||||
height:'100%',
|
||||
url:d.url,
|
||||
|
||||
@ -24,7 +24,7 @@ bricks.HScrollPanel = class extends bricks.HBox {
|
||||
constructor(opts){
|
||||
opts.width = '100%';
|
||||
opts.height = '100%';
|
||||
opts.css = 'scrollpanel';
|
||||
opts.css = opts.css + ' scrollpanel';
|
||||
opts.overflow = 'auto';
|
||||
super(opts);
|
||||
this.min_threshold = opts.min_threshold || 0.01;
|
||||
@ -66,7 +66,7 @@ bricks.VScrollPanel = class extends bricks.VBox {
|
||||
constructor(opts){
|
||||
opts.width = '100%';
|
||||
opts.height = '100%';
|
||||
opts.css = 'scrollpanel';
|
||||
opts.css = opts.css + ' scrollpanel';
|
||||
opts.overflow = 'auto';
|
||||
super(opts);
|
||||
this.min_threshold = opts.min_threshold || 0.02;
|
||||
|
||||
@ -289,17 +289,29 @@ bricks.Tree = class extends bricks.VScrollPanel {
|
||||
this.update_node();
|
||||
break;
|
||||
default:
|
||||
if ((opts.selected_data || opts.checked_data) && ! this.selected_node){
|
||||
if (opts.selected_data && ! this.selected_node){
|
||||
var w = new bricks.Error({title:'Error', message:'No selected node found'});
|
||||
w.open();
|
||||
return;
|
||||
}
|
||||
console.log('opts=', opts);
|
||||
var d = null;
|
||||
if (opts.checked_data){
|
||||
d = this.checked_data
|
||||
} else if (opts.selected_data){
|
||||
d = this.selected_node.user_data
|
||||
if (opts.checked_data && this.checked_data.length == 0){
|
||||
var w = new bricks.Error({title:'Error', message:'No checked node found'});
|
||||
w.open();
|
||||
return;
|
||||
}
|
||||
var d = {};
|
||||
if (opts.selected_data){
|
||||
d = this.selected_node.user_data;
|
||||
} else if (opts.checked_data){
|
||||
d = this.checked_data;
|
||||
} else {
|
||||
if (this.selected_node){
|
||||
d = this.selected_node.user_data;
|
||||
} else if (this.checked_data.length>0) {
|
||||
d = this.checked_data[0];
|
||||
} else {
|
||||
d = this.opts.params;
|
||||
}
|
||||
}
|
||||
d.meta_data = {
|
||||
referer: this.id,
|
||||
|
||||
@ -1,6 +1,55 @@
|
||||
var bricks = window.bricks || {};
|
||||
bricks.bug = false;
|
||||
|
||||
/*
|
||||
We use ResizeObserver to implements dom object resize event
|
||||
*/
|
||||
bricks.resize_observer = new ResizeObserver(entries => {
|
||||
for (let entry of entries){
|
||||
const cr = entry.contentRect;
|
||||
const ele = entry.target;
|
||||
const w = ele.bricks_widget;
|
||||
// console.log('size=', cr, 'element=', ele, w);
|
||||
if (w){
|
||||
w.dispatch('element_resize', cr);
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
/* MutationObserver for add to DOM or remove from DOM
|
||||
event:
|
||||
domon: add to dom
|
||||
domoff: remove from dom
|
||||
*/
|
||||
bricks.dom_on_off_observer=new MutationObserver((mutations)=>{
|
||||
function handleRemoved(node) {
|
||||
if (node.nodeType !== 1) return; // 只处理元素节点
|
||||
if (node.bricks_widget) {
|
||||
console.log('**** widget removed', node.bricks_widget);
|
||||
node.bricks_widget.dispatch('domoff');
|
||||
}
|
||||
// 遍历后代
|
||||
for (let child of node.querySelectorAll('*')) {
|
||||
if (child.bricks_widget) {
|
||||
console.log('**** widget removed (descendant)', child.bricks_widget);
|
||||
child.bricks_widget.dispatch('domoff');
|
||||
}
|
||||
}
|
||||
}
|
||||
for (let m of mutations) {
|
||||
for (let n of m.removedNodes) {
|
||||
handleRemoved(n);
|
||||
}
|
||||
for (let n of m.addedNodes) {
|
||||
if (n.bricks_widget){
|
||||
var w = n.bricks_widget;
|
||||
w.dispatch('domon');
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
bricks.dom_on_off_observer.observe(document.body,
|
||||
{ childList: true, subtree: true });
|
||||
function addParamsToUrl(url, params, widget) {
|
||||
const urlObj = new URL(url, window.baseURI); // 处理相对和绝对路径
|
||||
Object.keys(params).forEach(key => {
|
||||
@ -664,6 +713,30 @@ function blobToBase64(blob) {
|
||||
reader.readAsDataURL(blob);
|
||||
});
|
||||
}
|
||||
/*
|
||||
opts = {
|
||||
css:
|
||||
id
|
||||
}
|
||||
*/
|
||||
bricks.dom_create = function(tag, opts){
|
||||
var e = document.createElement(tag);
|
||||
if (opts.css){
|
||||
var arr = css.split(' ');
|
||||
arr.forEach(c =>{
|
||||
e.classList.add(c);
|
||||
});
|
||||
}
|
||||
if (opts.id){
|
||||
e.id = opts.id;
|
||||
}
|
||||
return e;
|
||||
}
|
||||
bricks.element_from_html = function(html){
|
||||
var e = document.createElement('div');
|
||||
e.outerHTML = html;
|
||||
return e;
|
||||
}
|
||||
/*
|
||||
// 使用队列
|
||||
const queue = new Queue();
|
||||
|
||||
322
bricks/videoplayer.js
Normal file
322
bricks/videoplayer.js
Normal file
@ -0,0 +1,322 @@
|
||||
var bricks = window.bricks || {}
|
||||
/*
|
||||
use hls to play m3u8
|
||||
https://cdn.jsdelivr.net/npm/hls.js@latest
|
||||
use dash to play dash
|
||||
https://cdn.dashjs.org/latest/dash.all.min.js
|
||||
*/
|
||||
|
||||
bricks.VideoPlayer = class extends bricks.VBox {
|
||||
/*
|
||||
opts:
|
||||
url: video source
|
||||
autoplay:true or false
|
||||
*/
|
||||
constructor(opts) {
|
||||
super(opts)
|
||||
this.set_css('video-container');
|
||||
this.dom_element.innerHTML = `<video id="video" class="video-element"></video>
|
||||
<div class="controls">
|
||||
<div class="progress-container">
|
||||
<input type="range" class="progress-bar" value="0" step="0.0001" />
|
||||
</div>
|
||||
<div class="controls-bottom">
|
||||
<button class="play-pause">▶</button>
|
||||
<div class="volume-container">
|
||||
<button class="mute">🔊</button>
|
||||
<input type="range" class="volume" min="0" max="1" step="0.01" value="1" />
|
||||
</div>
|
||||
<span class="time">00:00 / 00:00</span>
|
||||
<div class="speed-container">
|
||||
<select class="playback-speed">
|
||||
<option value="0.5">0.5x</option>
|
||||
<option value="0.75">0.75x</option>
|
||||
<option value="1" selected>1x</option>
|
||||
<option value="1.25">1.25x</option>
|
||||
<option value="1.5">1.5x</option>
|
||||
<option value="2">2x</option>
|
||||
</select>
|
||||
</div>
|
||||
<div class="audio-tracks">
|
||||
<select class="audio-track-select"></select>
|
||||
</div>
|
||||
<button class="fullscreen">⛶</button>
|
||||
</div>
|
||||
</div>`
|
||||
this.video = this.dom_element.querySelector('.video-element');
|
||||
this.controls = this.dom_element.querySelector('.controls');
|
||||
|
||||
this.hls = null;
|
||||
this.dashPlayer = null;
|
||||
|
||||
this.playPauseBtn = this.controls.querySelector('.play-pause');
|
||||
this.muteBtn = this.controls.querySelector('.mute');
|
||||
this.volumeInput = this.controls.querySelector('.volume');
|
||||
this.progressBar = this.controls.querySelector('.progress-bar');
|
||||
this.timeDisplay = this.controls.querySelector('.time');
|
||||
this.speedSelect = this.controls.querySelector('.playback-speed');
|
||||
this.audioTrackSelect = this.controls.querySelector('.audio-track-select');
|
||||
this.fullscreenBtn = this.controls.querySelector('.fullscreen');
|
||||
|
||||
this.bind('domon', this.init.bind(this));
|
||||
this.bind('domoff', this.destroy.bind(this));
|
||||
}
|
||||
|
||||
destroy(){
|
||||
if (this.hls) {
|
||||
this.hls.destroy();
|
||||
this.hls = null;
|
||||
}
|
||||
if (this.dashPlayer) {
|
||||
this.dashPlayer.reset();
|
||||
this.dashPlayer = null;
|
||||
}
|
||||
this.video.src = ''; // 清空
|
||||
}
|
||||
init() {
|
||||
this.loadVideo(this.opts.url); // 可替换为 mp4 / m3u8 / mpd
|
||||
this.bindEvents();
|
||||
this.updateUI();
|
||||
if (this.opts.autoplay && this.video.paused){
|
||||
this.playPauseBtn.click();
|
||||
}
|
||||
}
|
||||
|
||||
loadVideo(src) {
|
||||
// 销毁旧播放器
|
||||
this.destroy()
|
||||
|
||||
if (src.endsWith('.m3u8') || src.includes('m3u8')) {
|
||||
if (Hls.isSupported()) {
|
||||
this.hls = new Hls({
|
||||
enableWebVTT: false, // 不加载 WebVTT
|
||||
enableIMSC1: false, // 不加载 IMSC1/TTML
|
||||
renderTextTracksNatively: false // 不用浏览器原生 track
|
||||
});
|
||||
this.hls.subtitleTrack = -1; // 关闭字幕轨道
|
||||
this.hls.loadSource(src);
|
||||
this.hls.attachMedia(this.video);
|
||||
this.hls.on(Hls.Events.MANIFEST_PARSED, () => this.onLoaded());
|
||||
} else {
|
||||
console.error('HLS not supported');
|
||||
}
|
||||
} else if (src.endsWith('.mpd') || src.includes('mpd')) {
|
||||
this.dashPlayer = dashjs.MediaPlayer().create();
|
||||
this.dashPlayer.initialize(this.video, src, true);
|
||||
this.dashPlayer.on('manifestParsed', () => this.onLoaded());
|
||||
} else {
|
||||
// 普通视频
|
||||
this.video.src = src;
|
||||
this.video.addEventListener('loadedmetadata', () => this.onLoaded());
|
||||
}
|
||||
}
|
||||
|
||||
onLoaded() {
|
||||
this.updateAudioTracks();
|
||||
this.updateUI();
|
||||
}
|
||||
|
||||
bindEvents() {
|
||||
// 播放/暂停
|
||||
this.playPauseBtn.addEventListener('click', () => {
|
||||
if (this.video.paused) {
|
||||
this.video.play();
|
||||
} else {
|
||||
this.video.pause();
|
||||
}
|
||||
});
|
||||
|
||||
// 静音切换
|
||||
this.muteBtn.addEventListener('click', () => {
|
||||
this.video.muted = !this.video.muted;
|
||||
this.updateMuteUI();
|
||||
});
|
||||
|
||||
// 音量变化
|
||||
this.volumeInput.addEventListener('input', (e) => {
|
||||
this.video.volume = e.target.value;
|
||||
this.video.muted = this.video.volume === 0;
|
||||
this.updateMuteUI();
|
||||
});
|
||||
|
||||
// 进度条拖动
|
||||
this.progressBar.addEventListener('input', (e) => {
|
||||
const time = e.target.value * this.video.duration;
|
||||
this.video.currentTime = time;
|
||||
});
|
||||
|
||||
// 播放速度
|
||||
this.speedSelect.addEventListener('change', (e) => {
|
||||
this.video.playbackRate = parseFloat(e.target.value);
|
||||
});
|
||||
|
||||
// 音轨切换
|
||||
this.audioTrackSelect.addEventListener('change', (e) => {
|
||||
const index = parseInt(e.target.value);
|
||||
if (this.video.audioTracks) {
|
||||
for (let i = 0; i < this.video.audioTracks.length; i++) {
|
||||
this.video.audioTracks[i].enabled = i === index;
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
// 全屏
|
||||
this.fullscreenBtn.addEventListener('click', () => {
|
||||
if (this.dom_element.requestFullscreen) {
|
||||
this.dom_element.requestFullscreen();
|
||||
} else if (this.dom_element.webkitRequestFullscreen) {
|
||||
this.dom_element.webkitRequestFullscreen();
|
||||
}
|
||||
});
|
||||
|
||||
// 视频事件
|
||||
this.video.addEventListener('play', () => this.updatePlayPauseUI());
|
||||
this.video.addEventListener('pause', () => this.updatePlayPauseUI());
|
||||
this.video.addEventListener('timeupdate', () => this.updateProgress());
|
||||
this.video.addEventListener('durationchange', () => this.updateProgress());
|
||||
this.video.addEventListener('volumechange', () => {
|
||||
this.updateMuteUI();
|
||||
this.volumeInput.value = this.video.volume;
|
||||
});
|
||||
this.video.addEventListener('loadedmetadata', () => {
|
||||
this.updateAudioTracks();
|
||||
});
|
||||
this.video.addEventListener('seeking', () => {
|
||||
this.progressBar.value = this.video.currentTime / this.video.duration;
|
||||
});
|
||||
}
|
||||
|
||||
updateUI() {
|
||||
this.updatePlayPauseUI();
|
||||
this.updateMuteUI();
|
||||
this.updateProgress();
|
||||
this.volumeInput.value = this.video.volume;
|
||||
}
|
||||
|
||||
updatePlayPauseUI() {
|
||||
this.playPauseBtn.textContent = this.video.paused ? '▶' : '❚❚';
|
||||
}
|
||||
|
||||
updateMuteUI() {
|
||||
this.muteBtn.textContent = this.video.muted || this.video.volume === 0 ? '🔇' : '🔊';
|
||||
}
|
||||
|
||||
updateProgress() {
|
||||
const percent = this.video.duration ? this.video.currentTime / this.video.duration : 0;
|
||||
this.progressBar.value = percent;
|
||||
this.timeDisplay.textContent = `${this.formatTime(this.video.currentTime)} / ${this.formatTime(this.video.duration || 0)}`;
|
||||
}
|
||||
|
||||
updateAudioTracks() {
|
||||
this.audioTrackSelect.innerHTML = '';
|
||||
if (this.video.audioTracks && this.video.audioTracks.length > 0) {
|
||||
for (let i = 0; i < this.video.audioTracks.length; i++) {
|
||||
const track = this.video.audioTracks[i];
|
||||
const option = document.createElement('option');
|
||||
option.value = i;
|
||||
option.textContent = track.label || `音轨 ${i + 1}`;
|
||||
if (track.enabled) option.selected = true;
|
||||
this.audioTrackSelect.appendChild(option);
|
||||
}
|
||||
} else {
|
||||
const option = document.createElement('option');
|
||||
option.textContent = '无音轨';
|
||||
option.disabled = true;
|
||||
this.audioTrackSelect.appendChild(option);
|
||||
}
|
||||
}
|
||||
|
||||
formatTime(seconds) {
|
||||
const s = Math.floor(seconds % 60);
|
||||
const m = Math.floor((seconds / 60) % 60);
|
||||
const h = Math.floor(seconds / 3600);
|
||||
return h > 0
|
||||
? `${h}:${m.toString().padStart(2, '0')}:${s.toString().padStart(2, '0')}`
|
||||
: `${m}:${s.toString().padStart(2, '0')}`;
|
||||
}
|
||||
|
||||
}
|
||||
bricks.Iptv = class extends bricks.VBox {
|
||||
/*
|
||||
{
|
||||
iptv_data_url:
|
||||
playok_url:
|
||||
playfailed_url:
|
||||
}
|
||||
*/
|
||||
constructor(opts){
|
||||
super(opts);
|
||||
schedule_once(this.build_subwidgets.bind(this), 0.1);
|
||||
}
|
||||
async build_subwidgets(){
|
||||
console.log('build_subwidgets called');
|
||||
if (!this.user_data){
|
||||
var jc = new bricks.HttpJson();
|
||||
this.deviceid = bricks.deviceid('iptv')
|
||||
this.user_data = await jc.httpcall(this.iptv_data_url, {
|
||||
params:{
|
||||
deviceid:this.deviceid
|
||||
},
|
||||
method:'GET'
|
||||
});
|
||||
}
|
||||
console.log('this.user_data =', this.user_data);
|
||||
this.video = new bricks.VideoPlayer({
|
||||
autoplay:true,
|
||||
url:this.user_data.url
|
||||
});
|
||||
this.title_w = new bricks.Text({text:this.user_data.tv_name, wrap:false});
|
||||
this.add_widget(this.title_w);
|
||||
this.add_widget(this.video);
|
||||
this.video.bind('play_ok', this.report_play_ok.bind(this));
|
||||
this.video.bind('play_failed', this.report_play_failed.bind(this));
|
||||
}
|
||||
async report_play_ok(){
|
||||
console.log(this.user_data, 'channel playing ...', this.playok_url);
|
||||
if (this.playok_url){
|
||||
var ht = new bricks.HttpText();
|
||||
var resp = ht.httpcall(this.playok_url,{
|
||||
params:{
|
||||
deviceid:this.deviceid,
|
||||
channelid:this.user_data.id
|
||||
},
|
||||
method:"GET"
|
||||
});
|
||||
if (resp != 'Error'){
|
||||
console.log('report playok ok');
|
||||
} else {
|
||||
console.log('report playok failed');
|
||||
}
|
||||
} else {
|
||||
console.log('this.playok_url not defined', this.playok_url);
|
||||
}
|
||||
}
|
||||
async report_play_failed(){
|
||||
console.log(this.user_data, 'channel play failed ...');
|
||||
if (this.playfailed_url){
|
||||
var ht = new bricks.HttpText();
|
||||
var resp = ht.httpcall(this.playfailed_url,{
|
||||
params:{
|
||||
deviceid:this.deviceid,
|
||||
channelid:this.user_data.id
|
||||
},
|
||||
method:"GET"
|
||||
});
|
||||
if (resp != 'Error'){
|
||||
console.log('report playfailed ok');
|
||||
} else {
|
||||
console.log('report playfailed failed');
|
||||
}
|
||||
} else {
|
||||
console.log('this.playfailed_url not defined', this.playfailed_url);
|
||||
}
|
||||
}
|
||||
setValue(data){
|
||||
this.user_data = data;
|
||||
this.title_w.set_text(data.tv_name);
|
||||
this.video.set_url(data.url);
|
||||
}
|
||||
}
|
||||
bricks.Factory.register('Iptv', bricks.Iptv);
|
||||
bricks.Factory.register('VideoPlayer', bricks.VideoPlayer);
|
||||
bricks.Factory.register('Video', bricks.VideoPlayer);
|
||||
@ -1,18 +1,4 @@
|
||||
var bricks = window.bricks || {};
|
||||
/*
|
||||
We use ResizeObserver to implements dom object resize event
|
||||
*/
|
||||
bricks.resize_observer = new ResizeObserver(entries => {
|
||||
for (let entry of entries){
|
||||
const cr = entry.contentRect;
|
||||
const ele = entry.target;
|
||||
const w = ele.bricks_widget;
|
||||
// console.log('size=', cr, 'element=', ele, w);
|
||||
if (w){
|
||||
w.dispatch('element_resize', cr);
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
bricks.JsWidget = class {
|
||||
/*
|
||||
@ -255,20 +241,20 @@ bricks.JsWidget = class {
|
||||
this.dom_element.style[k] = v;
|
||||
}
|
||||
set_csses(csses, remove_flg){
|
||||
var arr = csses.split(' ');
|
||||
arr.forEach(c =>{
|
||||
this.set_css(c, remove_flg);
|
||||
})
|
||||
this.set_css(csses, remove_flg);
|
||||
}
|
||||
unset_css(css){
|
||||
this.dom_element.classList.remove(css);
|
||||
}
|
||||
set_css(css, remove_flg){
|
||||
if (!remove_flg){
|
||||
this.dom_element.classList.add(css);
|
||||
} else {
|
||||
this.dom_element.classList.remove(css);
|
||||
}
|
||||
var arr = css.split(' ');
|
||||
arr.forEach(c => {
|
||||
if (!remove_flg){
|
||||
this.dom_element.classList.add(c);
|
||||
} else {
|
||||
this.dom_element.classList.remove(c);
|
||||
}
|
||||
});
|
||||
}
|
||||
set_cssObject(cssobj){
|
||||
bricks.extend(this.dom_element.style, cssobj);
|
||||
|
||||
@ -14,12 +14,61 @@ bricks.Wterm = class extends bricks.JsWidget {
|
||||
this.socket = null;
|
||||
this.ping_timeout = opts.ping_timeout || 19;
|
||||
schedule_once(this.open.bind(this), 1);
|
||||
this.bind('domon', this.send_term_size.bind(this));
|
||||
this.bind('domoff', this.destroy.bind(this));
|
||||
}
|
||||
close_websocket(){
|
||||
try {
|
||||
console.log('socket alive, destroy it');
|
||||
// this.socket.send(JSON.stringify({ type: "close"}));
|
||||
this.socket.close(1000,'close now');
|
||||
this.socket.onopen = null;
|
||||
this.socket.onmessage = null;
|
||||
this.socket.onerror = null;
|
||||
this.socket.onclose = null;
|
||||
this.socket = null;
|
||||
} catch(e) {
|
||||
this.socket = null;
|
||||
console.log('e=', e);
|
||||
}
|
||||
}
|
||||
close_terminal(){
|
||||
try {
|
||||
this.fitAddon.dispose();
|
||||
this.term.dispose();
|
||||
this.term = null;
|
||||
} catch(e){
|
||||
this.term = null;
|
||||
console.log('e=', e);
|
||||
}
|
||||
}
|
||||
destroy(){
|
||||
console.debug('------domoff event, destory this widget');
|
||||
try {
|
||||
if (this.heartbeat_task){
|
||||
this.heartbeat_task.cancel();
|
||||
this.heartbeat_task = null;
|
||||
}
|
||||
this.unbind('element_resize', this.term_resize.bind(this))
|
||||
} catch(e) {
|
||||
console.log('error ', e);
|
||||
}
|
||||
console.debug('---1--domoff event, destory this widget');
|
||||
if (this.socket){
|
||||
this.close_websocket();
|
||||
}
|
||||
console.debug('---2--domoff event, destory this widget');
|
||||
if (this.term){
|
||||
this.close_terminal();
|
||||
}
|
||||
console.debug('---3--domoff event, destory this widget');
|
||||
}
|
||||
charsize_sizing(){
|
||||
var cs = bricks.app.charsize;
|
||||
this.term.setOption('fontSize', cs);
|
||||
}
|
||||
send_term_size(){
|
||||
console.debug('------domon event, send the terminal size to server');
|
||||
try {
|
||||
console.log('resize():rows=', this.term.rows, this.term.cols);
|
||||
this.socket.send(JSON.stringify({ type: "resize",
|
||||
@ -44,10 +93,6 @@ bricks.Wterm = class extends bricks.JsWidget {
|
||||
this.heartbeat_task = schedule_once(this.heartbeat.bind(this),
|
||||
this.ping_timeout);
|
||||
}
|
||||
async close(){
|
||||
this.term.close();
|
||||
this.socket.close();
|
||||
}
|
||||
async open(){
|
||||
var term_options = bricks.extend({width: "100%", height: "100%"}, this.term_options);
|
||||
var term = new Terminal(term_options);
|
||||
@ -93,6 +138,7 @@ bricks.Wterm = class extends bricks.JsWidget {
|
||||
term.onResize(({cols, rows}) =>{
|
||||
this.send_term_size();
|
||||
});
|
||||
this.send_term_size();
|
||||
term.focus();
|
||||
}
|
||||
term_resize(){
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user