Skip to content

Instantly share code, notes, and snippets.

@zew13
Created November 15, 2022 09:23
Show Gist options
  • Save zew13/80822c6d3414a0a5bd8df915a151c536 to your computer and use it in GitHub Desktop.
Save zew13/80822c6d3414a0a5bd8df915a151c536 to your computer and use it in GitHub Desktop.
> ./utax/On.js
./utax/assign.js
./lib/SDK.js
./utax/web/tld.js
./utax/sleep.js
+ USER, INIT_RESOLVE, TAB_ID, _setUser, unbindBeforeunload
same_host = do =>
dot_host = '.'+tld
(origin)=>
{hostname} = new URL(origin)
hostname == tld or hostname.endsWith(dot_host)
liSet = (li,to)=>
li.splice(0,li.length,...to)
return
li2user = (li)=>
if li
[id,name] = li
return {id,name}
{}
liEq = (a,b)=>
r = a?.length == b?.length
if a and r
return a.every (i,p)=>i==b[p]
r
ON_USER_CHANGE = new Set()
_setMe = (me)=>
USER = li2user me
for f from ON_USER_CHANGE
f(USER)
return
_update = =>
replyMsgNew(0)
_setMe USER_SIGNIN[0]
return
_setSigninExit = (signin,exit)=>
liSet USER_SIGNIN,signin
liSet USER_EXIT,exit
return
_updateUser = (signin,exit)=>
pre = USER_SIGNIN[0]
now = signin[0]
_setSigninExit signin,exit
if not liEq pre, now
_update()
return
INIT = new Promise (resolve)=>
_setUser = INIT_RESOLVE = (signin, exit)=>
INIT_RESOLVE = INIT = undefined
_setSigninExit signin,exit
_setMe signin[0]
_setUser = _updateUser
resolve()
return
return
< CHANNEL = new BroadcastChannel 'user.tax:'+tld
_ms = =>
parseInt +new Date
MSG_ID = 0
LEADER = 0
MSG_NEW = 1
< USER_SIGNIN = []
< USER_EXIT = []
NEW_REPLY = []
replyMsgNew = (tab_id)=>
CHANNEL.postMessage [
MSG_NEW
tab_id
TAB_ID
USER_SIGNIN
USER_EXIT
]
return
initPost = =>
TAB_ID = _ms()
CHANNEL.postMessage [
MSG_NEW
TAB_ID
]
return
On CHANNEL,{
message:(e)=>
{data,origin} = e
if not same_host origin
return
{length} = data
switch data[0]
when MSG_NEW
tab_id = data[1]
if length == 2
if INIT_RESOLVE
return
if LEADER
replyMsgNew tab_id
else
data.push _ms()
NEW_REPLY.push data
timeout = 10
await sleep timeout
if NEW_REPLY.length
li = NEW_REPLY.filter(
(i)=>
time = i[2]
timeout = (new Date - time) >= timeout
if timeout
replyMsgNew(i[1])
!timeout
)
if li.length != NEW_REPLY.length
NEW_REPLY = li
if not LEADER
LEADER = 1
# document.title = 'leader'
unbindBeforeunload = On window,{
beforeunload:=>
# 重新选举避免延时(没有leader的时候,延时甚至可能会高达1秒)
initPost()
return
}
else
user_li = data[3..]
_setUser ...user_li
src_id = data[2]
if src_id == TAB_ID
initPost()
for i,pos in NEW_REPLY
if i[1] == tab_id
NEW_REPLY.splice(pos,1)
return
if tab_id and LEADER
if src_id <= TAB_ID
# document.title = 'member'
unbindBeforeunload()
unbindBeforeunload = undefined
LEADER = 0
return
}
do =>
initPost()
await sleep 300
if INIT_RESOLVE
_setUser ... await SDK.u()
return
< onUserChange = (func)=>
ON_USER_CHANGE.add func
if USER != undefined
func USER
=>
ON_USER_CHANGE.delete func
return
< userSet = (li)=>
r = Array.isArray(li)
if r
uid = li[0]
for [id],pos in USER_EXIT
if uid == id
USER_EXIT.splice(pos,1)
USER_SIGNIN.unshift(li)
_update()
return r
for [id],pos in USER_SIGNIN
if uid == id
if pos == 0
break
USER_SIGNIN.splice pos, 1
USER_SIGNIN.unshift li
_update()
return r
USER_SIGNIN.unshift li
_update()
return r
< exit = ()=>
{id} = await User()
if id
return exitUid(id)
return
< exitUid = (id)=>
for i,pos in USER_SIGNIN
if i[0] == id
await SDK.u.exit id
USER_SIGNIN.splice pos,1
_update()
return
return
_User = =>
await INIT
_User = => USER
USER
< default User = =>
_User()
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment