// This file creates and syncs msto // msto is a recursive proxy that synchronizes itself between all meeting participants // you can get a clone of the object by typing jc(msto) into your dev console dlog = nop // dlog = clog function match(mx,m,o){ var k,v,k2,v2 var r = 0 for ([k,v] of Object.entries(m || {})){ v2 = o[k] if (typeof(v) == "string" && typeof(v2) == "string") { r += !(v==v2) } else if (Array.isArray(v) && Array.isArray(v2)){ r += !(isSubset_arr(v,v2)) } else if (Array.isArray(v) && typeof(v2) == "string"){ // r += !(isSubset_arr(v2,v)) r += !v.includes(v2) } else if (Array.isArray(v2) && typeof(v) == "string"){ r += !(v2.includes(v)) } if (r){ return !r } } return !r } function isSubset(subset,superset){ for (var elem of subset) { if (!superset.includes(elem)) { return false; } } return true; } function isSubset_arr(subset,superset){ for (var elem of subset) { if (Array.isArray(elem)){ if (!new Set(elem).intersection(superset).size){ return false } } else if (!superset.includes(elem)) { return false; } } return true; } function dispatch_ws_events3(e,key){ var k,v // let dlog =clog clog("dispatch_ws_events3",e,{that:this,e,key}) // return // e.payload.etype ? 1 : e.payload.etype = "null" e.parsed.etype ? 1 : e.parsed.etype = "null" var mflag =0 dlog("dispatch_events??",e,key) for ([k,v] of Object.entries(glob_mx.ws_event_handlers || {}) ) { dlog("dispatch_events:",k) if (v.m){ // mflag = match({},v.m,e.payload) mflag = match({},v.m,e.parsed) mflag ? v.fn(e,key) : 1 } } } function dispatch_ws_events(e,key){ var k,v // let dlog =clog clog("dispatch_ws_events",{that:this,e,key}) // return // e.payload.etype ? 1 : e.payload.etype = "null" e.parsed.etype ? 1 : e.parsed.etype = "null" var mflag =0 dlog("dispatch_events??",e,key) for ([k,v] of Object.entries(glob_mx.ws_event_handlers || {}) ) { dlog("dispatch_events:",k) if (v.m){ // mflag = match({},v.m,e.payload) mflag = match({},v.m,e.parsed) mflag ? v.fn(e,key) : 1 } } } function dispatch_events(e,key){ var k,v // clog("dispatch_events_z",{that:this,e,key}) e.parsed.etype ? 1 : e.parsed.etype = "null" var mflag =0 dlog("dispatch_events??",e,key) for ([k,v] of Object.entries(glob_mx.event_handlers || {}) ) { dlog("dispatch_events:",k) if (v.m){ mflag = match({},v.m,e.parsed) mflag ? v.fn(e) : 1 } } } function run_cbs(key){ jlog("RCB","run_cbs") var k,v dlog("RUN_CB??",key,glob_mx.cb[key]) for ([k,v] of Object.entries(glob_mx.cb[key]|| {}) ) { dlog("RUN_CB:",k) v() } } function run_hook_cbs(key,o){ jlog("RCB","run_hook_cbs") var k,v // dlog("RUN_HOOK_CB??",key,glob_mx.hook_cb[key]) for ([k,v] of Object.entries(glob_mx.hook_cb[key]|| {}) ) { // dlog("RUN_HOOK_CB:",k) v(o) } } function wait(ms) { return new Promise(r => setTimeout(r, ms)); } function attr_info(n){ var k,v var ret ={} // clog(".") for (k in n.attributes){ // clog(k) } // clog("~") for (k of n.attributes){ // for (k of n.attributes){ // clog(k) } // clog("--") for ([k,v] of Object.entries(n.attributes)){ // clog(k,v,v+"+") // clog("+",[k,v],v) ret[v.name]= v.value // clog(typeof(k),typeof(v)) } return ret } // ai.from.split((a0,a1,a2,a3)=>{clog({a0,a1,a2,a3});return "z"}) // tmsgx3({type:"db_sync_request"}) function mhndlr_rld(that,m){ try { window.mx=m var n = m.querySelector(`code`) if (!n){return} var parsed = JSON.parse(n.innerHTML) var ai = attr_info(m) window.ai=ai // clog("FROM",ai.from == glob_mx.all_jids[0]) // var id = ai.from.split().slice(-1)[0] var id = ai.from.split("/").pop() dlog("mhndlr_rld2",m,parsed,n,n.dataset) var o = parsed.payload switch (parsed.type){ case "set_msg": pf._set_recv(o.path,o.key,o.val) window._set_recv_cb ? window._set_recv_cb({that:this,m,n,o,ai,id}): 0 // TODO DEV BODGE? if (window.glob_td && glob_td.cb._set_recv_cb){ // run_cbs_td("_set_recv_cb",{that:this,m,n,o,ai,id}) run_cbs_td("_set_recv_cb",{that:this,m,n,o,ai,id,parsed,innerHTML:n.innerHTML,p2:JSON.parse(n.innerHTML)}) // glob_td.cb._set_recv_cb("_set_recv_cb",{that:this,m,n,o,ai,id}) } // window?._set_recv_cb?.({that:this,m,n,o,ai,id}) opt_chain break; case "event": dlog("~event~",parsed) dispatch_events({parsed,ai,m,that}) break; case "msg_test": dlog("msg_test",parsed) break; case "db_sync_request": // tmsgx3({type:"db_sync_response",payload:pf.root}) tmsgx3({type:"db_sync_response",payload:pf.root},{to:ai.from}) // dlog("db_sync_request",parsed) clog("db_sync_request",parsed) break; case "db_sync_response": if (id == glob_mx.local_id){ dlog( "db_sync_response ...") break } if (glob_mx.prom.init_db_resolve){ glob_mx.prom.init_db_resolve({aaa:"dsr",pl:parsed.payload}) } clog("db_sync_response",ai.from == glob_mx.local_id,ai.from,parsed) break; } /* if (parsed.type == "set_msg"){ var o = parsed.payload pf._set_recv(o.path,o.key,o.val) } if (parsed.type == "msg_test"){ clog("msg_test",parsed) } */ } catch (err) { clog("mhndlr err:",err) } return true } isProxy = Symbol("isProxy") tlu = { object:"", string:true, number:true, undefined:true, boolean:true, } function type_info(o){ var t var flags = { leaf:false, deep_not_prx:false, prx:false, isObj:false, isArr:false, els:false, } t = typeof(o) flags.t=t if (!(o === null)){ flags.isArr = Array.isArray(o) flags.isObj = Object.prototype == o.__proto__ } if (tlu[t] === true || o === null){ flags.leaf = true } else if (t == "object" && o.__prx){ flags.prx = true } else if (t == "object" && (flags.isArr || flags.isObj)){ flags.prx = false flags.deep_not_prx = true } else { clog("ELSE") flags.els = true } return flags clog(t,flags) } function deep_prop_v0(o,p){ try { var arr = jc(p) var ret = o while (arr.length){ // clog("deep_prop",arr,ret) ret = ret[arr.shift()] } // clog("deep_prop ret",ret) return ret } catch(err){console.error("DEEP_PROP ERR:",err)} } delete Proxy_Factory { class Proxy_Factory { constructor(o,n="dflt"){ this.db = o this.n = n this.hidden_props = ["add_proxy","_set","walker","walker_start","prxy","_sett","_sett2"] this._pub_cb =[] this.__prx = true this.SymPrx = Symbol("SymPrx") // clog("pfx",{o,n,that:this}) } init(o){ // dlog("BP",this,this.baseProp,this.__proto__.baseProp,window.baseProp) // clog("pfx init",{o,that:this}) this.root = o } sync(o){ this.root = jc(o.root) o._pub_cb.push(this._set_recv.bind(this)) } get prxy(){ return this } _set(o,k,v,prx,a0){ this.obj[k]=prx } _sett(o,k,v,prx,a0){ dlog("_SETT",this,arguments) } _sett2(o,k,v,prx,a0){ dlog("_SETT2",this,arguments) } set_pub(obj, prop, val,receiver){ // dlog("qia_pub",obj, prop, val,receiver) // dlog("qia_pub2",this.n,obj.__path_arr, prop, jx(val)) this._set_pub(obj.__path_arr, prop, jx(val)) } _set_pub(path,key,val){ var k,v /* tmsgx({ "type":"set_msg", "payload":{path,key,val}, },"code") // */ tmsgx3({ "type":"set_msg", "payload":{path,key,val},}, // window.tmsgx_to || {} // {to:"nl4qbyiz61z-mce1@specplot.com/FlUkwrLs"}, // {to:"maf@conference.i.specplot.com/0695c1e4"}, // {}, ) for (v of this._pub_cb){ v(path,key,val) } } _set_recv(path,prop,val){ // return var p = path var nprop = deep_prop_v0(this.root,p) var dpth = nprop.__dpth if (tlu[typeof(val)]){ nprop._set(nprop,prop,val,val) } else { nprop._set(nprop,prop,val,new Proxy(val,this)) nprop[prop].add_proxy(nprop,prop,val,dpth+1) } // var tf = {} // this.walker(nprop[prop],tf,dpth+2) this.walker(nprop[prop],{},dpth+2) } set(obj, prop, val,receiver){ // dlog("prx_db set ",this,obj, prop, val,receiver,val.__prx) // clog("prx_db set ",{that:this,obj, prop, val,receiver},val.__prx) // clog("prx_db set ",obj.__path_arr) if (obj[prop] === val){ return Reflect.set(...arguments) } this.set_pub(obj, prop, val,receiver) this.event_proc("set") if ("__prx" == prop){ this.__prx=val return this.__prx } if (typeof(val) === "object" && val != null && !(val.__prx)){ var ret = Reflect.set(...arguments) this.set_obj(obj, prop, val,receiver) return ret } return Reflect.set(...arguments) } get(obj, prop,receiver){ // dlog("prx_db get ...",prop==isProxy,this,obj, prop,receiver) if (this.hidden_props.includes(prop)){ switch (prop){ case "add_proxy": return this.add_proxy.bind(this) break; case "prxy": return this case "_set": // dlog("_SET") // return this._set.bind({this}) return this._set.bind({that:this,obj, prop,receiver}) case "_sett": return this._sett.bind({that:this,obj, prop,receiver}) case "_sett2": return this._sett2.bind({that:this}) case "walker_start": return this.walker_start case "walker": return this.walker break; } } if (isProxy == prop){ return true } if ("__prx" == prop){ return this.__prx } return Reflect.get(...arguments) } add_proxy(o,k,v,dpth){ // clog("~add_proxy~",o,k,v,dpth) // clog("~add_proxy~",o.__prx,o,k,v,dpth,xpath) var xpath = o.__path var apath = o.__path_arr this.event_proc("add_proxy") if (!apath){ apath=[] } if (!xpath){ xpath="ROOT!" } Object.defineProperty(v,"__path_arr",Object.assign({value:apath.concat(k),},this.baseProp)) Object.defineProperty(v,"__path",Object.assign({value:xpath+":"+k,},this.baseProp)) Object.defineProperty(v,"__dpth",Object.assign({value:dpth,},this.baseProp)) // Object.defineProperty(v,"__dbg",Object.assign({value:{},},this.baseProp)) } set_obj(obj, prop, val,receiver){ var dpth = obj.__dpth var tf = {} this.walker(receiver,tf,dpth) } walker(o,tfo,dpth=0){ // dlog("qia WALK",this) if (dpth > 7){ console.error("MAX DEPTH") return } var k,v var tf for ([k,v] of Object.entries(o)){ tf = type_info(v) if (tf.deep_not_prx){ o._set(o,k,v,new Proxy(v,this.prxy)) o[k].add_proxy(o,k,v,dpth) this.walker(o[k],tf,dpth+1) } } } walker_start(o,dpth){ var tf = type_info(o) o.add_proxy({},[],o,-1) this.walker(o,tf,0) } event_proc(e){} } window.Proxy_Factory = Proxy_Factory Proxy_Factory.prototype.baseProp={ writable: true, // enumerable: true, enumerable: false, configurable: true, } } function arr_match(m,o){ var k,v var r = 0 for ([k,v] of Object.entries(m || {})){ if (o[k] != v.valueOf()){ r += 1 return !r } // for ([k,v] in m){ // case // dlog(k,v) } return !r } permissions_def = { participants:{ m:["participants"], fn(set_scope,match){ // clog("FN....",match.fp,match.fp[1] == window.glob_mx.local_id) if (match.fp[1] != window.glob_mx.local_id) throw "permission err" return }, } } // // msto.my_data.prxy.__proto__.__proto__.set.call(msto.my_data.prxy,msto.participants,"abc2",{}) permissions_def__set = { participants:{ m:["participants"], fn(set_scope,match){ dlog("FN....",match.fp,match.fp[1] == window.glob_mx.local_id) if (match.fp[1] != window.glob_mx.local_id) // throw "permission err" return }, } } { class Proxy_Permissions extends Proxy_Factory { constructor(a,a1){ super(...arguments) } set(obj, prop, val,receiver){ // clog("PRX_PERM",obj.__path_arr,prop) var k,v var r var matched var fp = obj.__path_arr.concat(prop) for ([k,v] of Object.entries(permissions_def)){ matched = arr_match(v.m,fp) if (matched){ r = v.fn({that:this,obj, prop, val,receiver},{fp,k,v}) || {} } // if (r.return) } // case // if (obj.__path_arr && obj.__path_arr.length){} return super.set(obj, prop, val,receiver) } _set(){ // clog("Proxy_Permissions _set") super._set(...arguments) } } window.Proxy_Permissions = Proxy_Permissions } msto_z = { // private_local:{}, // participant_local:{}, conference:{}, participants:{ }, } function pfnf(o){ return function(resolve, reject){ o.resolve=resolve o.reject=reject // clog(arguments) } } function init_db_cb(){ msto.participants[glob_mx.local_id] = msto.my_data } function init_sync_participant(){ } function init_db(objx){ var obj if (objx.participants){ obj = objx } else { obj = objx.pl } window.objx_1 = objx // var obj = obj.pl clog("INIT DB...",objx,obj) pf = new Proxy_Permissions({},"pf") msto_prx = new Proxy(obj,pf) window.msto_prx0 =msto_prx // msto_prx = new Proxy(msto_z,pf) pf.init(msto_prx) msto_prx.walker_start(msto_prx) pf.root.participants[glob_mx.local_id] = {} glob_mx.flags.init_db = true setTimeout(init_db_cb,2000) window.msto= { participants:pf.root.participants, conference:pf.root.conference, // my_data:pf.root.participants[glob_mx.local_id], get my_data(){ return msto.participants[glob_mx.local_id] // my_data("pfx get k1") }, set my_data(val){ clog("pfx set my_data") msto.participants[glob_mx.local_id] = val }, private_local:{}, set_listeners:{ }, } // var k,v clog("RUN_CB...") run_cbs("init_db") } function init_mu(persistent_mods){ // .role == "moderator" // clog(">>>>>>>>>>>>>>>>>>>.. RUN_CB") var participants = get_participants() // clog(participants) var local = get_local(participants) if (window.glob_mx.local_id && persistent_mods && local.role=="moderator"){ // if window.glob_mx.local_id // clog("no RUN_CB") return } window.glob_mx.local_id = local.id var k,v window.glob_mx.all_ids = [] window.glob_mx.all_jids = [] for (v of participants){ window.glob_mx.all_ids.push(v.id) window.glob_mx.all_jids.push(`nnnx@conference.jfidev.com/${v.id}`) } var rr = {} var prom1 = new Promise(pfnf(rr)); prom1.then(init_db) // setTimeout(rr.reject,2000,"RESP DB Timeout") // setTimeout(rr.resolve,4000,"RESP DB Timeout") // setTimeout(rr.resolve,4000,msto_z) // setTimeout(rr.resolve,4000,{aaa:"timedout",pl:msto_z}) setTimeout(rr.resolve,5000,{aaa:"timedout",pl:msto_z}) if (participants.length > 1){ glob_mx.prom.init_db_resolve = rr.resolve clog("MSTO > 1") tmsgx3({type:"db_sync_request"}) } else { clog("MSTO INIT!") // glob_mx.prom.init_db_resolve(msto_z) rr.resolve(msto_z) // init_db() } } function create_db(){ } function isident(){ return JSON.stringify(pf.root) == JSON.stringify(pf2.root) } function init_mu_runner(){ if (window.glob_mx.conf_joined){ init_mu(...arguments) } } function init_mx2(){ clog("INITMX3") window.glob_mx.conf_joined =1 init_mu_runner() // add_handler_m(mhndlr) } ifn_obj.init_conf_join.push(init_mx2) // init_mu_runner("auto") init_mu_runner("")