Fossil SCM
Enable the chronological forum display for all users able to read the forum. Make chronological the default display mode for mobile devices, as determined by the user-agent string.
Commit
c720327afe191528e0e62aa171fda8a19cf4154d87f16497d609dbe69277e0ba
Parent
6313d0a828d2b7a…
2 files changed
+12
+19
-13
+12
| --- src/cgi.c | ||
| +++ src/cgi.c | ||
| @@ -2067,5 +2067,17 @@ | ||
| 2067 | 2067 | int cgi_is_loopback(const char *zIpAddr){ |
| 2068 | 2068 | return fossil_strcmp(zIpAddr, "127.0.0.1")==0 || |
| 2069 | 2069 | fossil_strcmp(zIpAddr, "::ffff:127.0.0.1")==0 || |
| 2070 | 2070 | fossil_strcmp(zIpAddr, "::1")==0; |
| 2071 | 2071 | } |
| 2072 | + | |
| 2073 | +/* | |
| 2074 | +** Return true if the HTTP request is likely to be from a small-screen | |
| 2075 | +** mobile device. | |
| 2076 | +** | |
| 2077 | +** The returned value is a guess. Use it only for setting up defaults. | |
| 2078 | +*/ | |
| 2079 | +int cgi_from_mobile(void){ | |
| 2080 | + const char *zAgent = P("HTTP_USER_AGENT"); | |
| 2081 | + if( zAgent==0 ) return 0; | |
| 2082 | + return sqlite3_strlike("%mobile%", zAgent, 0)==0; | |
| 2083 | +} | |
| 2072 | 2084 |
| --- src/cgi.c | |
| +++ src/cgi.c | |
| @@ -2067,5 +2067,17 @@ | |
| 2067 | int cgi_is_loopback(const char *zIpAddr){ |
| 2068 | return fossil_strcmp(zIpAddr, "127.0.0.1")==0 || |
| 2069 | fossil_strcmp(zIpAddr, "::ffff:127.0.0.1")==0 || |
| 2070 | fossil_strcmp(zIpAddr, "::1")==0; |
| 2071 | } |
| 2072 |
| --- src/cgi.c | |
| +++ src/cgi.c | |
| @@ -2067,5 +2067,17 @@ | |
| 2067 | int cgi_is_loopback(const char *zIpAddr){ |
| 2068 | return fossil_strcmp(zIpAddr, "127.0.0.1")==0 || |
| 2069 | fossil_strcmp(zIpAddr, "::ffff:127.0.0.1")==0 || |
| 2070 | fossil_strcmp(zIpAddr, "::1")==0; |
| 2071 | } |
| 2072 | |
| 2073 | /* |
| 2074 | ** Return true if the HTTP request is likely to be from a small-screen |
| 2075 | ** mobile device. |
| 2076 | ** |
| 2077 | ** The returned value is a guess. Use it only for setting up defaults. |
| 2078 | */ |
| 2079 | int cgi_from_mobile(void){ |
| 2080 | const char *zAgent = P("HTTP_USER_AGENT"); |
| 2081 | if( zAgent==0 ) return 0; |
| 2082 | return sqlite3_strlike("%mobile%", zAgent, 0)==0; |
| 2083 | } |
| 2084 |
+19
-13
| --- src/forum.c | ||
| +++ src/forum.c | ||
| @@ -295,29 +295,29 @@ | ||
| 295 | 295 | } |
| 296 | 296 | zDate = db_text(0, "SELECT datetime(%.17g)", pPost->rDate); |
| 297 | 297 | @ <p>By %h(pPost->zUser) on %h(zDate) (%d(p->fpid)) |
| 298 | 298 | fossil_free(zDate); |
| 299 | 299 | if( p->pEdit ){ |
| 300 | - @ edit of %z(href("%R/forumpost/%S?t",p->pEdit->zUuid))%d(p->fprev)</a> | |
| 300 | + @ edit of %z(href("%R/forumpost/%S?t=c",p->pEdit->zUuid))%d(p->fprev)</a> | |
| 301 | 301 | } |
| 302 | 302 | if( p->firt ){ |
| 303 | 303 | ForumEntry *pIrt = p->pPrev; |
| 304 | 304 | while( pIrt && pIrt->fpid!=p->firt ) pIrt = pIrt->pPrev; |
| 305 | 305 | if( pIrt ){ |
| 306 | - @ reply to %z(href("%R/forumpost/%S?t",pIrt->zUuid))%d(p->firt)</a> | |
| 306 | + @ reply to %z(href("%R/forumpost/%S?t=c",pIrt->zUuid))%d(p->firt)</a> | |
| 307 | 307 | } |
| 308 | 308 | } |
| 309 | 309 | if( p->pLeaf ){ |
| 310 | - @ updated by %z(href("%R/forumpost/%S?t",p->pLeaf->zUuid))\ | |
| 310 | + @ updated by %z(href("%R/forumpost/%S?t=c",p->pLeaf->zUuid))\ | |
| 311 | 311 | @ %d(p->pLeaf->fpid)</a> |
| 312 | 312 | } |
| 313 | 313 | if( g.perm.Debug ){ |
| 314 | 314 | @ <span class="debug">\ |
| 315 | 315 | @ <a href="%R/artifact/%h(p->zUuid)">artifact</a></span> |
| 316 | 316 | } |
| 317 | 317 | if( p->fpid!=target ){ |
| 318 | - @ %z(href("%R/forumpost/%S?t",p->zUuid))[link]</a> | |
| 318 | + @ %z(href("%R/forumpost/%S?t=c",p->zUuid))[link]</a> | |
| 319 | 319 | } |
| 320 | 320 | isPrivate = content_is_private(p->fpid); |
| 321 | 321 | sameUser = notAnon && fossil_strcmp(pPost->zUser, g.zLogin)==0; |
| 322 | 322 | if( isPrivate && !g.perm.ModForum && !sameUser ){ |
| 323 | 323 | @ <p><span class="modpending">Awaiting Moderator Approval</span></p> |
| @@ -471,11 +471,12 @@ | ||
| 471 | 471 | ** selected posting into view after the page loads. |
| 472 | 472 | ** |
| 473 | 473 | ** Query parameters: |
| 474 | 474 | ** |
| 475 | 475 | ** name=X REQUIRED. The hash of the post to display |
| 476 | -** t Show a chronologic listing instead of hierarchical | |
| 476 | +** t=MODE Display mode. MODE is 'c' for chronological or | |
| 477 | +** 'h' for hierarchical, or 'a' for automatic. | |
| 477 | 478 | */ |
| 478 | 479 | void forumpost_page(void){ |
| 479 | 480 | forumthread_page(); |
| 480 | 481 | } |
| 481 | 482 | |
| @@ -487,16 +488,18 @@ | ||
| 487 | 488 | ** the postings in the thread are selected. |
| 488 | 489 | ** |
| 489 | 490 | ** Query parameters: |
| 490 | 491 | ** |
| 491 | 492 | ** name=X REQUIRED. The hash of any post of the thread. |
| 492 | -** t Show a chronologic listing instead of hierarchical | |
| 493 | +** t=MODE Display mode. MODE is 'c' for chronological or | |
| 494 | +** 'h' for hierarchical, or 'a' for automatic. | |
| 493 | 495 | */ |
| 494 | 496 | void forumthread_page(void){ |
| 495 | 497 | int fpid; |
| 496 | 498 | int froot; |
| 497 | 499 | const char *zName = P("name"); |
| 500 | + const char *zMode = PD("t","a"); | |
| 498 | 501 | login_check_credentials(); |
| 499 | 502 | if( !g.perm.RdForum ){ |
| 500 | 503 | login_needed(g.anon.RdForum); |
| 501 | 504 | return; |
| 502 | 505 | } |
| @@ -511,19 +514,22 @@ | ||
| 511 | 514 | froot = db_int(0, "SELECT froot FROM forumpost WHERE fpid=%d", fpid); |
| 512 | 515 | if( froot==0 ){ |
| 513 | 516 | webpage_error("Not a forum post: \"%s\"", zName); |
| 514 | 517 | } |
| 515 | 518 | if( fossil_strcmp(g.zPath,"forumthread")==0 ) fpid = 0; |
| 516 | - if( P("t") ){ | |
| 517 | - if( g.perm.Debug ){ | |
| 518 | - style_submenu_element("Hierarchical", "%R/%s/%s", g.zPath, zName); | |
| 519 | - } | |
| 519 | + if( zMode[0]=='a' ){ | |
| 520 | + if( cgi_from_mobile() ){ | |
| 521 | + zMode = "c"; /* Default to chronological on mobile */ | |
| 522 | + }else{ | |
| 523 | + zMode = "h"; | |
| 524 | + } | |
| 525 | + } | |
| 526 | + if( zMode[0]=='c' ){ | |
| 527 | + style_submenu_element("Hierarchical", "%R/%s/%s?t=h", g.zPath, zName); | |
| 520 | 528 | forum_display_chronological(froot, fpid); |
| 521 | 529 | }else{ |
| 522 | - if( g.perm.Debug ){ | |
| 523 | - style_submenu_element("Chronological", "%R/%s/%s?t", g.zPath, zName); | |
| 524 | - } | |
| 530 | + style_submenu_element("Chronological", "%R/%s/%s?t=c", g.zPath, zName); | |
| 525 | 531 | forum_display_hierarchical(froot, fpid); |
| 526 | 532 | } |
| 527 | 533 | style_load_js("forum.js"); |
| 528 | 534 | style_footer(); |
| 529 | 535 | } |
| 530 | 536 |
| --- src/forum.c | |
| +++ src/forum.c | |
| @@ -295,29 +295,29 @@ | |
| 295 | } |
| 296 | zDate = db_text(0, "SELECT datetime(%.17g)", pPost->rDate); |
| 297 | @ <p>By %h(pPost->zUser) on %h(zDate) (%d(p->fpid)) |
| 298 | fossil_free(zDate); |
| 299 | if( p->pEdit ){ |
| 300 | @ edit of %z(href("%R/forumpost/%S?t",p->pEdit->zUuid))%d(p->fprev)</a> |
| 301 | } |
| 302 | if( p->firt ){ |
| 303 | ForumEntry *pIrt = p->pPrev; |
| 304 | while( pIrt && pIrt->fpid!=p->firt ) pIrt = pIrt->pPrev; |
| 305 | if( pIrt ){ |
| 306 | @ reply to %z(href("%R/forumpost/%S?t",pIrt->zUuid))%d(p->firt)</a> |
| 307 | } |
| 308 | } |
| 309 | if( p->pLeaf ){ |
| 310 | @ updated by %z(href("%R/forumpost/%S?t",p->pLeaf->zUuid))\ |
| 311 | @ %d(p->pLeaf->fpid)</a> |
| 312 | } |
| 313 | if( g.perm.Debug ){ |
| 314 | @ <span class="debug">\ |
| 315 | @ <a href="%R/artifact/%h(p->zUuid)">artifact</a></span> |
| 316 | } |
| 317 | if( p->fpid!=target ){ |
| 318 | @ %z(href("%R/forumpost/%S?t",p->zUuid))[link]</a> |
| 319 | } |
| 320 | isPrivate = content_is_private(p->fpid); |
| 321 | sameUser = notAnon && fossil_strcmp(pPost->zUser, g.zLogin)==0; |
| 322 | if( isPrivate && !g.perm.ModForum && !sameUser ){ |
| 323 | @ <p><span class="modpending">Awaiting Moderator Approval</span></p> |
| @@ -471,11 +471,12 @@ | |
| 471 | ** selected posting into view after the page loads. |
| 472 | ** |
| 473 | ** Query parameters: |
| 474 | ** |
| 475 | ** name=X REQUIRED. The hash of the post to display |
| 476 | ** t Show a chronologic listing instead of hierarchical |
| 477 | */ |
| 478 | void forumpost_page(void){ |
| 479 | forumthread_page(); |
| 480 | } |
| 481 | |
| @@ -487,16 +488,18 @@ | |
| 487 | ** the postings in the thread are selected. |
| 488 | ** |
| 489 | ** Query parameters: |
| 490 | ** |
| 491 | ** name=X REQUIRED. The hash of any post of the thread. |
| 492 | ** t Show a chronologic listing instead of hierarchical |
| 493 | */ |
| 494 | void forumthread_page(void){ |
| 495 | int fpid; |
| 496 | int froot; |
| 497 | const char *zName = P("name"); |
| 498 | login_check_credentials(); |
| 499 | if( !g.perm.RdForum ){ |
| 500 | login_needed(g.anon.RdForum); |
| 501 | return; |
| 502 | } |
| @@ -511,19 +514,22 @@ | |
| 511 | froot = db_int(0, "SELECT froot FROM forumpost WHERE fpid=%d", fpid); |
| 512 | if( froot==0 ){ |
| 513 | webpage_error("Not a forum post: \"%s\"", zName); |
| 514 | } |
| 515 | if( fossil_strcmp(g.zPath,"forumthread")==0 ) fpid = 0; |
| 516 | if( P("t") ){ |
| 517 | if( g.perm.Debug ){ |
| 518 | style_submenu_element("Hierarchical", "%R/%s/%s", g.zPath, zName); |
| 519 | } |
| 520 | forum_display_chronological(froot, fpid); |
| 521 | }else{ |
| 522 | if( g.perm.Debug ){ |
| 523 | style_submenu_element("Chronological", "%R/%s/%s?t", g.zPath, zName); |
| 524 | } |
| 525 | forum_display_hierarchical(froot, fpid); |
| 526 | } |
| 527 | style_load_js("forum.js"); |
| 528 | style_footer(); |
| 529 | } |
| 530 |
| --- src/forum.c | |
| +++ src/forum.c | |
| @@ -295,29 +295,29 @@ | |
| 295 | } |
| 296 | zDate = db_text(0, "SELECT datetime(%.17g)", pPost->rDate); |
| 297 | @ <p>By %h(pPost->zUser) on %h(zDate) (%d(p->fpid)) |
| 298 | fossil_free(zDate); |
| 299 | if( p->pEdit ){ |
| 300 | @ edit of %z(href("%R/forumpost/%S?t=c",p->pEdit->zUuid))%d(p->fprev)</a> |
| 301 | } |
| 302 | if( p->firt ){ |
| 303 | ForumEntry *pIrt = p->pPrev; |
| 304 | while( pIrt && pIrt->fpid!=p->firt ) pIrt = pIrt->pPrev; |
| 305 | if( pIrt ){ |
| 306 | @ reply to %z(href("%R/forumpost/%S?t=c",pIrt->zUuid))%d(p->firt)</a> |
| 307 | } |
| 308 | } |
| 309 | if( p->pLeaf ){ |
| 310 | @ updated by %z(href("%R/forumpost/%S?t=c",p->pLeaf->zUuid))\ |
| 311 | @ %d(p->pLeaf->fpid)</a> |
| 312 | } |
| 313 | if( g.perm.Debug ){ |
| 314 | @ <span class="debug">\ |
| 315 | @ <a href="%R/artifact/%h(p->zUuid)">artifact</a></span> |
| 316 | } |
| 317 | if( p->fpid!=target ){ |
| 318 | @ %z(href("%R/forumpost/%S?t=c",p->zUuid))[link]</a> |
| 319 | } |
| 320 | isPrivate = content_is_private(p->fpid); |
| 321 | sameUser = notAnon && fossil_strcmp(pPost->zUser, g.zLogin)==0; |
| 322 | if( isPrivate && !g.perm.ModForum && !sameUser ){ |
| 323 | @ <p><span class="modpending">Awaiting Moderator Approval</span></p> |
| @@ -471,11 +471,12 @@ | |
| 471 | ** selected posting into view after the page loads. |
| 472 | ** |
| 473 | ** Query parameters: |
| 474 | ** |
| 475 | ** name=X REQUIRED. The hash of the post to display |
| 476 | ** t=MODE Display mode. MODE is 'c' for chronological or |
| 477 | ** 'h' for hierarchical, or 'a' for automatic. |
| 478 | */ |
| 479 | void forumpost_page(void){ |
| 480 | forumthread_page(); |
| 481 | } |
| 482 | |
| @@ -487,16 +488,18 @@ | |
| 488 | ** the postings in the thread are selected. |
| 489 | ** |
| 490 | ** Query parameters: |
| 491 | ** |
| 492 | ** name=X REQUIRED. The hash of any post of the thread. |
| 493 | ** t=MODE Display mode. MODE is 'c' for chronological or |
| 494 | ** 'h' for hierarchical, or 'a' for automatic. |
| 495 | */ |
| 496 | void forumthread_page(void){ |
| 497 | int fpid; |
| 498 | int froot; |
| 499 | const char *zName = P("name"); |
| 500 | const char *zMode = PD("t","a"); |
| 501 | login_check_credentials(); |
| 502 | if( !g.perm.RdForum ){ |
| 503 | login_needed(g.anon.RdForum); |
| 504 | return; |
| 505 | } |
| @@ -511,19 +514,22 @@ | |
| 514 | froot = db_int(0, "SELECT froot FROM forumpost WHERE fpid=%d", fpid); |
| 515 | if( froot==0 ){ |
| 516 | webpage_error("Not a forum post: \"%s\"", zName); |
| 517 | } |
| 518 | if( fossil_strcmp(g.zPath,"forumthread")==0 ) fpid = 0; |
| 519 | if( zMode[0]=='a' ){ |
| 520 | if( cgi_from_mobile() ){ |
| 521 | zMode = "c"; /* Default to chronological on mobile */ |
| 522 | }else{ |
| 523 | zMode = "h"; |
| 524 | } |
| 525 | } |
| 526 | if( zMode[0]=='c' ){ |
| 527 | style_submenu_element("Hierarchical", "%R/%s/%s?t=h", g.zPath, zName); |
| 528 | forum_display_chronological(froot, fpid); |
| 529 | }else{ |
| 530 | style_submenu_element("Chronological", "%R/%s/%s?t=c", g.zPath, zName); |
| 531 | forum_display_hierarchical(froot, fpid); |
| 532 | } |
| 533 | style_load_js("forum.js"); |
| 534 | style_footer(); |
| 535 | } |
| 536 |