From 28c940c0cf7996b6f74f95da1516981e41de6c96 Mon Sep 17 00:00:00 2001 From: yumoqing Date: Tue, 26 Nov 2024 22:45:20 +0800 Subject: [PATCH 01/75] bugfix --- bricks/popup.js | 36 +++++++++++++++++++++++++++++++++++- bricks/widget.js | 36 +++++++++++++++++++++++++++++++++++- 2 files changed, 70 insertions(+), 2 deletions(-) diff --git a/bricks/popup.js b/bricks/popup.js index 74ca9ee..ad69950 100644 --- a/bricks/popup.js +++ b/bricks/popup.js @@ -53,7 +53,34 @@ bricks.Popup = class extends bricks.VBox { this.set_css('toppopup'); bricks.app.toppopup = this; } - + popup_from_widget(from_w){ + var myrect = this.showRectage(); + var rect = from_w.showRectage(); + var x,y; + var ox, oy; + ox = (rect.right - rect.left) / 2 + rect.left; + oy = (rect.bottom - rect.top) / 2 + rect.top; + if (ox < bricks.app.screenWidth() / 2) { + x = rect.right + 3; + if (x + (myrect.right - myrect.left) > bricks.app.screenWidth()){ + x = bricks.app.screenWidth() - (myrect.right - myrect.left); + } + } else { + x = rect.left - (myrect.right - myrect.left) - 3 + if (x < 0) x = 0; + } + if (oy < bricks.app.screenHeight() / 2){ + y = rect.bottom + 3; + if (y + (myrect.bottom - myrect.top) > bricks.app.screenHeight()){ + y = bricks.app.screenHeight() - (myrect.bottom - myrect.top); + } + } else { + y = rect.bottom - (myrect.bottom - myrect.top) - 3 + if (y < 0) y = 0; + } + this.set_style('top', y + 'px'); + this.set_style('left', x + 'px'); + } setup_resizable(){ this.resizable_w = new bricks.Icon({rate:1.5, url:bricks_resource('imgs/right-bottom-triangle.png')}); super.add_widget(this.resizable_w); @@ -230,6 +257,12 @@ bricks.Popup = class extends bricks.VBox { // console.log('auto_open is ', this.auto_open, ' so not auto open it', this.opts, w); } } + remove_widget(w){ + this.content_box.remove_widget(w); + } + clear_widgets(){ + this.content_box.clear_widgets(); + } open(){ var rect, w, h; if (this.opened) { @@ -261,6 +294,7 @@ bricks.Popup = class extends bricks.VBox { this.content_box.disabled(false); } dismiss(){ + if (! this.opened) return; if (this.opts.modal){ this.target_w.disabled(false); } diff --git a/bricks/widget.js b/bricks/widget.js index 5566ee7..a05ac7d 100644 --- a/bricks/widget.js +++ b/bricks/widget.js @@ -15,6 +15,13 @@ bricks.resize_observer = new ResizeObserver(entries => { }); bricks.JsWidget = class { + /* + popup:{ + popup_event: + popup_desc: + popupwindow:false or true + } + */ constructor(options){ if (!options){ options = {} @@ -38,9 +45,36 @@ bricks.JsWidget = class { var w = bricks.app.tooltip; this.bind('mousemove', w.show.bind(w, this.opts.tip)); this.bind('mouseout', w.hide.bind(w)); + this.bind('click', w.hide.bind(w)); + } + if (this.popup){ + this.bind(this.popup.popup_event, this.popup_action.bind(this)); } bricks.resize_observer.observe(this.dom_element); } + destroy_popup(){ + this.popup_widget.destroy(); + this.popup_widget = null; + } + async popup_action(){ + if (this.popup_widget){ + this.popup_widget.destroy(); + this.popup_widget = null; + } else { + if (this.popup.popupwindow){ + this.popup_widget = new bricks.PopupWindow(this.popup.optiosn); + } else { + this.popup_widget = new bricks.Popup(this.popup.options); + } + this.popup_widget.bind('dismissed', this.destroy_popup.bind(this)); + var w = await bricks.widgetBuild(this.popup.popup_desc, this, this.user_data); + if (w){ + this.popup_widget.add_widget(w); + this.popup_widget.open(); + this.popup_widget.popup_from_widget(this); + } + } + } showRectage(){ return this.dom_element.getBoundingClientRect(); } @@ -500,7 +534,7 @@ bricks.Tooltip = class extends bricks.Text { if (this.auto_task){ this.auto_task.cancel(); } - this.auto_task = schedule_once(this.hide.bind(this), 30); + this.auto_task = schedule_once(this.hide.bind(this), 6); } hide(){ if (this.auto_task){ From 7e6603b0ec87714370193343b1d984b7ca71bbf8 Mon Sep 17 00:00:00 2001 From: yumoqing Date: Thu, 28 Nov 2024 13:36:17 +0800 Subject: [PATCH 02/75] bugfix --- bricks/bricks.js | 3 +++ bricks/datarow.js | 6 +++++- 2 files changed, 8 insertions(+), 1 deletion(-) diff --git a/bricks/bricks.js b/bricks/bricks.js index ac9b146..7751e74 100644 --- a/bricks/bricks.js +++ b/bricks/bricks.js @@ -124,6 +124,9 @@ bricks.widgetBuild = async function(desc, widget, data){ var klassname = desc.widgettype; var base_url = widget.baseURI; while (klassname == 'urlwidget'){ + if (data){ + desc = bricks.apply_data(desc, data); + } let url = bricks.absurl(desc.options.url, widget); base_url = url; let method = desc.options.method || 'GET'; diff --git a/bricks/datarow.js b/bricks/datarow.js index 8bbd31b..4ac9f7d 100644 --- a/bricks/datarow.js +++ b/bricks/datarow.js @@ -35,7 +35,11 @@ bricks.DataRow = class extends bricks.HBox { if (header){ w = new bricks.BlankIcon({}); } else { - w = new bricks.UiCheck({name:this.checkField,value:this.user_data[this.checkField]}); + var v = 0 + if (this.user_data){ + v = this.user_data[this.checkField]; + } + w = new bricks.UiCheck({name:this.checkField,value:v}); w.bind('changed', this.get_check_state.bind(this)); } this.add_widget(w); From 8da00bcdc47481a64e3e8bb5a26a4a1b76ca39b4 Mon Sep 17 00:00:00 2001 From: yumoqing Date: Sun, 1 Dec 2024 15:23:13 +0800 Subject: [PATCH 03/75] bugfix --- bricks/css/bricks.css | 6 ++++++ bricks/llm.js | 1 + bricks/menu.js | 6 +++++- 3 files changed, 12 insertions(+), 1 deletion(-) diff --git a/bricks/css/bricks.css b/bricks/css/bricks.css index d4406de..2e29901 100755 --- a/bricks/css/bricks.css +++ b/bricks/css/bricks.css @@ -7,6 +7,10 @@ body { display: flex; } +pre { + overflow-x: auto; /* 允许内容超出容器显示 */ + background-color: #b5e5e5; +} * { box-sizing: border-box!important; } @@ -436,3 +440,5 @@ hr { .llm_title { background-color:#eeeeee; } + + diff --git a/bricks/llm.js b/bricks/llm.js index 4cab3d2..43aa7cf 100644 --- a/bricks/llm.js +++ b/bricks/llm.js @@ -118,6 +118,7 @@ bricks.ModelOutput = class extends bricks.HBox { this.run = null; var w = await bricks.widgetBuild(this.output_view, this.llmio, data); w.set_css('llm_msg'); + w.set_style('width', '100%'); this.filler.clear_widgets(); this.filler.add_widget(w); this.filler.add_widget(this.estimate_w); diff --git a/bricks/menu.js b/bricks/menu.js index f0a7d97..92876d9 100644 --- a/bricks/menu.js +++ b/bricks/menu.js @@ -55,13 +55,17 @@ bricks.Menu = class extends bricks.VBox { itw.add_widget(subw); itw.add_widget(w1); this.create_children(w1, item.items); - subw.bind('click', w1.toggle_hide.bind(w1)); + subw.bind('click', this.items_toggle_hide.bind(this, w1)); } else { subw.bind('click', this.regen_menuitem_event.bind(this, item)) w.add_widget(subw); } } } + items_toggle_hide(w, event){ + w.toggle_hide(); + event.stopPropagation(); + } create_menuitem(item){ var w = new bricks.HBox({cheight:this.item_cheight||2}); var iw, tw; From 680fcfd4349f294e71f29f9f4289b5c61bbdd8ab Mon Sep 17 00:00:00 2001 From: yumoqing Date: Mon, 2 Dec 2024 20:25:55 +0800 Subject: [PATCH 04/75] bugfix --- bricks/build.sh | 2 +- bricks/css/bricks.css | 1 + bricks/pdfviewer.js | 68 +++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 70 insertions(+), 1 deletion(-) create mode 100644 bricks/pdfviewer.js diff --git a/bricks/build.sh b/bricks/build.sh index 78f050a..cd56490 100755 --- a/bricks/build.sh +++ b/bricks/build.sh @@ -8,7 +8,7 @@ SOURCES=" page_data_loader.js factory.js uitypesdef.js utils.js uitype.js \ floaticonbar.js miniform.js wterm.js dynamicaccordion.js \ binstreaming.js streaming_audio.js vadtext.js rtc.js \ llm_dialog.js llm.js websocket.js datarow.js tabular.js \ - line.js pie.js bar.js gobang.js period.js " + line.js pie.js bar.js gobang.js period.js pdfviewer.js " echo ${SOURCES} cat ${SOURCES} > ../dist/bricks.js # uglifyjs --compress --mangle -- ../dist/bricks.js > ../dist/bricks.min.js diff --git a/bricks/css/bricks.css b/bricks/css/bricks.css index 2e29901..d71f1d8 100755 --- a/bricks/css/bricks.css +++ b/bricks/css/bricks.css @@ -418,6 +418,7 @@ hr { margin-left: 5px; margin-right: auto; margin-bottom: 10px; + padding: 3px; background-color:#fefedd; border-top-left-radius: 10px; border-top-right-radius: 0; diff --git a/bricks/pdfviewer.js b/bricks/pdfviewer.js new file mode 100644 index 0000000..b7b80d0 --- /dev/null +++ b/bricks/pdfviewer.js @@ -0,0 +1,68 @@ +/* +https://mozilla.github.io/pdf.js download pdf from here +or add follow line to html file body tag + +*/ + +var bricks = window.bricks || {} + +bricks.PDFviewer = class extends bricks.VBox { + /* + url: + */ + constructor(opts){ + super(opts); + this.curpage = null; + this.pdf = null; + bricks.app.bind('keydown', this.key_action.bind(this)); + schedule_once(this.renderPage(1), 0.2); + } + key_action(e){ + if (!this.curpage) return; + switch(e.key){ + case 'Enter': + case ' ': + case 'ArrowDown': + this.renderPage(this.curpage+1); + break; + case 'ArrowUp': + this.renderPage(this.curpage-1); + break; + } + } + async renderPage(pn){ + if (pn < 1) return; + this.curpage = pn; + if (!this.pdf) { + pdfjsLib.getDocument(this.url).promise.then(function(pdf){ + this.pdf = pdf; + pdf.getPage(pn).promise.then(function(page){ + this._render_page(page); + }); + }); + return; + } + this.pdf.getPage(pn).promise.then(function(page){ + this._render_page(page); + }); + } + _render_page(page){ + var scale = 1.5; + var viewport = page.getViewport({scale: scale}); + var canvasElement = document.createElement('canvas'); + var context = canvasElement.getContext('2d'); + + canvasElement.height = viewport.height; + canvasElement.width = viewport.width; + + var renderContext = { + canvasContext: context, + viewport: viewport + }; + page.render(renderContext); + this.dom_element.innerHTML = ''; + this.dom_element.appendChild(canvasElement); + } +} + +bricks.Factory.register('PDFviewer', bricks.PDFviewer); From 1e6acc19ca6deb3f7c5032d18ddb80fe35bb2169 Mon Sep 17 00:00:00 2001 From: yumoqing Date: Wed, 4 Dec 2024 18:51:05 +0800 Subject: [PATCH 05/75] bugfix --- bricks/build.sh | 4 ++-- bricks/header.tmpl | 3 +++ bricks/input.js | 5 ++++- bricks/jsoncall.js | 9 +++++++-- bricks/llm.js | 15 +++++++++++---- 5 files changed, 27 insertions(+), 9 deletions(-) diff --git a/bricks/build.sh b/bricks/build.sh index cd56490..81a9310 100755 --- a/bricks/build.sh +++ b/bricks/build.sh @@ -6,9 +6,9 @@ SOURCES=" page_data_loader.js factory.js uitypesdef.js utils.js uitype.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 \ floaticonbar.js miniform.js wterm.js dynamicaccordion.js \ - binstreaming.js streaming_audio.js vadtext.js rtc.js \ + binstreaming.js streaming_audio.js vadtext.js rtc.js docxviewer.js \ llm_dialog.js llm.js websocket.js datarow.js tabular.js \ - line.js pie.js bar.js gobang.js period.js pdfviewer.js " + line.js pie.js bar.js gobang.js period.js " echo ${SOURCES} cat ${SOURCES} > ../dist/bricks.js # uglifyjs --compress --mangle -- ../dist/bricks.js > ../dist/bricks.min.js diff --git a/bricks/header.tmpl b/bricks/header.tmpl index ba0a53d..2f8ee11 100644 --- a/bricks/header.tmpl +++ b/bricks/header.tmpl @@ -5,6 +5,7 @@ + @@ -15,7 +16,9 @@ + --> + diff --git a/bricks/input.js b/bricks/input.js index 8e959fd..1dd4fe9 100644 --- a/bricks/input.js +++ b/bricks/input.js @@ -393,6 +393,8 @@ bricks.UiImage =class extends bricks.VBox { if (this.imgw){ 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, width:'100%' @@ -404,7 +406,8 @@ bricks.UiImage =class extends bricks.VBox { getValue(){ var ret = {} if (this.imgw){ - ret[this.name] = this.imgw.base64() + // ret[this.name] = this.imgw.base64() + ret[this.name] = this.value; } else { ret[this.name] = null; } diff --git a/bricks/jsoncall.js b/bricks/jsoncall.js index d491553..21fc3ac 100644 --- a/bricks/jsoncall.js +++ b/bricks/jsoncall.js @@ -44,9 +44,9 @@ bricks.HttpText = class { }; bricks.extend(this.headers, headers); var width=0, height=0; - var is_mobile = 0 + var is_mobile = '0' if (bricks.is_mobile()){ - is_mobile = 1; + is_mobile = '1'; } if (bricks.app) { width = bricks.app.screenWidth(); @@ -187,6 +187,11 @@ bricks.HttpText = class { } } +bricks.HttpBin = class extends bricks.HttpText { + async get_result_data(resp){ + return await resp.blob() + } +} bricks.HttpResponse = class extends bricks.HttpText { async get_result_data(resp){ return resp; diff --git a/bricks/llm.js b/bricks/llm.js index 43aa7cf..a805165 100644 --- a/bricks/llm.js +++ b/bricks/llm.js @@ -185,23 +185,30 @@ bricks.LlmModel = class extends bricks.JsWidget { this.llmio.o_w.add_widget(mout); var fmt = this.opts.user_message_format || { role:'user', content:'${prompt}'}; var umsg = bricks.apply_data(fmt, data); - var d = data; + var d = {}; this.messages.push(umsg); - d = {}; - d.messages = this.messages; d.model = this.opts.model; d.modelinstanceid = this.opts.modelinstanceid; d.modeltypeid = this.opts.modeltypeid; - console.log('upload data=', d, this.options); if (this.response_mode == 'stream' || this.response_mode == 'async') { + d = {}; + d.messages = this.messages; + d.model = this.opts.model; + d.modelinstanceid = this.opts.modelinstanceid; + d.modeltypeid = this.opts.modeltypeid; 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 { + d = data + d.model = this.opts.model; + d.modelinstanceid = this.opts.modelinstanceid; + d.modeltypeid = this.opts.modeltypeid; 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(); From 91e24f567f12ec46421658b8f48ed70387f3b745 Mon Sep 17 00:00:00 2001 From: yumoqing Date: Thu, 5 Dec 2024 18:20:28 +0800 Subject: [PATCH 06/75] bugfix --- bricks/audio.js | 4 +++- bricks/bricks.js | 25 ++++++++++++++++++++++--- bricks/build.sh | 2 +- bricks/form.js | 16 ++++++++++++++-- bricks/header.tmpl | 4 +++- bricks/input.js | 10 +++++++++- bricks/jsoncall.js | 16 ++++++++-------- bricks/pdfviewer.js | 2 +- 8 files changed, 61 insertions(+), 18 deletions(-) diff --git a/bricks/audio.js b/bricks/audio.js index 2f06e57..a93774c 100644 --- a/bricks/audio.js +++ b/bricks/audio.js @@ -105,7 +105,9 @@ bricks.AudioRecorder = class extends bricks.HBox { this.add_widget(this.rec_btn); this.add_widget(this.rec_time); this.recordData = null; - this.bind('record_ended', this.upload.bind(this)); + if (this.upload_url){ + this.bind('record_ended', this.upload.bind(this)); + } } rec_btn_pressed(){ bricks.debug(this.rec_btn.url, ':url:', this.start_icon, this.stop_icon); diff --git a/bricks/bricks.js b/bricks/bricks.js index 7751e74..798dc0d 100644 --- a/bricks/bricks.js +++ b/bricks/bricks.js @@ -214,7 +214,7 @@ bricks.buildEventHandler = async function(w, desc, event){ return null } var rtdata = {}; - + desc.event_params = event.params || {} ; if (desc.rtdata) rtdata = desc.rtdata; else if (desc.datawidget){ var data_desc = { @@ -225,9 +225,15 @@ bricks.buildEventHandler = async function(w, desc, event){ } rtdata = await bricks.getRealtimeData(w, data_desc); } + /* if (typeof event.params == typeof {}){ rtdata = bricks.extend(rtdata, event.params); + } else if (event.params instanceof FormData){ + for ( const [key, value] of Object.entries(rtdata)){ + params.append(key, value); + } } + */ switch (desc.actiontype){ case 'urlwidget': return bricks.buildUrlwidgetHandler(w, target, rtdata, desc); @@ -312,8 +318,21 @@ bricks.buildUrlwidgetHandler = function(w, target, rtdata, desc){ } var options = objcopy(desc.options||{}); var params = options.params || {}; - options = bricks.apply_data(options, rtdata); - options.params = bricks.extend(params, rtdata); + if (desc.event_params instanceof FormData){ + var params = desc.event_params; + for ( const [key, value] of Object.entries(rtdata)){ + params.append(key, value); + } + options = bricks.apply_data(options, rtdata); + for ( const [key, value] of Object.entries(options.params||{})){ + params.append(key, value); + } + options.params = params; + } else { + rtdata = bricks.extend(rtdata, desc.event_params); + options = bricks.apply_data(options, rtdata); + options.params = bricks.extend(params, rtdata); + } var opts = { "widgettype":"urlwidget", diff --git a/bricks/build.sh b/bricks/build.sh index 81a9310..84bc196 100755 --- a/bricks/build.sh +++ b/bricks/build.sh @@ -8,7 +8,7 @@ SOURCES=" page_data_loader.js factory.js uitypesdef.js utils.js uitype.js \ floaticonbar.js miniform.js wterm.js dynamicaccordion.js \ binstreaming.js streaming_audio.js vadtext.js rtc.js docxviewer.js \ llm_dialog.js llm.js websocket.js datarow.js tabular.js \ - line.js pie.js bar.js gobang.js period.js " + line.js pie.js bar.js gobang.js period.js pdfviewer.js" echo ${SOURCES} cat ${SOURCES} > ../dist/bricks.js # uglifyjs --compress --mangle -- ../dist/bricks.js > ../dist/bricks.min.js diff --git a/bricks/form.js b/bricks/form.js index d245c94..f8782d4 100644 --- a/bricks/form.js +++ b/bricks/form.js @@ -177,6 +177,12 @@ bricks.FormBase = class extends bricks.Layout { } } getValue(){ + if (this.data) { + var ret = this.data; + this.data = null; + return ret; + } + return this.get_formdata(); var data = {}; for (var name in this.name_inputs){ if (! this.name_inputs.hasOwnProperty(name)){ @@ -204,11 +210,12 @@ bricks.FormBase = class extends bricks.Layout { var w = this.name_inputs[name]; var d = w.getValue(); if (w.required && ( d[name] == '' || d[name] === null)){ - bricks.debug('data=', data, 'd=', d); new bricks.Error({title:'Requirement', message:'required field must input"' + w.label + '"'}) w.focus(); return; } + w.set_formdata(data); + /* if (bricks.need_formdata_fields.includes(w.uitype)){ var files = w.get_files(); for (var i=0;i --> - + + + diff --git a/bricks/input.js b/bricks/input.js index 1dd4fe9..ff5fbc0 100644 --- a/bricks/input.js +++ b/bricks/input.js @@ -17,6 +17,9 @@ bricks.UiType =class extends bricks.Layout { } return o; } + set_formdata(formdata){ + formdata.append(this.name, this.resultValue()); + } resultValue(){ return this.value; } @@ -71,7 +74,8 @@ bricks.UiAudioText = class extends bricks.UiType { this.text_w.setValue(''); } getValue(){ - return this.text_w.getValue(); + this.value = this.text_w.getValue(); + return this.value; } setValue(v){ this.text_w.setValue(v); @@ -265,6 +269,7 @@ bricks.UiFloat =class extends bricks.UiInt { this.dom_element.step = step; } resultValue(){ + super.resultValue(); return parseFloat(this.value); } setValue(v){ @@ -403,6 +408,9 @@ bricks.UiImage =class extends bricks.VBox { }; reader.readAsDataURL(file); } + set_formdata(formdata){ + formdata.append(this.name, this.value); + } getValue(){ var ret = {} if (this.imgw){ diff --git a/bricks/jsoncall.js b/bricks/jsoncall.js index 21fc3ac..ac27bc3 100644 --- a/bricks/jsoncall.js +++ b/bricks/jsoncall.js @@ -77,8 +77,6 @@ bricks.HttpText = class { return await resp.text(); } add_own_params(params){ - if (! params) - params = {}; var session = bricks.app.get_session(); if (params instanceof FormData){ for ( const [key, value] of Object.entries(this.params)){ @@ -89,6 +87,8 @@ bricks.HttpText = class { } return params; } + if (! params) + params = {}; var p = bricks.extend({}, this.params); p = bricks.extend(p, params); if (session){ @@ -109,13 +109,13 @@ bricks.HttpText = class { var _params = { method:method } - // _params.headers = headers; - if (method == 'GET' || method == 'HEAD') { - let pstr = url_params(data); - url = url + '?' + pstr; + if (data instanceof FormData){ + method = 'POST'; + _params.body = data; } else { - if (data instanceof FormData){ - _params.body = data; + if (method == 'GET' || method == 'HEAD') { + let pstr = url_params(data); + url = url + '?' + pstr; } else { _params.body = JSON.stringify(data); } diff --git a/bricks/pdfviewer.js b/bricks/pdfviewer.js index b7b80d0..d4268c1 100644 --- a/bricks/pdfviewer.js +++ b/bricks/pdfviewer.js @@ -15,7 +15,7 @@ bricks.PDFviewer = class extends bricks.VBox { this.curpage = null; this.pdf = null; bricks.app.bind('keydown', this.key_action.bind(this)); - schedule_once(this.renderPage(1), 0.2); + schedule_once(this.renderPage(1), 1); } key_action(e){ if (!this.curpage) return; From 3caea6bc6edaa0cb404de010899379046cce8c04 Mon Sep 17 00:00:00 2001 From: yumoqing Date: Fri, 6 Dec 2024 11:57:27 +0800 Subject: [PATCH 07/75] bugfix --- bricks/input.js | 5 +++-- bricks/llm.js | 47 ++++++++++++++++++++++++++++++++++------------- 2 files changed, 37 insertions(+), 15 deletions(-) diff --git a/bricks/input.js b/bricks/input.js index ff5fbc0..05b00f7 100644 --- a/bricks/input.js +++ b/bricks/input.js @@ -73,11 +73,12 @@ bricks.UiAudioText = class extends bricks.UiType { clear_text(){ this.text_w.setValue(''); } - getValue(){ - this.value = this.text_w.getValue(); + resultValue(){ + this.value = this.text_w.resultValue(); return this.value; } setValue(v){ + this.value = v; this.text_w.setValue(v); } set_result_text(event){ diff --git a/bricks/llm.js b/bricks/llm.js index a805165..edbd75d 100644 --- a/bricks/llm.js +++ b/bricks/llm.js @@ -1,5 +1,17 @@ bricks = window.bricks || {} +var inputdata2dic = function(data){ + if (! data instanceof FormData) return data; + var d = {} + for (let k of data.keys()){ + var x = data.get(k); + x = x instanceof File? x:x.toString(); + y = Object.prototype.toString.call(x) + d[k] = x; + console.log('x=', x, 'k=', k, 'x type=', y); + } + return d; +} bricks.LlmMsgAudio = class extends bricks.UpStreaming { constructor(opts){ super(opts); @@ -171,6 +183,19 @@ bricks.LlmModel = class extends bricks.JsWidget { } show_setup_panel(event){ + } + inputdata2uploaddata(data){ + var d = data; + if (data instanceof FormData){ + d.append('model', this.opts.model) + d.append('modelinstanceid', this.opts.modelinstanceid) + d.append('modeltypeid', this.opts.modeltypeid) + } else { + d.model = this.opts.model; + d.modelinstanceid = this.opts.modelinstanceid; + d.modeltypeid = this.opts.modeltypeid; + } + return d; } async model_inputed(data){ if (!opts.use_session){ @@ -184,27 +209,20 @@ bricks.LlmModel = class extends bricks.JsWidget { output_view:this.opts.output_view}); this.llmio.o_w.add_widget(mout); var fmt = this.opts.user_message_format || { role:'user', content:'${prompt}'}; - var umsg = bricks.apply_data(fmt, data); + var umsg = bricks.apply_data(fmt, inputdata2dic(data)); var d = {}; this.messages.push(umsg); d.model = this.opts.model; d.modelinstanceid = this.opts.modelinstanceid; d.modeltypeid = this.opts.modeltypeid; if (this.response_mode == 'stream' || this.response_mode == 'async') { - d = {}; - d.messages = this.messages; - d.model = this.opts.model; - d.modelinstanceid = this.opts.modelinstanceid; - d.modeltypeid = this.opts.modeltypeid; + var d = this.inputdata2uploaddata(data); 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 { - d = data - d.model = this.opts.model; - d.modelinstanceid = this.opts.modelinstanceid; - d.modeltypeid = this.opts.modeltypeid; + var d = this.inputdata2uploaddata(data); var hj = new bricks.HttpJson() var resp = await hj.post(this.opts.url, {params:d}); if (this.response_mode == 'sync'){ @@ -302,8 +320,6 @@ bricks.LlmIO = class extends bricks.VBox { } async handle_input(event){ var params = event.params; - if (params.prompt) - params.prompt = bricks.escapeSpecialChars(params.prompt); await this.show_input(params); for(var i=0;i Date: Fri, 6 Dec 2024 17:23:28 +0800 Subject: [PATCH 08/75] bugfix --- bricks/bricks.js | 1 + bricks/jsoncall.js | 11 +++++++++-- 2 files changed, 10 insertions(+), 2 deletions(-) diff --git a/bricks/bricks.js b/bricks/bricks.js index 798dc0d..5f2b6a6 100644 --- a/bricks/bricks.js +++ b/bricks/bricks.js @@ -328,6 +328,7 @@ bricks.buildUrlwidgetHandler = function(w, target, rtdata, desc){ params.append(key, value); } options.params = params; + options.method = "POST"; } else { rtdata = bricks.extend(rtdata, desc.event_params); options = bricks.apply_data(options, rtdata); diff --git a/bricks/jsoncall.js b/bricks/jsoncall.js index ac27bc3..f5f8155 100644 --- a/bricks/jsoncall.js +++ b/bricks/jsoncall.js @@ -187,11 +187,18 @@ bricks.HttpText = class { } } -bricks.HttpBin = class extends bricks.HttpText { +bricks.HttpArrayBuffer = class extends bricks.HttpText { async get_result_data(resp){ - return await resp.blob() + return await resp.arrayBuffer(); } } + +bricks.HttpBin = class extends bricks.HttpText { + async get_result_data(resp){ + return await resp.blob(); + } +} + bricks.HttpResponse = class extends bricks.HttpText { async get_result_data(resp){ return resp; From b7edc34bddfb88172f906dfc143c2e5a1dfaff30 Mon Sep 17 00:00:00 2001 From: yumoqing Date: Fri, 6 Dec 2024 18:41:25 +0800 Subject: [PATCH 09/75] bugfix --- bricks/build.sh | 2 +- bricks/pdfviewer.js | 68 --------------------------------------------- 2 files changed, 1 insertion(+), 69 deletions(-) delete mode 100644 bricks/pdfviewer.js diff --git a/bricks/build.sh b/bricks/build.sh index 84bc196..81a9310 100755 --- a/bricks/build.sh +++ b/bricks/build.sh @@ -8,7 +8,7 @@ SOURCES=" page_data_loader.js factory.js uitypesdef.js utils.js uitype.js \ floaticonbar.js miniform.js wterm.js dynamicaccordion.js \ binstreaming.js streaming_audio.js vadtext.js rtc.js docxviewer.js \ llm_dialog.js llm.js websocket.js datarow.js tabular.js \ - line.js pie.js bar.js gobang.js period.js pdfviewer.js" + line.js pie.js bar.js gobang.js period.js " echo ${SOURCES} cat ${SOURCES} > ../dist/bricks.js # uglifyjs --compress --mangle -- ../dist/bricks.js > ../dist/bricks.min.js diff --git a/bricks/pdfviewer.js b/bricks/pdfviewer.js deleted file mode 100644 index d4268c1..0000000 --- a/bricks/pdfviewer.js +++ /dev/null @@ -1,68 +0,0 @@ -/* -https://mozilla.github.io/pdf.js download pdf from here -or add follow line to html file body tag - -*/ - -var bricks = window.bricks || {} - -bricks.PDFviewer = class extends bricks.VBox { - /* - url: - */ - constructor(opts){ - super(opts); - this.curpage = null; - this.pdf = null; - bricks.app.bind('keydown', this.key_action.bind(this)); - schedule_once(this.renderPage(1), 1); - } - key_action(e){ - if (!this.curpage) return; - switch(e.key){ - case 'Enter': - case ' ': - case 'ArrowDown': - this.renderPage(this.curpage+1); - break; - case 'ArrowUp': - this.renderPage(this.curpage-1); - break; - } - } - async renderPage(pn){ - if (pn < 1) return; - this.curpage = pn; - if (!this.pdf) { - pdfjsLib.getDocument(this.url).promise.then(function(pdf){ - this.pdf = pdf; - pdf.getPage(pn).promise.then(function(page){ - this._render_page(page); - }); - }); - return; - } - this.pdf.getPage(pn).promise.then(function(page){ - this._render_page(page); - }); - } - _render_page(page){ - var scale = 1.5; - var viewport = page.getViewport({scale: scale}); - var canvasElement = document.createElement('canvas'); - var context = canvasElement.getContext('2d'); - - canvasElement.height = viewport.height; - canvasElement.width = viewport.width; - - var renderContext = { - canvasContext: context, - viewport: viewport - }; - page.render(renderContext); - this.dom_element.innerHTML = ''; - this.dom_element.appendChild(canvasElement); - } -} - -bricks.Factory.register('PDFviewer', bricks.PDFviewer); From 7fca12127fe7f0e87f636ecc21273f8dcdf7b683 Mon Sep 17 00:00:00 2001 From: yumoqing Date: Fri, 6 Dec 2024 23:46:51 +0800 Subject: [PATCH 10/75] bugfix --- bricks/bricks.js | 9 +++++++++ bricks/llm.js | 12 ------------ bricks/utils.js | 12 ++++++++++++ 3 files changed, 21 insertions(+), 12 deletions(-) diff --git a/bricks/bricks.js b/bricks/bricks.js index 5f2b6a6..54fa022 100644 --- a/bricks/bricks.js +++ b/bricks/bricks.js @@ -300,6 +300,7 @@ var _buildWidget = async function(from_widget, target, mode, options){ } bricks.buildUrlwidgetHandler = function(w, target, rtdata, desc){ + /* var f = async function(target, mode, options){ bricks.debug('target=', target, 'mode=', mode, 'options=', options); var w = await (bricks.widgetBuild(options, w)); @@ -316,6 +317,7 @@ bricks.buildUrlwidgetHandler = function(w, target, rtdata, desc){ target.add_widget(w); } } + */ var options = objcopy(desc.options||{}); var params = options.params || {}; if (desc.event_params instanceof FormData){ @@ -342,6 +344,7 @@ bricks.buildUrlwidgetHandler = function(w, target, rtdata, desc){ return _buildWidget.bind(w, target, target, desc.mode || 'replace', opts); } bricks.buildBricksHandler = function(w, target, rtdata, desc){ + /* var f = async function(target, mode, options){ bricks.debug('target=', target, 'mode=', mode, 'options=', options); var w = await (bricks.widgetBuild(options, wa)); @@ -354,7 +357,9 @@ bricks.buildBricksHandler = function(w, target, rtdata, desc){ } target.add_widget(w); } + */ var options = objcopy(desc.options||{}); + rtdata = bricks.extend(rtdata, inputdata2dic(desc.event_params)); options = bricks.apply_data(options, rtdata); return _buildWidget.bind(w, target, target, desc.mode || 'replace', options); } @@ -371,6 +376,7 @@ bricks.buildRegisterFunctionHandler = function(w, target, rtdata, desc){ if (rtdata){ bricks.extend(params, rtdata); } + bricks.extend(params, inputdata2dic(desc.event_params)); params = bricks.apply_data(params, rtdata); return f.bind(target, params); } @@ -383,6 +389,7 @@ bricks.buildMethodHandler = function(w, target, rtdata, desc){ var params = {}; bricks.extend(params, desc.params) bricks.extend(params, rtdata); + bricks.extend(params, inputdata2dic(desc.event_params)); params = bricks.apply_data(params, rtdata); return f.bind(target, params); } @@ -390,6 +397,7 @@ bricks.buildScriptHandler = function(w, target, rtdata, desc){ var params = {}; bricks.extend(params, desc.params) bricks.extend(params, rtdata); + bricks.extend(params, inputdata2dic(desc.event_params)); params = bricks.apply_data(params, rtdata); var AsyncFunction = Object.getPrototypeOf(async function(){}).constructor; var f = new AsyncFunction('params', 'event', desc.script); @@ -403,6 +411,7 @@ bricks.buildDispatchEventHandler = function(w, target, rtdata, desc){ var params = {}; bricks.extend(params, desc.params) bricks.extend(params, rtdata); + bricks.extend(params, inputdata2dic(desc.event_params)); params = bricks.apply_data(params, rtdata); return f.bind(target, desc.dispatch_event, params); } diff --git a/bricks/llm.js b/bricks/llm.js index edbd75d..3d1864b 100644 --- a/bricks/llm.js +++ b/bricks/llm.js @@ -1,17 +1,5 @@ bricks = window.bricks || {} -var inputdata2dic = function(data){ - if (! data instanceof FormData) return data; - var d = {} - for (let k of data.keys()){ - var x = data.get(k); - x = x instanceof File? x:x.toString(); - y = Object.prototype.toString.call(x) - d[k] = x; - console.log('x=', x, 'k=', k, 'x type=', y); - } - return d; -} bricks.LlmMsgAudio = class extends bricks.UpStreaming { constructor(opts){ super(opts); diff --git a/bricks/utils.js b/bricks/utils.js index d11481c..283a235 100644 --- a/bricks/utils.js +++ b/bricks/utils.js @@ -1,5 +1,17 @@ var bricks = window.bricks || {}; bricks.bug = false; +var inputdata2dic = function(data){ + try { + var d = {} + for (let k of data.keys()){ + var x = data.get(k); + d[k] = x; + } + return d; + } catch (e){ + return data; + } +} bricks.delete_null_values = function(obj) { for (let key in obj) { if (obj[key] === null) { From b479461741122b00b8ed5b8988fbc0d90b286836 Mon Sep 17 00:00:00 2001 From: yumoqing Date: Wed, 11 Dec 2024 10:36:07 +0800 Subject: [PATCH 11/75] bugfix --- bricks/cols.js | 8 +- bricks/css/bricks.css | 4 + bricks/dynamiccolumn.js | 1 + bricks/llm.js | 170 +++++++++++++++++++++++++++++++++------- bricks/popup.js | 101 ++++++++++++------------ bricks/utils.js | 3 + 6 files changed, 205 insertions(+), 82 deletions(-) diff --git a/bricks/cols.js b/bricks/cols.js index a7c3544..e9bd64f 100644 --- a/bricks/cols.js +++ b/bricks/cols.js @@ -55,6 +55,7 @@ bricks.Cols = class extends bricks.VBox { } async handle_click(rw, event){ + event.stopPropagation(); var orev = null; if (this.select_record){ orev = this.select_record; @@ -64,6 +65,8 @@ bricks.Cols = class extends bricks.VBox { } this.select_record = rw; this.select_record.set_css('selected_record'); + console.log('record data=', rw.user_data); + this.dispatch('record_click', rw.user_data); } async dataHandle(d){ var data = d.rows; @@ -77,6 +80,7 @@ bricks.Cols = class extends bricks.VBox { for (var i=0;i{ - if (this.textvoice){ - m.textvoice = true; - m.tts_url = this.tts_url; - } - var lm = new bricks.LlmModel(this, m); - this.llmmodels.push(lm); - var tw = lm.render_title(); - this.title_w.add_widget(tw); + this.show_added_model(m); }); - this.build_input(); + } + show_added_model(m){ + if (this.textvoice){ + m.textvoice = true; + m.tts_url = this.tts_url; + } + var lm = new bricks.LlmModel(this, m); + this.llmmodels.push(lm); + var tw = lm.render_title(); + this.title_w.add_widget(tw); + } + async open_search_models(event){ + event.preventDefault(); + event.stopPropagation(); + var rect = this.showRectage(); + var opts = { + title:"select model", + icon:bricks_resource('imgs/search.png'), + auto_destroy:true, + auto_open:true, + auto_dismiss:false, + movable:true, + top:rect.top + 'px', + left:rect.left + 'px', + width: rect.right - rect.left + 'px', + height: rect.bottom - rect.top + 'px' + } + var w = new bricks.PopupWindow(opts); + var sopts = { + data_url:this.list_models_url, + data_params:{ + mii:this.models[0].modelinstanceid, + mti:this.models[0].modeltypeid + }, + data_method:'POST', + col_cwidth: 24, + record_view:{ + widgettype:"VBox", + options:{ + cheight:20, + css:"card" + }, + subwidgets:[ + { + widgettype:"Title4", + options:{ + text:"${name}" + } + }, + { + widgettype:"Filler", + options:{ + css:"scroll" + }, + subwidgets:[ + { + widgettype:"VBox", + options:{ + css:"subcard" + }, + subwidgets:[ + { + widgettype:"Text", + options:{ + text:"模型描述:${description}", + wrap:true + } + }, + { + widgettype:"Text", + options:{ + text:"启用日期:${enable_date}" + } + } + ] + } + ] + } + ] + } + }; + var cols = new bricks.Cols(sopts); + cols.bind('record_click', this.add_new_model.bind(this)); + cols.bind('record_click', w.dismiss.bind(w)); + w.add_widget(cols); + w.open(); + } + async add_new_model(event){ + event.preventDefault(); + event.stopPropagation(); + this.models.push(event.params); + this.show_added_model(event.params); + } + async open_input_widget(event){ + event.preventDefault(); + event.stopPropagation(); + var rect = this.showRectage(); + var opts = { + title:"input data", + icon:bricks_resource('imgs/input.png'), + auto_destroy:true, + auto_open:true, + auto_dismiss:false, + movable:true, + top:rect.top + 'px', + left:rect.left + 'px', + width: rect.right - rect.left + 'px', + height: rect.bottom - rect.top + 'px' + } + var w = new bricks.PopupWindow(opts); + var fopts = { + fields:this.input_fields + } + var fw = new bricks.Form(fopts); + fw.bind('submit', this.handle_input.bind(this)); + fw.bind('submit', w.destroy.bind(w)); + w.add_widget(fw); + w.open(); } async handle_input(event){ var params = event.params; @@ -320,9 +445,6 @@ bricks.LlmIO = class extends bricks.VBox { async show_input(params){ var box = new bricks.HBox({width:'100%'}); var data = inputdata2dic(params); - if (data.prompt){ - data.prompt = bricks.escapeSpecialChars(data.prompt); - } console.log('data=', data, 'input_view=', this.input_view); var w = await bricks.widgetBuild(this.input_view, this.o_w, data); w.set_css(this.msg_css||'user_msg'); @@ -333,14 +455,6 @@ bricks.LlmIO = class extends bricks.VBox { box.add_widget(img); this.o_w.add_widget(box); } - build_input(){ - var fopts = { - fields:this.input_fields - }; - var fw = new bricks.InlineForm(fopts); - fw.bind('submit', this.handle_input.bind(this)); - this.i_w.add_widget(fw); - } } bricks.Factory.register('LlmIO', bricks.LlmIO); diff --git a/bricks/popup.js b/bricks/popup.js index ad69950..c1a28ac 100644 --- a/bricks/popup.js +++ b/bricks/popup.js @@ -10,8 +10,10 @@ bricks.Popup = class extends bricks.VBox { auto_dismiss:boolean auto_destroy:boolean movable:boolean + dismiss_event: resizable:boolean modal:boolean + content:{} */ constructor(opts){ super(opts); @@ -21,11 +23,10 @@ bricks.Popup = class extends bricks.VBox { this.opened = false; this.set_css('popup'); this.bring_to_top(); - this.moving_w = this; - this.content_box = new bricks.VBox({width:'100%', height:'100%'}); - this.content_box.set_style('display', 'flex'); - this.content_box.set_style('overflow', 'auto'); + this.content_box = new bricks.VBox({height:'100%',width:'100%'}); super.add_widget(this.content_box); + this.content_w = this.content_box; + this.moving_w = this; if (this.auto_dismiss){ bricks.Body.bind('click', this.click_outside.bind(this)); } @@ -41,6 +42,22 @@ bricks.Popup = class extends bricks.VBox { this.set_style('display', 'none'); bricks.Body.add_widget(this); this.bind('click', this.bring_to_top.bind(this)); + if (this.auto_open){ + this.open(); + } + if (this.content){ + this.bind('opened', this.load_content.bind(this)) + } + } + async load_content(){ + var w = bricks.widgetBuild(this.content, this); + if (w){ + if (this.content.dismiss_event){ + w.bind(this.content.dismiss_event, this.distroy.bind(this)); + } + this.content_w.clear_widgets(); + this.content_w.add_widget(w); + } } bring_to_top(){ if (this == bricks.app.toppopup){ @@ -50,6 +67,7 @@ bricks.Popup = class extends bricks.VBox { bricks.app.toppopup.set_css('toppopup', true); this.zindex = bricks.app.new_zindex(); this.set_style('zIndex', this.zindex); + console.log('this.zindex=', this.zindex, 'app.zindex=', bricks.app.zindex); this.set_css('toppopup'); bricks.app.toppopup = this; } @@ -249,20 +267,6 @@ bricks.Popup = class extends bricks.VBox { this.dismiss(); } } - add_widget(w, index){ - this.content_box.add_widget(w, index); - if (this.auto_open){ - this.open(); - } else { - // console.log('auto_open is ', this.auto_open, ' so not auto open it', this.opts, w); - } - } - remove_widget(w){ - this.content_box.remove_widget(w); - } - clear_widgets(){ - this.content_box.clear_widgets(); - } open(){ var rect, w, h; if (this.opened) { @@ -291,7 +295,7 @@ bricks.Popup = class extends bricks.VBox { if (this.opts.modal && this.opts.widget){ this.target_w.disabled(true); } - this.content_box.disabled(false); + this.bring_to_top(); } dismiss(){ if (! this.opened) return; @@ -319,6 +323,15 @@ bricks.Popup = class extends bricks.VBox { this.parent = null; } } + add_widget(w, i){ + return this.content_box.add_widget(w, i); + } + remove_widget(w){ + return this.content_box.remove_widget(w); + } + clear_widgets(){ + return this.content_box.clear_widgets(); + } } bricks.PopupWindow = class extends bricks.Popup { @@ -333,33 +346,24 @@ bricks.PopupWindow = class extends bricks.Popup { constructor(opts){ opts.moviable = true; opts.resizable = true; - opts.auto_open = true; + var ao = opts.auto_open; + opts.auto_open = false opts.auto_dismiss = false; opts.auto_destroy = false; super(opts); - this.title_bar = new bricks.HBox({cheight:1.5, width:'100%'}); - this.title_bar.set_css('titlebar') + this.auto_open = ao; + this.title_bar = new bricks.HBox({css:'titlebar', cheight:2, width:'100%'}); this.moving_w = this.title_bar; - this.parent_add_widget(this.title_bar); + super.add_widget(this.title_bar); this.build_title_bar(); var filler = new bricks.Filler({}); - this.parent_add_widget(filler) + super.add_widget(filler) this.content_w = new bricks.Layout({}); this.content_w.set_css('flexbox'); - this.auto_open = true; filler.add_widget(this.content_w); - // console.log(this.auto_open, 'opts=', opts); - } - async load_content(){ - var dic = { - "widgettype":"urlwidget", - "options":{ - "params":this.params, - "url":this.url - } + if (this.auto_open){ + this.open(); } - var w = bricks.widgetBuild(dic, bricks.Body); - this.add_widget(w); } build_title_bar(){ var icon = new bricks.Icon({ @@ -406,22 +410,6 @@ bricks.PopupWindow = class extends bricks.Popup { this.title_w.set_text(txt); } } - parent_add_widget(w, index){ - var ao = this.autho_open; - this.auto_open = false; - super.add_widget(w, index); - this.auto_open = ao; - } - add_widget(w, index){ - // console.log('auto_open=', this.auto_open); - this.content_w.add_widget(w, index); - if (this.auto_open){ - this.open(); - } else { - this.open(); - // console.log('auto_open is false, not auto open'); - } - } open(){ var f = bricks.app.docks.find(o => { if (o == this){ @@ -439,6 +427,15 @@ bricks.PopupWindow = class extends bricks.Popup { } super.dismiss() } + add_widget(w, i){ + return this.content_w.add_widget(w, i); + } + remove_widget(w){ + return this.content_w.remove_widget(w); + } + clear_widgets(){ + return this.content_w.clear_widgets(); + } } bricks.Dock = class extends bricks.HBox { constructor(opts){ diff --git a/bricks/utils.js b/bricks/utils.js index 283a235..939f4e2 100644 --- a/bricks/utils.js +++ b/bricks/utils.js @@ -5,6 +5,9 @@ var inputdata2dic = function(data){ var d = {} for (let k of data.keys()){ var x = data.get(k); + if (k == 'prompt'){ + x = bricks.escapeSpecialChars(x); + } d[k] = x; } return d; From 3adab2a60e6775236643f77a8b15bf59e4729fca Mon Sep 17 00:00:00 2001 From: yumoqing Date: Wed, 11 Dec 2024 14:46:46 +0800 Subject: [PATCH 12/75] bugfix --- bricks/camera.js | 4 ++ bricks/docxviewer.js | 119 +++++++++++++++++++++++++++++++++++++++++++ bricks/input.js | 19 +++---- bricks/period.js | 99 +++++++++++++++++++++++++++++++++++ 4 files changed, 232 insertions(+), 9 deletions(-) create mode 100644 bricks/docxviewer.js create mode 100644 bricks/period.js diff --git a/bricks/camera.js b/bricks/camera.js index 90c09eb..c4820d1 100644 --- a/bricks/camera.js +++ b/bricks/camera.js @@ -52,6 +52,10 @@ bricks.Camera = class extends bricks.Popup { this.task = schedule_once(this.show_picture.bind(this), this.task_period); } take_picture(){ + if (this.task){ + task.cancel(); + } + this.task = null; var d = this.imgw.base64(); this.dispatch('shot', d); // Create a blob from the canvas data URL diff --git a/bricks/docxviewer.js b/bricks/docxviewer.js new file mode 100644 index 0000000..d990187 --- /dev/null +++ b/bricks/docxviewer.js @@ -0,0 +1,119 @@ +/* need mammoth module + +*/ +var bricks = window.bricks || {}; + +bricks.DOCXviewer = class extends bricks.VBox { + /* + url: + */ + constructor(opts){ + super(opts); + this.bind('on_parent', this.set_url.bind(this)); + // schedule_once(this.set_url.bind(this, this.url), 0.2); + } + async set_url(url){ + var container = this.dom_element + var hab = new bricks.HttpArrayBuffer(); + var ab = await hab.get(this.url); + var result = await mammoth.convertToHtml({ arrayBuffer: ab }); + container.innerHTML = result.value; + } +} + +function extractBodyContent(htmlString) { + // 正则表达式匹配和之间的内容 + const regex = /]*>([\s\S]*?)<\/body>/i; + const matches = htmlString.match(regex); + return matches ? matches[1] : null; // 如果匹配到,返回匹配的内容,否则返回null +} + +bricks.EXCELviewer = class extends bricks.VBox { + constructor(opts){ + opts.height = "100%", + super(opts); + this.sheets_w = new bricks.HBox({cheight:3, width:'100%'}); + this.sheets_w.set_css('scroll'); + this.cur_sheetname = null; + this.container = new bricks.Filler({}); + this.add_widget(this.container); + this.add_widget(this.sheets_w); + this.bind('on_parent', this.set_url.bind(this)); + } + async set_url(url){ + this.sheets_w.clear_widgets(); + var hab = new bricks.HttpArrayBuffer(); + var ab = await hab.get(this.url); + const data = new Uint8Array(ab); + this.workbook = XLSX.read(data, {type: 'array'}); + this.workbook.SheetNames.forEach((sheetname, index) => { + var w = new bricks.Text({text:sheetname, wrap:false}); + w.set_css('clickable'); + w.set_style('padding', '10px'); + w.bind('click', this.show_sheet_by_name.bind(this, sheetname, w)); + this.sheets_w.add_widget(w); + if (index==0){ + this.show_sheet_by_name(this.workbook.SheetNames[0], w); + } + }); + } + show_sheet_by_name(sheetname, tw){ + if (this.cur_sheetname == sheetname) return; + this.sheets_w.children.forEach(c => c.set_css('selected', true)); + tw.set_css('selected'); + const x = new bricks.VScrollPanel({width: '100%', height: '100%'}); + const sheet = this.workbook.Sheets[sheetname]; + // const html = extractBodyContent(XLSX.utils.sheet_to_html(sheet)); + const html = XLSX.utils.sheet_to_html(sheet); + x.dom_element.innerHTML = html; + this.container.clear_widgets(); + this.container.add_widget(x); + this.cur_sheetname = sheetname; + } +} + +bricks.PDFviewer = class extends bricks.VBox { + /* + url: + */ + constructor(opts){ + opts.width = '100%'; + super(opts); + this.bind('on_parent', this.set_url.bind(this)); + } + async set_url(url){ + var container = this.dom_element + var hab = new bricks.HttpArrayBuffer(); + var ab = await hab.get(this.url); + const task = pdfjsLib.getDocument({ data: ab }); + task.promise.then((pdf) => { + this.pdf = pdf; + for (let i = 1; i <= this.pdf.numPages; i++) { + this.pdf.getPage(i).then((page) => { + this.add_page_content(page); + }); + } + }).catch((err) => { + console.log('error'); + }) + } + add_page_content(page){ + const scale = 1.5; + const viewport = page.getViewport({ scale }); + const canvas = document.createElement('canvas'); + const context = canvas.getContext('2d'); + canvas.height = viewport.height; + canvas.width = viewport.width; + page.render({ canvasContext: context, viewport }); + var w = new bricks.JsWidget(); + w.dom_element.appendChild(canvas); + this.add_widget(w); + if (i < this.pdf.numPages){ + w = new bricks.Splitter(); + this.add_widget(w) + } + } +} +bricks.Factory.register('DOCXviewer', bricks.DOCXviewer); +bricks.Factory.register('EXCELviewer', bricks.EXCELviewer); +bricks.Factory.register('PDFviewer', bricks.PDFviewer); diff --git a/bricks/input.js b/bricks/input.js index 05b00f7..2cbf42e 100644 --- a/bricks/input.js +++ b/bricks/input.js @@ -372,16 +372,17 @@ bricks.UiImage =class extends bricks.VBox { "height":"90%", "width":"90%" }); - camera.bind('shot', function(d){ - if (this.imgw){ - this.remove_widget(this.imgw); - } - this.imgw = new bricks.Image({ - url:d, - width:'100%' - }); - this.add_widget(this.imgw); + camera.bind('shot', this.accept_photo.bind(this)); + } + accept_photo(url){ + if (this.imgw){ + this.remove_widget(this.imgw); + } + this.imgw = new bricks.Image({ + url:url, + width:'100%' }); + this.add_widget(this.imgw); } handleFileSelect(event){ const file = event.target.files[0]; diff --git a/bricks/period.js b/bricks/period.js new file mode 100644 index 0000000..3c00802 --- /dev/null +++ b/bricks/period.js @@ -0,0 +1,99 @@ +var bricks = window.bricks || {}; +bricks.str2date = function(sdate){ + let [year, month, day] = sdate.split("-"); + var dateObj = new Date(year, month - 1, day); + return dateObj; +} +bricks.date2str = function(date){ + let year = date.getFullYear(); + let month = String(date.getMonth() + 1).padStart(2, '0'); + let day = String(date.getDate()).padStart(2, '0'); + let formattedDate = `${year}-${month}-${day}`; + return formattedDate; +} +bricks.addMonths = function(dateObj, months){ + var newDate = new Date(dateObj); + newDate.setMonth(newDate.getMonth() + months); + return newDate; +} +bricks.addYears = function(dateObj, years){ + const newDate = new Date(dateObj); + newDate.setYear(newDate.getYear() + years); + return newDate; +} +bricks.addDays = function(dateObj, days){ + var newdate = new Date(dateObj); + newdate.setDate(newdate.getDate() + days); + return newdate; +} + +bricks.PeriodDays = class extends bricks.HBox { + /* + { + start_date: + end_date: + step_type: 'days', 'months', 'years' + step_cnt: + title:'', + splitter:' -- ' + } + event: 'changed'; + */ + constructor(opts){ + opts.splitter = opts.splitter || ' 至 '; + opts.step_cnt = opts.step_cnt || 1; + super(opts); + this.start_w = new bricks.Text({ + text:opts.start_date + }); + this.end_w = new bricks.Text({ + text:opts.end_date + }); + this.start_w.set_css('clickable'); + this.end_w.set_css('clickable'); + this.start_w.bind('click', this.step_back.bind(this)); + this.end_w.bind('click', this.step_forward.bind(this)); + if (this.title){ + this.add_widget(new bricks.Text({otext:this.title, i18n:true})); + } + this.add_widget(this.start_w); + this.add_widget(new bricks.Text({ + otext:this.splitter, + i18n:true + })); + this.add_widget(this.end_w); + } + date_add(strdate, step_cnt, step_type){ + var date = bricks.str2date(strdate); + switch(step_type){ + case 'years': + var nd = bricks.addYears(date, step_cnt); + return bricks.date2str(nd); + break; + case 'months': + var nd = bricks.addMonths(date, step_cnt); + return bricks.date2str(nd); + break; + default: + var nd = bricks.addDays(date, step_cnt); + return bricks.date2str(nd); + break; + } + } + step_back(){ + this.start_date = this.date_add(this.start_date, -this.step_cnt, this.step_type); + this.end_date = this.date_add(this.end_date, -this.step_cnt, this.step_type); + this.start_w.set_text(this.start_date); + this.end_w.set_text(this.end_date); + this.dispatch('changed', {start_date:this.start_date, end_date:this.end_date}); + } + step_forward(){ + this.start_date = this.date_add(this.start_date, this.step_cnt, this.step_type); + this.end_date = this.date_add(this.end_date, this.step_cnt, this.step_type); + this.start_w.set_text(this.start_date); + this.end_w.set_text(this.end_date); + this.dispatch('changed', {start_date:this.start_date, end_date:this.end_date}); + } +} + +bricks.Factory.register('PeriodDays', bricks.PeriodDays); From 4b46f2ff00a68ff6dc83f422ae8f499bff93cf4f Mon Sep 17 00:00:00 2001 From: yumoqing Date: Wed, 11 Dec 2024 18:08:41 +0800 Subject: [PATCH 13/75] bugfix --- bricks/bricks.js | 27 ++++++++++++++++++++++++--- bricks/camera.js | 46 ++++++++++++++++++++++++++++++++++++++++------ bricks/image.js | 2 +- bricks/input.js | 25 ++++++++++++++++++------- 4 files changed, 83 insertions(+), 17 deletions(-) diff --git a/bricks/bricks.js b/bricks/bricks.js index 54fa022..697f1cc 100644 --- a/bricks/bricks.js +++ b/bricks/bricks.js @@ -519,12 +519,33 @@ bricks.App = class extends bricks.Layout { this._Height = this.dom_element.offsetHeight; this.video_stream = null; this.audio_stream = null; + this.video_devices = null + this.vpos = null; document.addEventListener('keydown', this.key_down_action.bind(this)); } - async start_camera() { - if (this.video_stream) return; + async getCameras() { + try { + const devices = await navigator.mediaDevices.enumerateDevices(); + this.video_devices = devices.filter(device => device.kind === 'videoinput'); + } catch (error) { + console.error('获取摄像头数量出错:', error); + } + } + async start_camera(vpos) { + if (typeof(vpos) == 'undefined') vpos = 0; + if (this.video_devices === null){ + await this.getCameras(); + } + if (vpos == this.vpos) return; + this.vpos = vpos; + if (this.video_stream){ + this.video_stream.getTracks().forEach(track => { + track.stop(); + }); + } if (navigator.mediaDevices.getUserMedia) { - this.video_stream = await navigator.mediaDevices.getUserMedia({ video: true }); + var x = { deviceId: this.video_devices[vpos].deviceId }; + this.video_stream = await navigator.mediaDevices.getUserMedia({ video: x }); } else { console.log("Webcam access is not supported in this browser."); } diff --git a/bricks/camera.js b/bricks/camera.js index c4820d1..397c331 100644 --- a/bricks/camera.js +++ b/bricks/camera.js @@ -7,42 +7,73 @@ bricks.Camera = class extends bricks.Popup { */ constructor(opts){ opts.fps = opts.fps || 60; + opts.auto_dismiss = false; super(opts); this.stream = null; this.video = document.createElement('video'); var filler = new bricks.Filler({}); var hbox = new bricks.HBox({ - cheight:2 + cheight:3 }); + this.cur_camera_id = 0; this.add_widget(filler); this.add_widget(hbox); var shot_btn = new bricks.Icon({ url:bricks_resource('imgs/camera.png'), + margin: '10px', + tip:'Take a picture', + rate:2.5 + }); + var switch_btn = new bricks.Icon({ + url:bricks_resource('imgs/switch-camera.png'), + tip:'switch camera', + margin: '10px', rate:1.5 }); var del_btn = new bricks.Icon({ url:bricks_resource('imgs/delete.png'), + tip:'canel it', + margin: '10px', rate:1.5 }) del_btn.bind('click', this.dismiss.bind(this)); shot_btn.bind('click', this.take_picture.bind(this)); + switch_btn.bind('click', this.switch_camera.bind(this, switch_btn)); this.imgw = new bricks.Image({ width:'100%' }); + hbox.add_widget(switch_btn); hbox.add_widget(shot_btn); + hbox.add_widget(new bricks.Filler({})); hbox.add_widget(del_btn); filler.add_widget(this.imgw); this.task_period = 1 / this.fps; - schedule_once(this.startCamera.bind(this), 0.3); + schedule_once(this.startCamera.bind(this), 0.1); } - async startCamera() { - await bricks.app.start_camera(); + async switch_camera(btn, event){ + if (bricks.app.video_devices.length < 2){ + btn.disabled(true); + return; + } + var vpos = bricks.app.vpos; + vpos += 1; + if (vpos >= bricks.app.video_devices.length){ + vpos = 0; + } + this.startCamera(vpos); + } + async startCamera(vpos) { + await bricks.app.start_camera(vpos); this.stream = bricks.app.video_stream; this.video.srcObject = this.stream; this.video.play(); + this.show_cnt = 1; this.task = schedule_once(this.show_picture.bind(this), this.task_period); } show_picture(){ + if (this.task_period == 0){ + return; + } var canvas = document.createElement('canvas'); canvas.height = this.video.videoHeight; canvas.width = this.video.videoWidth; @@ -50,15 +81,18 @@ bricks.Camera = class extends bricks.Popup { context.drawImage(this.video, 0, 0); this.imgw.set_url(canvas.toDataURL('image/jpeg')); this.task = schedule_once(this.show_picture.bind(this), this.task_period); + this.show_cnt += 1; } - take_picture(){ + take_picture(event){ + event.stopPropagation(); if (this.task){ task.cancel(); + this.task = null; } + this.task_period = 0; this.task = null; var d = this.imgw.base64(); this.dispatch('shot', d); - // Create a blob from the canvas data URL } } diff --git a/bricks/image.js b/bricks/image.js index 977a340..0cb21b0 100644 --- a/bricks/image.js +++ b/bricks/image.js @@ -46,7 +46,7 @@ bricks.Image = class extends bricks.JsWidget { // 获取画布数据并转换为 base64 var dataURL = canvas.toDataURL('image/png'); // 可以根据需要修改图像格式 - dataURL = this.removeBase64Header(dataURL); + // dataURL = this.removeBase64Header(dataURL); return dataURL; } set_url(url){ diff --git a/bricks/input.js b/bricks/input.js index 2cbf42e..1baa345 100644 --- a/bricks/input.js +++ b/bricks/input.js @@ -352,7 +352,8 @@ bricks.UiImage =class extends bricks.VBox { this.uitype='image'; this.camera_w = new bricks.Icon({ url:bricks_resource('imgs/camera.png'), - rate:1.5}); + tip:'use cemera to take a picture', + rate:2}); this.add_widget(this.camera_w); this.camera_w.bind('click', this.take_photo.bind(this)); this.bind('drop', this.dropHandle.bind(this)); @@ -365,21 +366,23 @@ bricks.UiImage =class extends bricks.VBox { this.dom_element.appendChild(this.input); this.imgw = null; } - take_photo(){ + take_photo(event){ + event.stopPropagation(); var camera = new bricks.Camera({ "archor":"cc", "auto_open":true, "height":"90%", "width":"90%" }); - camera.bind('shot', this.accept_photo.bind(this)); + camera.bind('shot', this.accept_photo.bind(this, camera)); } - accept_photo(url){ + accept_photo(camera, event){ + camera.dismiss(); if (this.imgw){ this.remove_widget(this.imgw); } this.imgw = new bricks.Image({ - url:url, + url:event.params, width:'100%' }); this.add_widget(this.imgw); @@ -410,8 +413,16 @@ bricks.UiImage =class extends bricks.VBox { }; reader.readAsDataURL(file); } - set_formdata(formdata){ - formdata.append(this.name, this.value); + set_formdata(fd){ + // fd.append(this.name, this.resultValue(), 'test.png'); + fd.append(this.name, this.resultValue()); + } + resultValue(){ + if (this.imgw){ + this.value = this.imgw.base64(); + return this.value; + } + return null; } getValue(){ var ret = {} From 05bea8606909063cea7a1ddac2ad174d21d81598 Mon Sep 17 00:00:00 2001 From: yumoqing Date: Fri, 13 Dec 2024 18:07:16 +0800 Subject: [PATCH 14/75] bugfix --- bricks/bricks.js | 22 +++++++++++++++++++--- bricks/llm.js | 25 +++++++++++++++++++------ 2 files changed, 38 insertions(+), 9 deletions(-) diff --git a/bricks/bricks.js b/bricks/bricks.js index 697f1cc..f8d6b58 100644 --- a/bricks/bricks.js +++ b/bricks/bricks.js @@ -48,9 +48,20 @@ params: */ bricks.uuid = function(){ - var d = crypto.randomUUID(); - var lst = d.split('-'); - return lst.join(''); + try{ + var d = crypto.randomUUID(); + var lst = d.split('-'); + return lst.join(''); + } catch(e) { + const vv = '1234567890qwertyuiopasdfghjklzxcvbnm'; + var ret = ''; + for (var i=0;i<30;i++){ + var j = parseInt(Math.random() * vv.length); + ret = ret + vv[j]; + } + console.log('uuid() return', ret); + return ret; + } } bricks.deviceid = function(appname){ @@ -522,6 +533,11 @@ bricks.App = class extends bricks.Layout { this.video_devices = null this.vpos = null; document.addEventListener('keydown', this.key_down_action.bind(this)); + this.screen_orient = window.screen.orientation.type; + window.screen.orientation.addEventListener('change', () => { + this.screen_orient = window.screen.orientation.type; + this.bind('orient_changed', this.screen_orient); + }); } async getCameras() { try { diff --git a/bricks/llm.js b/bricks/llm.js index 9979694..f611a17 100644 --- a/bricks/llm.js +++ b/bricks/llm.js @@ -55,7 +55,11 @@ bricks.ModelOutput = class extends bricks.HBox { opts.width = '100%'; super(opts); this.logid = null; - this.img = new bricks.Icon({rate:2,url:this.icon||bricks_resource('imgs/llm.png')}); + this.img = new bricks.Icon({ + rate:2, + tip:this.opts.model, + url:this.icon||bricks_resource('imgs/llm.png') + }); this.run = new bricks.BaseRunning({target:this}); this.add_widget(this.img); this.add_widget(this.run); @@ -163,7 +167,10 @@ bricks.LlmModel = class extends bricks.JsWidget { render_title(){ var w = new bricks.HBox({}); w.bind('click', this.show_setup_panel.bind(this)) - var img = new bricks.Icon({rate:2,url:this.opts.icon||bricks_resource('imgs/llm.png')}); + var img = new bricks.Icon({ + rate:2, + url:this.opts.icon||bricks_resource('imgs/llm.png') + }); var txt = new bricks.Text({text:this.opts.model}); w.add_widget(img); w.add_widget(txt); @@ -199,7 +206,8 @@ bricks.LlmModel = class extends bricks.JsWidget { var mout = new bricks.ModelOutput({ textvoice:this.textvoice, tts_url:this.tts_url, - icon:this.opts.icon, + icon:this.opts.icon, + model:this.opts.model, estimate_url:this.llmio.estimate_url, output_view:this.opts.output_view}); this.llmio.o_w.add_widget(mout); @@ -286,20 +294,25 @@ bricks.LlmIO = class extends bricks.VBox { constructor(opts){ super(opts); this.llmmodels = []; - this.title_w = new bricks.HBox({cheight:2}); + this.title_w = new bricks.HBox({cheight:3}); + var bottom_box = new bricks.HBox({cheight:3}); this.i_w = new bricks.Icon({ rate:2, url:bricks_resource('imgs/input.png'), + margin:'14px', tip:'input data', css:'clickable' }); this.nm_w = new bricks.Icon({ rate:2, url:bricks_resource('imgs/add.png'), + margin:'14px', tip:'add new model', css:'clickable' }); - this.title_w.add_widget(this.nm_w); + bottom_box.add_widget(this.i_w); + bottom_box.add_widget(this.nm_w); + this.nm_w.bind('click', this.open_search_models.bind(this)); this.i_w.bind('click', this.open_input_widget.bind(this)); this.o_w = new bricks.Filler({overflow:'auto'}); @@ -308,7 +321,7 @@ bricks.LlmIO = class extends bricks.VBox { if (this.models.length < 2 && this.tts_url){ this.textvoice = true; } - this.add_widget(this.i_w); + this.add_widget(bottom_box); this.models.forEach( m =>{ this.show_added_model(m); }); From 8462fdfe8d1e92df6656f3820d1434a477455028 Mon Sep 17 00:00:00 2001 From: yumoqing Date: Fri, 13 Dec 2024 18:07:26 +0800 Subject: [PATCH 15/75] bigfix --- bricks/imgs/input.png | Bin 0 -> 12414 bytes bricks/imgs/search.png | Bin 0 -> 12795 bytes bricks/imgs/switch-camera.png | Bin 0 -> 14527 bytes 3 files changed, 0 insertions(+), 0 deletions(-) create mode 100644 bricks/imgs/input.png create mode 100644 bricks/imgs/search.png create mode 100644 bricks/imgs/switch-camera.png diff --git a/bricks/imgs/input.png b/bricks/imgs/input.png new file mode 100644 index 0000000000000000000000000000000000000000..c60e28c087e5596db39cf61e993ca9fa2088b0da GIT binary patch literal 12414 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 d5%x^xmN%H literal 0 HcmV?d00001 diff --git a/bricks/imgs/search.png b/bricks/imgs/search.png new file mode 100644 index 0000000000000000000000000000000000000000..7a81137ab9e1ca6a0547f23c49c7869469a91fd0 GIT binary patch literal 12795 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 X$1S+8uW8u|fq#2UElmn{(k}fUyRM0E literal 0 HcmV?d00001 From 536adc7887a11f59209117705cdef41b8cd3ad40 Mon Sep 17 00:00:00 2001 From: yumoqing Date: Thu, 26 Dec 2024 10:33:39 +0800 Subject: [PATCH 16/75] bugfix --- bricks/audio.js | 67 ++++++++++++-- bricks/binstreaming.js | 22 +++++ bricks/build.sh | 1 + bricks/css/bricks.css | 2 +- bricks/header.tmpl | 20 ++-- bricks/input.js | 44 ++++++++- bricks/jsoncall.js | 11 ++- bricks/utils.js | 204 +++++++++++++++++++++++++++++++---------- 8 files changed, 300 insertions(+), 71 deletions(-) diff --git a/bricks/audio.js b/bricks/audio.js index a93774c..8c088e5 100644 --- a/bricks/audio.js +++ b/bricks/audio.js @@ -26,7 +26,7 @@ bricks.AudioPlayer = class extends bricks.JsWidget { this.audio = this._create('audio'); this.audio.controls = true; if (this.opts.autoplay){ - this.audio.addEventListener('canplay', this.play_audio.bind(this)); + this.audio.addEventListener('canplay', this.play.bind(this)); } this.audio.style.width = "100%" this.dom_element.appendChild(this.audio); @@ -34,6 +34,58 @@ bricks.AudioPlayer = class extends bricks.JsWidget { this.set_source(this.url); } } + + set_stream_urls(response){ + async function* dyn_urls(response) { + const reader = response.body.getReader(); + var value; + var done; + while (true){ + done, value = await reader.read(); + if (value.done){ + console.log('done=', done, 'value=', value); + break; + } + let result = ''; + for (let i = 0; i < value.value.length; i++) { + result += String.fromCharCode(value.value[i]); + } + console.log('audio set url=', result); + yield result; + } + } + this.url_generator = dyn_urls(response); + this.srcList = []; + schedule_once(this.load_queue_url.bind(this), 0.1); + } + async load_queue_url(){ + while (true){ + var d = await this.url_generator.next(); + if (d.done){ + return; + } + this.srcList.push({played:false, url:d.value}); + if (this.srcList.length < 2 ){ + await this.play_srclist(); + this.audio.addEventListener('ended', + this.play_srclist.bind(this)); + } + } + } + async play_srclist(evnet){ + if (event && ! this.audio.ended){ + return; + } + for (var i=0;i - - - + + + - - - + + + +--> diff --git a/bricks/video.js b/bricks/video.js index a8cec15..86dcee1 100644 --- a/bricks/video.js +++ b/bricks/video.js @@ -64,6 +64,7 @@ bricks.Video = class extends bricks.Layout { } } auto_play(){ + return; schedule_once(this._auto_play.bind(this), 0.5); } _auto_play(){ @@ -74,6 +75,10 @@ bricks.Video = class extends bricks.Layout { play(){ console.log('Video:play() called....'); this.player.play(); + // this.player.muted(false); + } + unmuted(){ + this.player.muted(false); } set_fullscreen(){ if (this.fullscreen){ @@ -101,16 +106,10 @@ bricks.Video = class extends bricks.Layout { this.player.on('ended', this.report_ended.bind(this)); this._set_source(); this.player.ready(this.set_fullscreen.bind(this)); - /* + console.log('=======', this.autoplay, '========'); if (this.autoplay){ - this.player.autoplay = true; - this.player.muted = true; - this.player.ready(this.auto_play.bind(this)); - } else { - console.log('autoplay=', this.autoplay, this.auto_play); - // this.player.ready(this.auto_play.bind(this)); + this.auto_play(); } - */ } } report_ended(){ @@ -160,6 +159,7 @@ bricks.Video = class extends bricks.Layout { this.video_body.cur_url = url; this.video_body.cur_vtype = vtype; this._set_source(); + this.play(); } } set_url(url){ @@ -180,54 +180,73 @@ bricks.Iptv = class extends bricks.VBox { schedule_once(this.build_subwidgets.bind(this), 0.1); } async build_subwidgets(){ + console.log('build_subwidgets called'); var jc = new bricks.HttpJson(); - this.user_data = await jc.get(iptv_data_url); - this.video = new bricks.Video({url:this.iptv_data.url}); - this.title_w = new bricks.Text({text:this.iptv_data.title, wrap:false}); + 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.Video({ + 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 desc = { - "widgettye":"urlwidget", - "options":{ - "url":this.playok_url, - "params":this.user_data - } - } - var w = widgetBuild(desc, this); - if (w){ + 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 desc = { - "widgettye":"urlwidget", - "options":{ - "url":this.playfailed_url, - "params":this.user_data - } - } - var w = widgetBuild(desc, this); - if (w){ + 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('Video', bricks.Video); +bricks.Factory.register('Iptv', bricks.Iptv); From 643c4f62af8125c0bde571d695edff8816b565ec Mon Sep 17 00:00:00 2001 From: yumoqing Date: Tue, 14 Jan 2025 12:33:18 +0800 Subject: [PATCH 30/75] bugfix --- bricks/dataviewer.js | 2 +- bricks/wterm.js | 3 --- 2 files changed, 1 insertion(+), 4 deletions(-) diff --git a/bricks/dataviewer.js b/bricks/dataviewer.js index 4409696..dc7ab50 100644 --- a/bricks/dataviewer.js +++ b/bricks/dataviewer.js @@ -173,7 +173,7 @@ bricks.DataViewer = class extends bricks.VBox { var r = this.select_row; var data = r.user_data; } - this.dispatch(tdesc.name. data); + this.dispatch(tdesc.name, data); } get_edit_fields(){ var fs = this.row_options.fields; diff --git a/bricks/wterm.js b/bricks/wterm.js index 133963d..5408ed1 100644 --- a/bricks/wterm.js +++ b/bricks/wterm.js @@ -6,9 +6,6 @@ bricks.Wterm = class extends bricks.JsWidget { /* { ws_url: - host: - ssh_port: - user: } */ constructor(opts){ From 76dc6d37dc378de6a7091f4a281f977be3c56a59 Mon Sep 17 00:00:00 2001 From: yumoqing Date: Tue, 14 Jan 2025 13:42:29 +0800 Subject: [PATCH 31/75] bugfix --- 3parties/xterm-addon-fit.js | 2 ++ 1 file changed, 2 insertions(+) create mode 100644 3parties/xterm-addon-fit.js diff --git a/3parties/xterm-addon-fit.js b/3parties/xterm-addon-fit.js new file mode 100644 index 0000000..709e60a --- /dev/null +++ b/3parties/xterm-addon-fit.js @@ -0,0 +1,2 @@ +!function(e,t){"object"==typeof exports&&"object"==typeof module?module.exports=t():"function"==typeof define&&define.amd?define([],t):"object"==typeof exports?exports.FitAddon=t():e.FitAddon=t()}(window,function(){return function(e){var t={};function r(n){if(t[n])return t[n].exports;var o=t[n]={i:n,l:!1,exports:{}};return e[n].call(o.exports,o,o.exports,r),o.l=!0,o.exports}return r.m=e,r.c=t,r.d=function(e,t,n){r.o(e,t)||Object.defineProperty(e,t,{enumerable:!0,get:n})},r.r=function(e){"undefined"!=typeof Symbol&&Symbol.toStringTag&&Object.defineProperty(e,Symbol.toStringTag,{value:"Module"}),Object.defineProperty(e,"__esModule",{value:!0})},r.t=function(e,t){if(1&t&&(e=r(e)),8&t)return e;if(4&t&&"object"==typeof e&&e&&e.__esModule)return e;var n=Object.create(null);if(r.r(n),Object.defineProperty(n,"default",{enumerable:!0,value:e}),2&t&&"string"!=typeof e)for(var o in e)r.d(n,o,function(t){return e[t]}.bind(null,o));return n},r.n=function(e){var t=e&&e.__esModule?function(){return e.default}:function(){return e};return r.d(t,"a",t),t},r.o=function(e,t){return Object.prototype.hasOwnProperty.call(e,t)},r.p="",r(r.s=0)}([function(e,t,r){"use strict";Object.defineProperty(t,"__esModule",{value:!0});var n=function(){function e(){}return e.prototype.activate=function(e){this._terminal=e},e.prototype.dispose=function(){},e.prototype.fit=function(){var e=this.proposeDimensions();if(e&&this._terminal){var t=this._terminal._core;this._terminal.rows===e.rows&&this._terminal.cols===e.cols||(t._renderService.clear(),this._terminal.resize(e.cols,e.rows))}},e.prototype.proposeDimensions=function(){if(this._terminal&&this._terminal.element&&this._terminal.element.parentElement){var e=this._terminal._core,t=window.getComputedStyle(this._terminal.element.parentElement),r=parseInt(t.getPropertyValue("height")),n=Math.max(0,parseInt(t.getPropertyValue("width"))),o=window.getComputedStyle(this._terminal.element),i=r-(parseInt(o.getPropertyValue("padding-top"))+parseInt(o.getPropertyValue("padding-bottom"))),a=n-(parseInt(o.getPropertyValue("padding-right"))+parseInt(o.getPropertyValue("padding-left")))-e.viewport.scrollBarWidth;return{cols:Math.max(2,Math.floor(a/e._renderService.dimensions.actualCellWidth)),rows:Math.max(1,Math.floor(i/e._renderService.dimensions.actualCellHeight))}}},e}();t.FitAddon=n}])}); +//# sourceMappingURL=xterm-addon-fit.js.map \ No newline at end of file From 5df6a98d72b253eb0ea35852a50864dced119aac Mon Sep 17 00:00:00 2001 From: yumoqing Date: Tue, 14 Jan 2025 13:43:24 +0800 Subject: [PATCH 32/75] bugfix --- bricks/header.tmpl | 1 + 1 file changed, 1 insertion(+) diff --git a/bricks/header.tmpl b/bricks/header.tmpl index 48f0c53..afdf312 100644 --- a/bricks/header.tmpl +++ b/bricks/header.tmpl @@ -25,6 +25,7 @@ +