Index: backend/pgsql.t
==================================================================
--- backend/pgsql.t
+++ backend/pgsql.t
@@ -284,10 +284,34 @@
params = {uint64}, sql = [[
select (notice).* from pg_temp.parsavpg_notices
where rcpt = $1::bigint
]];
};
+
+ circle_search = {
+ params = {uint64,uint64}, sql = [[
+ select name, id, owner, array_length(members,1) from parsav_circles where
+ ($1::bigint = 0 or $1::bigint = owner) and
+ ($2::bigint = 0 or $2::bigint = id)
+ ]];
+ };
+
+ circle_members_fetch_cid = {
+ params = {uint64, uint64}, sql = [[
+ select unnest(members) from parsav_circles where
+ ($1::bigint = 0 or owner = $1::bigint) and
+ id = $2::bigint
+ ]];
+ };
+
+ circle_members_fetch_name = {
+ params = {uint64, pstring}, sql = [[
+ select unnest(members) from parsav_circles where
+ ($1::bigint = 0 or owner = $1::bigint) and
+ name = $2::text
+ ]];
+ };
auth_sigtime_user_fetch = {
params = {uint64}, sql = [[
select authtime::bigint
from parsav_actors where id = $1::bigint
@@ -2037,10 +2061,50 @@
end];
actor_conf_int_set = [terra(src: &lib.store.source, uid: uint64, key: rawstring, value: uint64): {}
queries.actor_conf_int_set.exec(src,uid,key,value) end];
actor_conf_int_reset = [terra(src: &lib.store.source, uid: uint64, key: rawstring): {}
queries.actor_conf_int_reset.exec(src,uid,key) end];
+
+ circle_search = [terra(
+ src: &lib.store.source,
+ pool:&lib.mem.pool,
+ uid: uint64,
+ cid: uint64
+ ): lib.mem.ptr(lib.store.circle)
+ var res = queries.circle_search.exec(src, uid, cid)
+ if res.sz == 0 then return [lib.mem.ptr(lib.store.circle)].null() end
+ defer res:free()
+
+ var rt = pool:alloc(lib.store.circle, res.sz)
+ for i = 0, res.sz do
+ var name = res:_string(i,0)
+ rt(i) = lib.store.circle {
+ name = name:pdup(pool);
+ cid = res:int(uint64,i,1);
+ owner = res:int(uint64,i,2);
+ memcount = res:int(uint64,i,3);
+ }
+ end
+
+ return rt
+ end];
+
+ circle_members_fetch_cid = [terra(
+ src: &lib.store.source,
+ pool:&lib.mem.pool,
+ uid: uint64,
+ cid: uint64
+ ): lib.mem.ptr(uint64)
+ var res = queries.circle_members_fetch_cid.exec(src,uid,cid)
+ if res.sz == 0 then return [lib.mem.ptr(uint64)].null() end
+ defer res:free()
+
+ var rt = pool:alloc(uint64, res.sz)
+ for i = 0, res.sz do rt(i) = res:int(uint64,i,0) end
+
+ return rt
+ end];
actor_auth_register_uid = nil; -- TODO better support non-view based auth
}
return b
Index: mem.t
==================================================================
--- mem.t
+++ mem.t
@@ -107,11 +107,14 @@
return self.ptr
end
terra t.methods.null(): t return t { ptr = nil, ct = 0 } end -- maybe should be a macro?
terra t:ref() return self.ptr ~= nil end
t.metamethods.__not = macro(function(self) return `not self:ref() end)
- t.metamethods.__apply = macro(function(self,idx) return `self.ptr[idx] end)
+ t.metamethods.__apply = macro(function(self,idx) return `self.ptr[ [idx or 0] ] end)
+ t.metamethods.__update = macro(function(self,idx,rhs)
+ return quote self.ptr[idx] = rhs end end)
+
if not ty:isstruct() then
terra t:cmp_raw(other: &ty)
for i=0, self.ct do
if self.ptr[i] ~= other[i] then return false end
end
Index: render/timeline.t
==================================================================
--- render/timeline.t
+++ render/timeline.t
@@ -7,17 +7,25 @@
or m == modes.mutual
or m == modes.circle
end
local terra
-render_timeline(co: &lib.srv.convo, modestr: lib.mem.ref(int8))
+render_timeline(co: &lib.srv.convo, hpath: lib.mem.ptr(lib.mem.ref(int8)))
+ var modestr = lib.str.ref.null()
+ var spec = lib.str.ref.null()
+ if hpath.ct >= 2 then
+ modestr = hpath(1)
+ if hpath.ct >= 3 then spec = hpath(2) end
+ end
var mode = modes.follow
var circle: uint64 = 0
- if modestr:cmp('local') then mode = [modes['local']]
- elseif modestr:cmp('mutual') then mode = modes.mutual
- elseif modestr:cmp('fedi') then mode = modes.fedi
- elseif modestr:cmp('circle') then mode = modes.circle
+ if modestr:ref() then
+ if modestr:cmp('local' ) then mode = [modes['local']]
+ elseif modestr:cmp('mutual') then mode = modes.mutual
+ elseif modestr:cmp('fedi' ) then mode = modes.fedi
+ elseif modestr:cmp('circle') then mode = modes.circle
+ end
end
if requires_login(mode) and co.aid == 0 then mode = [modes['local']] end
var stoptime = lib.osclock.time(nil)
@@ -43,41 +51,58 @@
var modelinks = arrayof(pstr, [modes.members])
acc:lpush('
showing ')
for i=0, [modelabels.type.N] do
if co.aid ~= 0 or not requires_login(i) then
if i > 0 then acc:lpush(' ยท ') end
- if i == mode then
+ if i == mode and not (mode == modes.circle and spec:ref()) then
acc:lpush(''):ppush(modelabels[i]):lpush('')
else
acc:lpush(''):ppush(modelabels[i]):lpush('')
end
end
end
acc:lpush(' ')
- acc:lpush('')
var newest: lib.store.timepoint = 0
- for i = 0, posts.sz do
- var author = co:uid2actor(posts(i).ptr.author)
- if mode == modes.mutual and posts(i).ptr.author ~= co.who.id then
- if not author.relationship.recip.follow() then goto skip end
+ if mode == modes.circle and not spec then
+ var circles = co.srv:circle_search(&co.srv.pool, co.who.id, 0)
+ acc:lpush '
'
+ else
+ acc:lpush('
')
+ for i = 0, posts.sz do
+ var author = co:uid2actor(posts(i).ptr.author)
+ if mode == modes.mutual and posts(i).ptr.author ~= co.who.id then
+ if not author.relationship.recip.follow() then goto skip end
+ end
+ if author.relationship.rel.mute() or
+ author.relationship.rel.avoid() or
+ author.relationship.recip.exclude() then goto skip end
+ lib.render.tweet(co, posts(i).ptr, &acc)
+ var t = lib.math.biggest(lib.math.biggest(posts(i).ptr.posted, posts(i).ptr.discovered),posts(i).ptr.edited)
+ if t > newest then newest = t end
+ ::skip:: posts(i):free()
end
- if author.relationship.rel.mute() or
- author.relationship.rel.avoid() or
- author.relationship.recip.exclude() then goto skip end
- lib.render.tweet(co, posts(i).ptr, &acc)
- var t = lib.math.biggest(lib.math.biggest(posts(i).ptr.posted, posts(i).ptr.discovered),posts(i).ptr.edited)
- if t > newest then newest = t end
- ::skip:: posts(i):free()
+ if posts.run > 0 then posts:free() end
+ acc:lpush('
')
end
- if posts.run > 0 then posts:free() end
- acc:lpush('
')
var doc = [lib.srv.convo.page] {
title = 'timeline';
body = acc:finalize();
class = 'timeline';
cache = false;
}
- co:livepage(doc,newest)
+ if newest ~= 0
+ then co:livepage(doc,newest)
+ else co:stdpage(doc)
+ end
--doc.body:free()
end
return render_timeline
Index: route.t
==================================================================
--- route.t
+++ route.t
@@ -220,11 +220,11 @@
co:reroute(redirto.buf)
end
end
terra http.timeline(co: &lib.srv.convo, mode: hpath)
- lib.render.timeline(co,lib.trn(mode.ptr == nil, rstring{ptr=nil}, mode.ptr[1]))
+ lib.render.timeline(co,mode)
end
terra http.documentation(co: &lib.srv.convo, path: hpath)
if path.ct == 2 then
lib.render.docpage(co,path(1))
Index: store.t
==================================================================
--- store.t
+++ store.t
@@ -238,10 +238,18 @@
isreply: bool
source: &m.source
-- save :: bool -> {} (defined in acl.t due to dep. hell)
}
+
+struct m.circle {
+ cid: uint64
+ owner: uint64
+ name: lib.str.t
+-- ephemera
+ memcount: intptr
+}
struct m.artifact {
rid: uint64
owner: uint64
desc: str
@@ -463,10 +471,18 @@
-- emoji: pstring (null to delete previous reaction, otherwise adds/changes)
post_act_cancel: {&m.source, uint64} -> {}
post_liked_uid: {&m.source, uint64, uint64} -> bool
post_reacted_uid: {&m.source, uint64, uint64} -> bool
post_act_fetch_notice: {&m.source, uint64} -> m.notice
+
+ circle_search: {&m.source, &lib.mem.pool, uint64, uint64} -> lib.mem.ptr(m.circle)
+ circle_create: {&m.source, uint64, pstring} -> {}
+ circle_destroy: {&m.source, uint64, uint64} -> {}
+ circle_members_fetch_cid: {&m.source, &lib.mem.pool, uint64, uint64} -> lib.mem.ptr(uint64)
+ circle_members_fetch_name: {&m.source, &lib.mem.pool, uint64, pstring} -> lib.mem.ptr(uint64)
+ circle_members_add_uid: {&m.source, uint64, uint64} -> {}
+ circle_members_del_uid: {&m.source, uint64, uint64} -> {}
thread_latest_arrival_calc: {&m.source, uint64} -> m.timepoint
artifact_instantiate: {&m.source, lib.mem.ptr(uint8), lib.mem.ptr(int8)} -> uint64
-- instantiate an artifact in the database, either installing a new
Index: str.t
==================================================================
--- str.t
+++ str.t
@@ -30,11 +30,10 @@
maxlen = maxlen - 1
end
return str
end
-
do local strptr = (lib.mem.ptr(int8))
local strref = (lib.mem.ref(int8))
local byteptr = (lib.mem.ptr(uint8))
local function install_funcs(ty)
ty.metamethods.__cast = function(from,to,e)
@@ -44,10 +43,17 @@
elseif from == &int8 then
return `ty {ptr = e, ct = m.sz(e)}
elseif to == &int8 then
return e.ptr
end
+ end
+ terra ty:pdup(p: &lib.mem.pool): strptr
+ if not @self then return strptr.null() end
+ if self.ct == 0 then self.ct = m.sz(self.ptr) end
+ var newstr = p:alloc(int8, self.ct)
+ lib.mem.cpy(newstr.ptr, self.ptr, self.ct)
+ return newstr
end
terra ty:cmp(other: ty)
if self.ptr == nil and other.ptr == nil then return true end
if self.ptr == nil or other.ptr == nil then return false end