Fossil SCM

Add a new subscription option to receive edits to forum posts. If this option is not selected, then alerts are only sent on the initial post, not on edits. Also: Use the "forumObs" class on timeline forum text that has been subsequently edited.

drh 2020-03-26 18:54 trunk
Commit e5653a4ceb9049b2b5f738224d9fecdcbec10e2169427bb9fb7c5d722b12453e
+26 -13
--- src/alerts.c
+++ src/alerts.c
@@ -1524,11 +1524,11 @@
15241524
** to know the subscriber code.
15251525
*/
15261526
void alert_page(void){
15271527
const char *zName = P("name");
15281528
Stmt q;
1529
- int sa, sc, sf, st, sw;
1529
+ int sa, sc, sf, st, sw, sx;
15301530
int sdigest, sdonotcall, sverified;
15311531
int isLogin; /* Logged in as an individual */
15321532
const char *ssub = 0;
15331533
const char *semail;
15341534
const char *smip;
@@ -1565,10 +1565,11 @@
15651565
if( PB("sa") ) newSsub[nsub++] = 'a';
15661566
if( g.perm.Read && PB("sc") ) newSsub[nsub++] = 'c';
15671567
if( g.perm.RdForum && PB("sf") ) newSsub[nsub++] = 'f';
15681568
if( g.perm.RdTkt && PB("st") ) newSsub[nsub++] = 't';
15691569
if( g.perm.RdWiki && PB("sw") ) newSsub[nsub++] = 'w';
1570
+ if( g.perm.RdForum && PB("sx") ) newSsub[nsub++] = 'x';
15701571
newSsub[nsub] = 0;
15711572
ssub = newSsub;
15721573
blob_init(&update, "UPDATE subscriber SET", -1);
15731574
blob_append_sql(&update,
15741575
" sdonotcall=%d,"
@@ -1646,10 +1647,11 @@
16461647
sa = strchr(ssub,'a')!=0;
16471648
sc = strchr(ssub,'c')!=0;
16481649
sf = strchr(ssub,'f')!=0;
16491650
st = strchr(ssub,'t')!=0;
16501651
sw = strchr(ssub,'w')!=0;
1652
+ sx = strchr(ssub,'x')!=0;
16511653
smip = db_column_text(&q, 5);
16521654
mtime = db_column_text(&q, 7);
16531655
sctime = db_column_text(&q, 8);
16541656
if( !g.perm.Admin && !sverified ){
16551657
db_multi_exec(
@@ -1715,10 +1717,12 @@
17151717
@ Check-ins</label><br>
17161718
}
17171719
if( g.perm.RdForum ){
17181720
@ <label><input type="checkbox" name="sf" %s(sf?"checked":"")>\
17191721
@ Forum Posts</label><br>
1722
+ @ <label><input type="checkbox" name="sx" %s(sx?"checked":"")>\
1723
+ @ Forum Edits</label><br>
17201724
}
17211725
if( g.perm.RdTkt ){
17221726
@ <label><input type="checkbox" name="st" %s(st?"checked":"")>\
17231727
@ Ticket changes</label><br>
17241728
}
@@ -2004,13 +2008,21 @@
20042008
20052009
#if LOCAL_INTERFACE
20062010
/*
20072011
** A single event that might appear in an alert is recorded as an
20082012
** instance of the following object.
2013
+**
2014
+** type values:
2015
+**
2016
+** c A new check-in
2017
+** f An original forum post
2018
+** x An edit to a prior forum post
2019
+** t A new ticket or a change to an existing ticket
2020
+** w A change to a wiki page
20092021
*/
20102022
struct EmailEvent {
2011
- int type; /* 'c', 'f', 'm', 't', 'w' */
2023
+ int type; /* 'c', 'f', 't', 'w', 'x' */
20122024
int needMod; /* Pending moderator approval */
20132025
Blob hdr; /* Header content, for forum entries */
20142026
Blob txt; /* Text description to appear in an alert */
20152027
char *zFromName; /* Human name of the sender */
20162028
EmailEvent *pNext; /* Next in chronological order */
@@ -2085,20 +2097,20 @@
20852097
p->needMod = db_column_int(&q, 4);
20862098
p->zFromName = 0;
20872099
p->pNext = 0;
20882100
switch( p->type ){
20892101
case 'c': zType = "Check-In"; break;
2090
- case 'f': zType = "Forum post"; break;
2102
+ /* case 'f': -- forum posts omitted from this loop. See below */
20912103
case 't': zType = "Ticket Change"; break;
20922104
case 'w': zType = "Wiki Edit"; break;
20932105
}
20942106
blob_init(&p->hdr, 0, 0);
20952107
blob_init(&p->txt, 0, 0);
20962108
blob_appendf(&p->txt,"== %s %s ==\n%s\n%s/info/%.20s\n",
20972109
db_column_text(&q,1),
20982110
zType,
2099
- db_column_text(&q,2),
2111
+ db_column_text(&q, 2),
21002112
zUrl,
21012113
db_column_text(&q,0)
21022114
);
21032115
if( p->needMod ){
21042116
blob_appendf(&p->txt,
@@ -2130,11 +2142,12 @@
21302142
" (SELECT uuid FROM blob WHERE rid=forumpost.fpid)," /* 1 */
21312143
" datetime(event.mtime)," /* 2 */
21322144
" substr(comment,instr(comment,':')+2)," /* 3 */
21332145
" (SELECT uuid FROM blob WHERE rid=forumpost.firt)," /* 4 */
21342146
" wantalert.needMod," /* 5 */
2135
- " coalesce(trim(substr(info,1,instr(info,'<')-1)),euser,user)" /* 6 */
2147
+ " coalesce(trim(substr(info,1,instr(info,'<')-1)),euser,user)," /* 6 */
2148
+ " forumpost.fprev IS NULL" /* 7 */
21362149
" FROM temp.wantalert, event, forumpost"
21372150
" LEFT JOIN user ON (login=coalesce(euser,user))"
21382151
" WHERE event.objid=substr(wantalert.eventId,2)+0"
21392152
" AND eventId GLOB 'f*'"
21402153
" AND forumpost.fpid=event.objid"
@@ -2150,11 +2163,11 @@
21502163
const char *z;
21512164
if( pPost==0 ) continue;
21522165
p = fossil_malloc( sizeof(EmailEvent) );
21532166
pLast->pNext = p;
21542167
pLast = p;
2155
- p->type = 'f';
2168
+ p->type = db_column_int(&q,7) ? 'f' : 'x';
21562169
p->needMod = db_column_int(&q, 5);
21572170
z = db_column_text(&q,6);
21582171
p->zFromName = z && z[0] ? fossil_strdup(z) : 0;
21592172
p->pNext = 0;
21602173
blob_init(&p->hdr, 0, 0);
@@ -2482,13 +2495,13 @@
24822495
** if the recipient is a moderator for that type of event. Setup
24832496
** and Admin users always get notified. */
24842497
char xType = '*';
24852498
if( strpbrk(zCap,"as")==0 ){
24862499
switch( p->type ){
2487
- case 'f': xType = '5'; break;
2488
- case 't': xType = 'q'; break;
2489
- case 'w': xType = 'l'; break;
2500
+ case 'x': case 'f': xType = '5'; break;
2501
+ case 't': xType = 'q'; break;
2502
+ case 'w': xType = 'l'; break;
24902503
}
24912504
if( strchr(zCap,xType)==0 ) continue;
24922505
}
24932506
}else if( strchr(zCap,'s')!=0 || strchr(zCap,'a')!=0 ){
24942507
/* Setup and admin users can get any notification that does not
@@ -2496,14 +2509,14 @@
24962509
}else{
24972510
/* Other users only see the alert if they have sufficient
24982511
** privilege to view the event itself */
24992512
char xType = '*';
25002513
switch( p->type ){
2501
- case 'c': xType = 'o'; break;
2502
- case 'f': xType = '2'; break;
2503
- case 't': xType = 'r'; break;
2504
- case 'w': xType = 'j'; break;
2514
+ case 'c': xType = 'o'; break;
2515
+ case 'x': case 'f': xType = '2'; break;
2516
+ case 't': xType = 'r'; break;
2517
+ case 'w': xType = 'j'; break;
25052518
}
25062519
if( strchr(zCap,xType)==0 ) continue;
25072520
}
25082521
if( blob_size(&p->hdr)>0 ){
25092522
/* This alert should be sent as a separate email */
25102523
--- src/alerts.c
+++ src/alerts.c
@@ -1524,11 +1524,11 @@
1524 ** to know the subscriber code.
1525 */
1526 void alert_page(void){
1527 const char *zName = P("name");
1528 Stmt q;
1529 int sa, sc, sf, st, sw;
1530 int sdigest, sdonotcall, sverified;
1531 int isLogin; /* Logged in as an individual */
1532 const char *ssub = 0;
1533 const char *semail;
1534 const char *smip;
@@ -1565,10 +1565,11 @@
1565 if( PB("sa") ) newSsub[nsub++] = 'a';
1566 if( g.perm.Read && PB("sc") ) newSsub[nsub++] = 'c';
1567 if( g.perm.RdForum && PB("sf") ) newSsub[nsub++] = 'f';
1568 if( g.perm.RdTkt && PB("st") ) newSsub[nsub++] = 't';
1569 if( g.perm.RdWiki && PB("sw") ) newSsub[nsub++] = 'w';
 
1570 newSsub[nsub] = 0;
1571 ssub = newSsub;
1572 blob_init(&update, "UPDATE subscriber SET", -1);
1573 blob_append_sql(&update,
1574 " sdonotcall=%d,"
@@ -1646,10 +1647,11 @@
1646 sa = strchr(ssub,'a')!=0;
1647 sc = strchr(ssub,'c')!=0;
1648 sf = strchr(ssub,'f')!=0;
1649 st = strchr(ssub,'t')!=0;
1650 sw = strchr(ssub,'w')!=0;
 
1651 smip = db_column_text(&q, 5);
1652 mtime = db_column_text(&q, 7);
1653 sctime = db_column_text(&q, 8);
1654 if( !g.perm.Admin && !sverified ){
1655 db_multi_exec(
@@ -1715,10 +1717,12 @@
1715 @ Check-ins</label><br>
1716 }
1717 if( g.perm.RdForum ){
1718 @ <label><input type="checkbox" name="sf" %s(sf?"checked":"")>\
1719 @ Forum Posts</label><br>
 
 
1720 }
1721 if( g.perm.RdTkt ){
1722 @ <label><input type="checkbox" name="st" %s(st?"checked":"")>\
1723 @ Ticket changes</label><br>
1724 }
@@ -2004,13 +2008,21 @@
2004
2005 #if LOCAL_INTERFACE
2006 /*
2007 ** A single event that might appear in an alert is recorded as an
2008 ** instance of the following object.
 
 
 
 
 
 
 
 
2009 */
2010 struct EmailEvent {
2011 int type; /* 'c', 'f', 'm', 't', 'w' */
2012 int needMod; /* Pending moderator approval */
2013 Blob hdr; /* Header content, for forum entries */
2014 Blob txt; /* Text description to appear in an alert */
2015 char *zFromName; /* Human name of the sender */
2016 EmailEvent *pNext; /* Next in chronological order */
@@ -2085,20 +2097,20 @@
2085 p->needMod = db_column_int(&q, 4);
2086 p->zFromName = 0;
2087 p->pNext = 0;
2088 switch( p->type ){
2089 case 'c': zType = "Check-In"; break;
2090 case 'f': zType = "Forum post"; break;
2091 case 't': zType = "Ticket Change"; break;
2092 case 'w': zType = "Wiki Edit"; break;
2093 }
2094 blob_init(&p->hdr, 0, 0);
2095 blob_init(&p->txt, 0, 0);
2096 blob_appendf(&p->txt,"== %s %s ==\n%s\n%s/info/%.20s\n",
2097 db_column_text(&q,1),
2098 zType,
2099 db_column_text(&q,2),
2100 zUrl,
2101 db_column_text(&q,0)
2102 );
2103 if( p->needMod ){
2104 blob_appendf(&p->txt,
@@ -2130,11 +2142,12 @@
2130 " (SELECT uuid FROM blob WHERE rid=forumpost.fpid)," /* 1 */
2131 " datetime(event.mtime)," /* 2 */
2132 " substr(comment,instr(comment,':')+2)," /* 3 */
2133 " (SELECT uuid FROM blob WHERE rid=forumpost.firt)," /* 4 */
2134 " wantalert.needMod," /* 5 */
2135 " coalesce(trim(substr(info,1,instr(info,'<')-1)),euser,user)" /* 6 */
 
2136 " FROM temp.wantalert, event, forumpost"
2137 " LEFT JOIN user ON (login=coalesce(euser,user))"
2138 " WHERE event.objid=substr(wantalert.eventId,2)+0"
2139 " AND eventId GLOB 'f*'"
2140 " AND forumpost.fpid=event.objid"
@@ -2150,11 +2163,11 @@
2150 const char *z;
2151 if( pPost==0 ) continue;
2152 p = fossil_malloc( sizeof(EmailEvent) );
2153 pLast->pNext = p;
2154 pLast = p;
2155 p->type = 'f';
2156 p->needMod = db_column_int(&q, 5);
2157 z = db_column_text(&q,6);
2158 p->zFromName = z && z[0] ? fossil_strdup(z) : 0;
2159 p->pNext = 0;
2160 blob_init(&p->hdr, 0, 0);
@@ -2482,13 +2495,13 @@
2482 ** if the recipient is a moderator for that type of event. Setup
2483 ** and Admin users always get notified. */
2484 char xType = '*';
2485 if( strpbrk(zCap,"as")==0 ){
2486 switch( p->type ){
2487 case 'f': xType = '5'; break;
2488 case 't': xType = 'q'; break;
2489 case 'w': xType = 'l'; break;
2490 }
2491 if( strchr(zCap,xType)==0 ) continue;
2492 }
2493 }else if( strchr(zCap,'s')!=0 || strchr(zCap,'a')!=0 ){
2494 /* Setup and admin users can get any notification that does not
@@ -2496,14 +2509,14 @@
2496 }else{
2497 /* Other users only see the alert if they have sufficient
2498 ** privilege to view the event itself */
2499 char xType = '*';
2500 switch( p->type ){
2501 case 'c': xType = 'o'; break;
2502 case 'f': xType = '2'; break;
2503 case 't': xType = 'r'; break;
2504 case 'w': xType = 'j'; break;
2505 }
2506 if( strchr(zCap,xType)==0 ) continue;
2507 }
2508 if( blob_size(&p->hdr)>0 ){
2509 /* This alert should be sent as a separate email */
2510
--- src/alerts.c
+++ src/alerts.c
@@ -1524,11 +1524,11 @@
1524 ** to know the subscriber code.
1525 */
1526 void alert_page(void){
1527 const char *zName = P("name");
1528 Stmt q;
1529 int sa, sc, sf, st, sw, sx;
1530 int sdigest, sdonotcall, sverified;
1531 int isLogin; /* Logged in as an individual */
1532 const char *ssub = 0;
1533 const char *semail;
1534 const char *smip;
@@ -1565,10 +1565,11 @@
1565 if( PB("sa") ) newSsub[nsub++] = 'a';
1566 if( g.perm.Read && PB("sc") ) newSsub[nsub++] = 'c';
1567 if( g.perm.RdForum && PB("sf") ) newSsub[nsub++] = 'f';
1568 if( g.perm.RdTkt && PB("st") ) newSsub[nsub++] = 't';
1569 if( g.perm.RdWiki && PB("sw") ) newSsub[nsub++] = 'w';
1570 if( g.perm.RdForum && PB("sx") ) newSsub[nsub++] = 'x';
1571 newSsub[nsub] = 0;
1572 ssub = newSsub;
1573 blob_init(&update, "UPDATE subscriber SET", -1);
1574 blob_append_sql(&update,
1575 " sdonotcall=%d,"
@@ -1646,10 +1647,11 @@
1647 sa = strchr(ssub,'a')!=0;
1648 sc = strchr(ssub,'c')!=0;
1649 sf = strchr(ssub,'f')!=0;
1650 st = strchr(ssub,'t')!=0;
1651 sw = strchr(ssub,'w')!=0;
1652 sx = strchr(ssub,'x')!=0;
1653 smip = db_column_text(&q, 5);
1654 mtime = db_column_text(&q, 7);
1655 sctime = db_column_text(&q, 8);
1656 if( !g.perm.Admin && !sverified ){
1657 db_multi_exec(
@@ -1715,10 +1717,12 @@
1717 @ Check-ins</label><br>
1718 }
1719 if( g.perm.RdForum ){
1720 @ <label><input type="checkbox" name="sf" %s(sf?"checked":"")>\
1721 @ Forum Posts</label><br>
1722 @ <label><input type="checkbox" name="sx" %s(sx?"checked":"")>\
1723 @ Forum Edits</label><br>
1724 }
1725 if( g.perm.RdTkt ){
1726 @ <label><input type="checkbox" name="st" %s(st?"checked":"")>\
1727 @ Ticket changes</label><br>
1728 }
@@ -2004,13 +2008,21 @@
2008
2009 #if LOCAL_INTERFACE
2010 /*
2011 ** A single event that might appear in an alert is recorded as an
2012 ** instance of the following object.
2013 **
2014 ** type values:
2015 **
2016 ** c A new check-in
2017 ** f An original forum post
2018 ** x An edit to a prior forum post
2019 ** t A new ticket or a change to an existing ticket
2020 ** w A change to a wiki page
2021 */
2022 struct EmailEvent {
2023 int type; /* 'c', 'f', 't', 'w', 'x' */
2024 int needMod; /* Pending moderator approval */
2025 Blob hdr; /* Header content, for forum entries */
2026 Blob txt; /* Text description to appear in an alert */
2027 char *zFromName; /* Human name of the sender */
2028 EmailEvent *pNext; /* Next in chronological order */
@@ -2085,20 +2097,20 @@
2097 p->needMod = db_column_int(&q, 4);
2098 p->zFromName = 0;
2099 p->pNext = 0;
2100 switch( p->type ){
2101 case 'c': zType = "Check-In"; break;
2102 /* case 'f': -- forum posts omitted from this loop. See below */
2103 case 't': zType = "Ticket Change"; break;
2104 case 'w': zType = "Wiki Edit"; break;
2105 }
2106 blob_init(&p->hdr, 0, 0);
2107 blob_init(&p->txt, 0, 0);
2108 blob_appendf(&p->txt,"== %s %s ==\n%s\n%s/info/%.20s\n",
2109 db_column_text(&q,1),
2110 zType,
2111 db_column_text(&q, 2),
2112 zUrl,
2113 db_column_text(&q,0)
2114 );
2115 if( p->needMod ){
2116 blob_appendf(&p->txt,
@@ -2130,11 +2142,12 @@
2142 " (SELECT uuid FROM blob WHERE rid=forumpost.fpid)," /* 1 */
2143 " datetime(event.mtime)," /* 2 */
2144 " substr(comment,instr(comment,':')+2)," /* 3 */
2145 " (SELECT uuid FROM blob WHERE rid=forumpost.firt)," /* 4 */
2146 " wantalert.needMod," /* 5 */
2147 " coalesce(trim(substr(info,1,instr(info,'<')-1)),euser,user)," /* 6 */
2148 " forumpost.fprev IS NULL" /* 7 */
2149 " FROM temp.wantalert, event, forumpost"
2150 " LEFT JOIN user ON (login=coalesce(euser,user))"
2151 " WHERE event.objid=substr(wantalert.eventId,2)+0"
2152 " AND eventId GLOB 'f*'"
2153 " AND forumpost.fpid=event.objid"
@@ -2150,11 +2163,11 @@
2163 const char *z;
2164 if( pPost==0 ) continue;
2165 p = fossil_malloc( sizeof(EmailEvent) );
2166 pLast->pNext = p;
2167 pLast = p;
2168 p->type = db_column_int(&q,7) ? 'f' : 'x';
2169 p->needMod = db_column_int(&q, 5);
2170 z = db_column_text(&q,6);
2171 p->zFromName = z && z[0] ? fossil_strdup(z) : 0;
2172 p->pNext = 0;
2173 blob_init(&p->hdr, 0, 0);
@@ -2482,13 +2495,13 @@
2495 ** if the recipient is a moderator for that type of event. Setup
2496 ** and Admin users always get notified. */
2497 char xType = '*';
2498 if( strpbrk(zCap,"as")==0 ){
2499 switch( p->type ){
2500 case 'x': case 'f': xType = '5'; break;
2501 case 't': xType = 'q'; break;
2502 case 'w': xType = 'l'; break;
2503 }
2504 if( strchr(zCap,xType)==0 ) continue;
2505 }
2506 }else if( strchr(zCap,'s')!=0 || strchr(zCap,'a')!=0 ){
2507 /* Setup and admin users can get any notification that does not
@@ -2496,14 +2509,14 @@
2509 }else{
2510 /* Other users only see the alert if they have sufficient
2511 ** privilege to view the event itself */
2512 char xType = '*';
2513 switch( p->type ){
2514 case 'c': xType = 'o'; break;
2515 case 'x': case 'f': xType = '2'; break;
2516 case 't': xType = 'r'; break;
2517 case 'w': xType = 'j'; break;
2518 }
2519 if( strchr(zCap,xType)==0 ) continue;
2520 }
2521 if( blob_size(&p->hdr)>0 ){
2522 /* This alert should be sent as a separate email */
2523
+17
--- src/forum.c
+++ src/forum.c
@@ -57,10 +57,27 @@
5757
ForumEntry *pDisplay; /* Entries in display order */
5858
ForumEntry *pTail; /* Last on the display list */
5959
int mxIndent; /* Maximum indentation level */
6060
};
6161
#endif /* INTERFACE */
62
+
63
+/*
64
+** Return true if the forum entry with the given rid has been
65
+** subsequently edited.
66
+*/
67
+int forum_rid_has_been_edited(int rid){
68
+ static Stmt q;
69
+ int res;
70
+ db_static_prepare(&q,
71
+ "SELECT 1 FROM forumpost A, forumpost B"
72
+ " WHERE A.fpid=$rid AND B.froot=A.froot AND B.fprev=$rid"
73
+ );
74
+ db_bind_int(&q, "$rid", rid);
75
+ res = db_step(&q)==SQLITE_ROW;
76
+ db_reset(&q);
77
+ return res;
78
+}
6279
6380
/*
6481
** Delete a complete ForumThread and all its entries.
6582
*/
6683
static void forumthread_delete(ForumThread *pThread){
6784
--- src/forum.c
+++ src/forum.c
@@ -57,10 +57,27 @@
57 ForumEntry *pDisplay; /* Entries in display order */
58 ForumEntry *pTail; /* Last on the display list */
59 int mxIndent; /* Maximum indentation level */
60 };
61 #endif /* INTERFACE */
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
62
63 /*
64 ** Delete a complete ForumThread and all its entries.
65 */
66 static void forumthread_delete(ForumThread *pThread){
67
--- src/forum.c
+++ src/forum.c
@@ -57,10 +57,27 @@
57 ForumEntry *pDisplay; /* Entries in display order */
58 ForumEntry *pTail; /* Last on the display list */
59 int mxIndent; /* Maximum indentation level */
60 };
61 #endif /* INTERFACE */
62
63 /*
64 ** Return true if the forum entry with the given rid has been
65 ** subsequently edited.
66 */
67 int forum_rid_has_been_edited(int rid){
68 static Stmt q;
69 int res;
70 db_static_prepare(&q,
71 "SELECT 1 FROM forumpost A, forumpost B"
72 " WHERE A.fpid=$rid AND B.froot=A.froot AND B.fprev=$rid"
73 );
74 db_bind_int(&q, "$rid", rid);
75 res = db_step(&q)==SQLITE_ROW;
76 db_reset(&q);
77 return res;
78 }
79
80 /*
81 ** Delete a complete ForumThread and all its entries.
82 */
83 static void forumthread_delete(ForumThread *pThread){
84
+5 -1
--- src/timeline.c
+++ src/timeline.c
@@ -794,11 +794,15 @@
794794
&& zType[0]=='f' && g.perm.Hyperlink
795795
&& (!content_is_private(rid) || g.perm.ModForum)
796796
){
797797
Manifest *pPost = manifest_get(rid, CFTYPE_FORUM, 0);
798798
if( pPost ){
799
- forum_render(0, pPost->zMimetype, pPost->zWiki, "forumTimeline");
799
+ const char *zClass = "forumTimeline";
800
+ if( forum_rid_has_been_edited(rid) ){
801
+ zClass = "forumTimeline forumObs";
802
+ }
803
+ forum_render(0, pPost->zMimetype, pPost->zWiki, zClass);
800804
manifest_destroy(pPost);
801805
}
802806
}
803807
}
804808
if( suppressCnt ){
805809
--- src/timeline.c
+++ src/timeline.c
@@ -794,11 +794,15 @@
794 && zType[0]=='f' && g.perm.Hyperlink
795 && (!content_is_private(rid) || g.perm.ModForum)
796 ){
797 Manifest *pPost = manifest_get(rid, CFTYPE_FORUM, 0);
798 if( pPost ){
799 forum_render(0, pPost->zMimetype, pPost->zWiki, "forumTimeline");
 
 
 
 
800 manifest_destroy(pPost);
801 }
802 }
803 }
804 if( suppressCnt ){
805
--- src/timeline.c
+++ src/timeline.c
@@ -794,11 +794,15 @@
794 && zType[0]=='f' && g.perm.Hyperlink
795 && (!content_is_private(rid) || g.perm.ModForum)
796 ){
797 Manifest *pPost = manifest_get(rid, CFTYPE_FORUM, 0);
798 if( pPost ){
799 const char *zClass = "forumTimeline";
800 if( forum_rid_has_been_edited(rid) ){
801 zClass = "forumTimeline forumObs";
802 }
803 forum_render(0, pPost->zMimetype, pPost->zWiki, zClass);
804 manifest_destroy(pPost);
805 }
806 }
807 }
808 if( suppressCnt ){
809

Keyboard Shortcuts

Open search /
Next entry (timeline) j
Previous entry (timeline) k
Open focused entry Enter
Show this help ?
Toggle theme Top nav button