Index: backend/pgsql.t ================================================================== --- backend/pgsql.t +++ backend/pgsql.t @@ -331,10 +331,26 @@ select unnest(members) from parsav_circles where ($1::bigint = 0 or owner = $1::bigint) and name = $2::text ]]; }; + + circle_members_add_uid = { + params = {uint64, uint64}, cmd = true, sql = [[ + update parsav_circles set + members = members || $2::bigint + where id = $1::bigint + ]]; + }; + + circle_members_del_uid = { + params = {uint64, uint64}, cmd = true, sql = [[ + update parsav_circles set + members = array_remove(members, $2::bigint) + where id = $1::bigint + ]]; + }; auth_sigtime_user_fetch = { params = {uint64}, sql = [[ select authtime::bigint from parsav_actors where id = $1::bigint @@ -2204,9 +2220,17 @@ for i = 0, res.sz do rt(i) = res:int(uint64,i,0) end return rt end]; + circle_members_add_uid = [terra( + src: &lib.store.source, owner: uint64, subject: uint64 + ): {} queries.circle_members_add_uid.exec(src,owner,subject) end]; + + circle_members_del_uid = [terra( + src: &lib.store.source, owner: uint64, subject: uint64 + ): {} queries.circle_members_del_uid.exec(src,owner,subject) end]; + actor_auth_register_uid = nil; -- TODO better support non-view based auth } return b Index: config.lua ================================================================== --- config.lua +++ config.lua @@ -57,11 +57,11 @@ {'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'}; + {'icon.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/conf/circles.t ================================================================== --- render/conf/circles.t +++ render/conf/circles.t @@ -8,10 +8,11 @@ if path.ct == 2 then var circs = co.srv:circle_search(&co.srv.pool, co.who.id, 0) var ui: data.view.conf_circles if circs.ct == 0 then ui.newattr = ' open'; + ui.circles = ''; else ui.newattr = ''; var circlst = co:stra(86) for i = 0, circs.ct do circlst:lpush '
  • ' 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(' media docs
    ') + t:lpush(' media docs
    ') t:push(co.who.handle,0) 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 @@ -196,20 +196,30 @@ 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 '' + var circpanel: lib.str.acc + if co.aid ~= 0 then + 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 end var profile = data.view.profile { nym = fullname; Index: route.t ================================================================== --- route.t +++ route.t @@ -20,14 +20,51 @@ co:complain(403,'blocked','you cannot follow a user you are blocked by') return end end if act:cmp('circle') then lib.dbg('encircling user!') + var allcircs = co.srv:circle_search(&co.srv.pool, co.who.id, 0) + var mycircs = co.srv:circle_memberships_uid(&co.srv.pool, co.who.id, actor.id) + var marked = co.srv.pool:alloc(bool, allcircs.ct) + var member = co.srv.pool:alloc(bool, allcircs.ct) + for i = 0, marked.ct do + marked(i) = false + member(i) = false + -- search through list of memberships to see if this circle is in them + -- if it is, set its membership flag + for j = 0, mycircs.ct do + if mycircs(j).cid == allcircs(i).cid then + member(i) = true + end + end + end + + -- which circles did the user mark this time? var iter = co:eachpostv('circle') for cid in iter do + var decode, ok = lib.math.shorthand.parse(cid.ptr, cid.ct) + if ok then + for i=0, allcircs.ct do + if allcircs(i).cid == decode then + marked(i) = true + end + end + end + end + -- compute the differential and carry out the appropriate action + for i = 0, marked.ct do + if marked(i) ~= member(i) then + if marked(i) then -- newly marked, add + co.srv:circle_members_add_uid(allcircs(i).cid, actor.id) + elseif member(i) then -- unmarked, remove + co.srv:circle_members_del_uid(allcircs(i).cid, actor.id) + end + end end + + -- thanks html for making this all so complicated 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 @@ -51,11 +88,16 @@ else rel.rel:clear() rel.recip:clear() end - lib.render.user_page(co, actor, &rel) + var go = co:pgetv('go') + if not go or go(0) ~= @'/' then + lib.render.user_page(co, actor, &rel) + else + co:reroute(go.ptr) + end end terra http.actor_profile_xid(co: &lib.srv.convo, uri: lib.mem.ptr(int8), meth: method.t) var handle = [lib.mem.ptr(int8)] { ptr = &uri.ptr[2], ct = 0 } for i=2,uri.ct do ADDED static/icon.svg Index: static/icon.svg ================================================================== --- static/icon.svg +++ static/icon.svg @@ -0,0 +1,178 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + image/svg+xml + + + + + + + + + + + + Index: static/style.scss ================================================================== --- static/style.scss +++ static/style.scss @@ -91,10 +91,11 @@ otone(-41%), otone(-43%) 15%, otone(-46%) 75%, otone(-50%) ); + background-repeat: no-repeat; // necessary to keep gradients from glitching out under failfucks &:hover, &:focus { @extend %glow; outline: none; color: tone(-55%); text-shadow: none; @@ -261,10 +262,11 @@ > a[href].gear { content: url(/s/gear.svg); } > a[href].pen { content: url(/s/pen.svg); } } } } + main { @extend %content; display: block; position: relative; @@ -294,10 +296,12 @@ } } body.profile { #rel { + .check-panel { margin-top: 0.6em; } + .check-panel + menu { margin-bottom: 2em; } menu { display: grid; grid-template-columns: 1fr 1fr; grid-template-rows: repeat(max-content); grid-gap: 0.1in; @@ -304,12 +308,13 @@ > .opt { padding: 0.1in; border-radius: 5px; border: 1px solid transparent; &.on { - background-color: tone(-30%, -0.7); - border-color: tone(-20%) transparent; + background: linear-gradient(to bottom, tone(-30%, -0.7), transparent 80%); + background-repeat: no-repeat; + border-top-color: tone(-30%); } > 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; @@ -1267,5 +1272,9 @@ background-position: 0 0; } } } } + +.modal .check-panel { + > label { margin: 0.1em; } +} Index: view/docskel.tpl ================================================================== --- view/docskel.tpl +++ view/docskel.tpl @@ -1,11 +1,11 @@ @instance :: @title - +

    @title

    Index: view/profile.tpl ================================================================== --- view/profile.tpl +++ view/profile.tpl @@ -34,11 +34,14 @@ close
    @relations
    @circles
    - + + + +
    sanctions @sanctions