Index: common.lua ================================================================== --- common.lua +++ common.lua @@ -76,10 +76,17 @@ dump = dump; ping = ping; chomp = chomp; map = map; tobool = tobool; + find = function(lst,pred) + for k,v in pairs(lst) do + local test = pred(v,k) + if test then return test end + end + return nil + end; rndstr = function(len) local s = '' for i=1,len do local ofs = math.random(0,10 + 26) if ofs >= 10 then ofs = 0x60 + (ofs - 10) Index: config.lua ================================================================== --- config.lua +++ config.lua @@ -54,12 +54,14 @@ {'style.css', 'text/css'}; {'live.js', 'text/javascript'}; -- rrrrrrrr {'default-avatar.webp', 'image/webp'}; -- needs inkscape-exclusive svg features {'bell.svg', 'image/svg+xml'}; {'gear.svg', 'image/svg+xml'}; + {'pen.svg', 'image/svg+xml'}; {'heart.webp', 'image/webp'}; {'retweet.webp', 'image/webp'}; + {'logo.svg', 'image/svg+xml'}; {'padlock.svg', 'image/svg+xml'}; {'warn.svg', 'image/svg+xml'}; {'query.webp', 'image/webp'}; {'reply.webp', 'image/webp'}; {'file.webp', 'image/webp'}; Index: render/nav.t ================================================================== --- render/nav.t +++ render/nav.t @@ -4,14 +4,14 @@ var t = co:stra(64) if co.who ~= nil or co.srv.cfg.pol_sec == lib.srv.secmode.public then t:lpush(' timeline') end if co.who ~= nil then - t:lpush(' compose media docs
') + t:lpush(' media docs
') t:push(co.who.handle,0) - t:lpush(' log out configure notices (x)') + t:lpush(' log out compose configure notices (x)') else t:lpush(' docs log in') end return t:finalize() end return render_nav Index: render/profile.t ================================================================== --- render/profile.t +++ render/profile.t @@ -195,10 +195,23 @@ end if relationship.recip.follow() then comments:lpush('
  • follows you
  • ') end + + var circpanel = co:stra(128) + var allcircs = co.srv:circle_search(&co.srv.pool, co.who.id, 0) + if allcircs:ref() then + var mycircs = co.srv:circle_memberships_uid(&co.srv.pool, co.who.id, actor.id) + for i=0, allcircs.ct do + circpanel:lpush '' + end + end var profile = data.view.profile { nym = fullname; bio = bio; xid = cs(actor.xid); @@ -210,10 +223,11 @@ timephrase = lib.trn(actor.origin == 0, pstr 'joined', pstr 'known since'); remarks = ''; auxbtn = auxp; + circles = circpanel:finalize(); relations = relbtns:finalize(); sanctions = sancbtns:finalize(); } if comments.sz > 0 then profile.remarks = comments:finalize() end Index: route.t ================================================================== --- route.t +++ route.t @@ -18,11 +18,17 @@ if rel.recip.block() then if act:cmp('follow') or act:cmp('subscribe') then co:complain(403,'blocked','you cannot follow a user you are blocked by') return end end - if act:cmp('block') and not rel.rel.block() then + if act:cmp('circle') then + lib.dbg('encircling user!') + var iter = co:eachpostv('circle') + for cid in iter do + + end + elseif act:cmp('block') and not rel.rel.block() then rel.rel.block = true rel.recip.follow = false co.srv:actor_rel_create([lib.store.relation.idvmap.block], co.who.id, actor.id) co.srv:actor_rel_destroy([lib.store.relation.idvmap.follow], actor.id, co.who.id) elseif not act:cmp('report') then [(function() Index: srv.t ================================================================== --- srv.t +++ srv.t @@ -415,30 +415,68 @@ ok = false self:complain(403,'insufficient privileges',['you lack the '..pow:asvalue()..' power and cannot perform this action']) end in ok end end) + +local pstr2mg, mg2pstr +do -- aaaaaaaaaaaaaaaaaaaaaaaa + mgstr = lib.util.find(lib.net.mg_http_message.entries, function(v) + if v.field == 'body' or v[1] == 'body' then return v.type end + end) + terra pstr2mg(p: pstring): mgstr + return mgstr { ptr = p.ptr, len = p.ct } + end + terra mg2pstr(m: mgstr): pstring + return pstring { ptr = m.ptr, ct = m.len } + end +end -- CALL ONLY ONCE PER VAR -terra convo:postv(name: rawstring) +terra convo:postv_next(name: pstring, start: &pstring) if self.varbuf.ptr == nil then self.varbuf = self.srv.pool:alloc(int8, self.msg.body.len + self.msg.query.len) self.vbofs = self.varbuf.ptr end - var o = lib.net.mg_http_get_var(&self.msg.body, name, self.vbofs, self.varbuf.ct - (self.vbofs - self.varbuf.ptr)) + var conv = pstr2mg(@start) + var o = lib.net.mg_http_get_var( + &conv, + name.ptr, self.vbofs, + self.varbuf.ct - (self.vbofs - self.varbuf.ptr) + ) if o > 0 then + start:advance(name.ct + o + 2) var r = self.vbofs self.vbofs = self.vbofs + o + 1 @(self.vbofs - 1) = 0 var norm = lib.str.normalize([lib.mem.ptr(int8)]{ptr = r, ct = o}) return norm.ptr, norm.ct else return nil, 0 end end -terra convo:ppostv(name: rawstring) +terra convo:postv(name: pstring) + var start = mg2pstr(self.msg.body) + return self:postv_next(name, &start) +end +terra convo:ppostv(name: pstring) var s,l = self:postv(name) return pstring { ptr = s, ct = l } end +do + local struct postiter { co: &convo where: pstring name: pstring } + terra convo:eachpostv(name: pstring) + return postiter { co = self, where = mg2pstr(self.msg.body), name = name } + end + postiter.metamethods.__for = function(self, body) + return quote + while true do + var str, len = self.co:postv_next(self.name, &self.where) + if str == nil then break end + [ body(`pstring {str, len}) ] + end + end + end +end terra convo:getv(name: rawstring) if self.varbuf.ptr == nil then self.varbuf = self.srv.pool:alloc(int8, self.msg.query.len + self.msg.body.len) self.vbofs = self.varbuf.ptr ADDED static/pen.svg Index: static/pen.svg ================================================================== --- static/pen.svg +++ static/pen.svg @@ -0,0 +1,264 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + image/svg+xml + + + + + + + + + + + Index: static/style.scss ================================================================== --- static/style.scss +++ static/style.scss @@ -173,10 +173,11 @@ } } select { width: 100%; } @mixin glass { + box-shadow: inset 0 0 1.5em tone(-56%); @supports (backdrop-filter: blur(1px)) or (-webkit-backdrop-filter: blur(1px)) { backdrop-filter: blur(40px); -webkit-backdrop-filter: blur(40px); background-color: tone(-53%, -0.7); } @@ -244,21 +245,23 @@ text-shadow: 1px 1px 1px black; &:hover{ transform: scale(1.2); } } - > a[href].bell, a[href].gear { + > a[href].bell, a[href].gear, a[href].pen { height: 2em; + width: 2em; padding: 0.125in 0.05in; filter: drop-shadow(1px 1px 3px tone(-5%)); &:hover { filter: drop-shadow(1px 1px 3px tone(-5%)) drop-shadow(0 0 10px tone(-5%)); } } > a[href].bell { content: url(/s/bell.svg); } > a[href].gear { content: url(/s/gear.svg); } + > a[href].pen { content: url(/s/pen.svg); } } } } main { @@ -302,12 +305,11 @@ padding: 0.1in; border-radius: 5px; border: 1px solid transparent; &.on { background-color: tone(-30%, -0.7); - box-shadow: 0 0 10px tone(-30%); - border-color: tone(-20%); + border-color: tone(-20%) transparent; } > button, > p, > a[href] { display: block; } > p { text-align: center; font-size: 80%; margin: 0; margin-top: 0.1in; } > button, > a[href] { width: max-content; Index: view/docskel.tpl ================================================================== --- view/docskel.tpl +++ view/docskel.tpl @@ -1,10 +1,11 @@ @instance :: @title +

    @title

    Index: view/profile.tpl ================================================================== --- view/profile.tpl +++ view/profile.tpl @@ -31,14 +31,14 @@