Fossil SCM

Diff toggles: move the toggle-all button into the page-level diff UI controls (and add that area to the /ckout page) and only show the toggle-all option if more than one diff is being shown. Only show the Sync-sbs-diff preference checkbox when rendering sbs diffs. There is some slight visual inconsistency across various pages in how the toggle-all button is rendered, so there's still opportunity for some polishing-up.

stephan 2024-12-13 00:41 trunk
Commit a718a7689409c5d71c83dac92cd03bbfc53c13ad76be0bcf0552600a8dcdfa2b
--- src/default.css
+++ src/default.css
@@ -748,10 +748,11 @@
748748
border-bottom: 3px solid gold;
749749
}
750750
body.tkt div.content ol.tkt-changes > li:target > ol {
751751
border-left: 1px solid gold;
752752
}
753
+body.cpage-ckout .file-change-line,
753754
body.cpage-info .file-change-line,
754755
body.cpage-vdiff .file-change-line {
755756
margin-top: 16px;
756757
margin-bottom: 16px;
757758
margin-right: 1em /* keep it from nudging right up against the scrollbar-reveal zone */;
758759
--- src/default.css
+++ src/default.css
@@ -748,10 +748,11 @@
748 border-bottom: 3px solid gold;
749 }
750 body.tkt div.content ol.tkt-changes > li:target > ol {
751 border-left: 1px solid gold;
752 }
 
753 body.cpage-info .file-change-line,
754 body.cpage-vdiff .file-change-line {
755 margin-top: 16px;
756 margin-bottom: 16px;
757 margin-right: 1em /* keep it from nudging right up against the scrollbar-reveal zone */;
758
--- src/default.css
+++ src/default.css
@@ -748,10 +748,11 @@
748 border-bottom: 3px solid gold;
749 }
750 body.tkt div.content ol.tkt-changes > li:target > ol {
751 border-left: 1px solid gold;
752 }
753 body.cpage-ckout .file-change-line,
754 body.cpage-info .file-change-line,
755 body.cpage-vdiff .file-change-line {
756 margin-top: 16px;
757 margin-bottom: 16px;
758 margin-right: 1em /* keep it from nudging right up against the scrollbar-reveal zone */;
759
+59 -32
--- src/fossil.diff.js
+++ src/fossil.diff.js
@@ -1,43 +1,81 @@
11
/**
22
diff-related JS APIs for fossil.
33
*/
44
"use strict";
5
+/* Locate the UI element (if any) into which we can inject some diff-related
6
+ UI controls. */
7
+window.fossil.onPageLoad(function(){
8
+ const potentialParents = window.fossil.page.diffControlContainers = [
9
+ /* CSS selectors for possible parents for injected diff-related UI
10
+ controls. */
11
+ /* Put the most likely pages at the end, as array.pop() is more
12
+ efficient than array.shift() (see loop below). */
13
+ /* /filedit */ 'body.cpage-fileedit #fileedit-tab-diff-buttons',
14
+ /* /wikiedit */ 'body.cpage-wikiedit #wikiedit-tab-diff-buttons',
15
+ /* /fdiff */ 'body.fdiff form div.submenu',
16
+ /* /vdiff */ 'body.vdiff form div.submenu',
17
+ /* /info, /vinfo, /ckout */ 'body.vinfo div.sectionmenu.info-changes-menu'
18
+ ];
19
+ window.fossil.page.diffControlContainer = undefined;
20
+ while( potentialParents.length ){
21
+ if( (window.fossil.page.diffControlContainer
22
+ = document.querySelector(potentialParents.pop())) ){
23
+ break;
24
+ }
25
+ }
26
+});
27
+
528
window.fossil.onPageLoad(function(){
629
/**
730
Adds toggle checkboxes to each file entry in the diff views for
831
/info and similar pages.
932
*/
1033
const D = window.fossil.dom;
1134
const allToggles = [/*collection of all diff-toggle checkboxes */];
1235
const addToggle = function(diffElem){
1336
const sib = diffElem.previousElementSibling,
14
- btnOne = sib ? D.addClass(D.checkbox(true), 'diff-toggle') : 0;
37
+ ckbox = sib ? D.addClass(D.checkbox(true), 'diff-toggle') : 0;
1538
if(!sib) return;
16
- const lblToggle = D.append(D.label(null, " Toggle "), btnOne);
39
+ const lblToggle = D.label();
40
+ D.append(lblToggle, ckbox, D.text(" show/hide "));
1741
const wrapper = D.append(D.span(), lblToggle);
18
- const btnAll = D.button("all");
19
- btnAll.$cb = btnOne;
20
- allToggles.push(btnOne);
21
- D.append(sib, D.append(wrapper, lblToggle, D.text(" "), btnAll));
22
- btnOne.addEventListener('change', function(){
42
+ allToggles.push(ckbox);
43
+ D.append(sib, D.append(wrapper, lblToggle));
44
+ ckbox.addEventListener('change', function(){
2345
diffElem.classList[this.checked ? 'remove' : 'add']('hidden');
24
- }, false);
25
- btnAll.addEventListener('click', function(){
26
- /* Toggle all entries to match this line's new state. Note that
27
- we use click() instead of cb.checked=... so that the
28
- on-change event handler fires. */
29
- const checked = !this.$cb.checked;
30
- allToggles.forEach( (cb)=>{
31
- if(cb.checked!==checked) cb.click();
32
- });
3346
}, false);
3447
};
3548
if( !document.querySelector('body.fdiff') ){
3649
/* Don't show the diff toggle button for /fdiff because it only
3750
has a single file to show (and also a different DOM layout). */
3851
document.querySelectorAll('table.diff').forEach(addToggle);
52
+ }
53
+ const icm = allToggles.length>1 ? window.fossil.page.diffControlContainer : 0;
54
+ if(icm) {
55
+ const btnAll = D.addClass(D.a("#", "Toggle all diffs"), "button");
56
+ D.append( icm, btnAll );
57
+ btnAll.addEventListener('click', function(ev){
58
+ ev.preventDefault();
59
+ ev.stopPropagation();
60
+ /* Figure out whether we want to show all or hide all: if any diffs are
61
+ toggled off, show all, else hide all. */
62
+ let show = false;
63
+ let ckbox;
64
+ for( ckbox of allToggles ){
65
+ if( !ckbox.checked ){
66
+ show = true;
67
+ break;
68
+ }
69
+ }
70
+ for( ckbox of allToggles ){
71
+ /* Toggle all entries to match this new state. We use click()
72
+ instead of ckbox.checked=... so that the on-change event handler
73
+ fires. */
74
+ if(ckbox.checked!==show) ckbox.click();
75
+ }
76
+ }, false);
3977
}
4078
});
4179
4280
window.fossil.onPageLoad(function(){
4381
const F = window.fossil, D = F.dom;
@@ -651,26 +689,15 @@
651689
/* Look for a parent element to hold the sbs-sync-scroll toggle
652690
checkbox. This differs per page. If we don't find one, simply
653691
elide that toggle and use whatever preference the user last
654692
specified (defaulting to on). */
655693
let cbSync /* scroll-sync checkbox */;
656
- let eToggleParent /* element to put the sync-scroll checkbox in */;
657
- const potentialParents = [ /* possible parents for the checkbox */
658
- /* Put the most likely pages at the end, as array.pop() is more
659
- efficient than array.shift() (see loop below). */
660
- /* /filedit */ 'body.cpage-fileedit #fileedit-tab-diff-buttons',
661
- /* /wikiedit */ 'body.cpage-wikiedit #wikiedit-tab-diff-buttons',
662
- /* /fdiff */ 'body.fdiff form div.submenu',
663
- /* /vdiff */ 'body.vdiff form div.submenu',
664
- /* /info, /vinfo */ 'body.vinfo div.sectionmenu.info-changes-menu'
665
- ];
666
- while( potentialParents.length ){
667
- if( (eToggleParent = document.querySelector(potentialParents.pop())) ){
668
- break;
669
- }
670
- }
671
- const keySbsScroll = 'sync-diff-scroll' /* F.storage key */;
694
+ let eToggleParent = /* element to put the sync-scroll checkbox in */
695
+ document.querySelector('table.diff.splitdiff')
696
+ ? window.fossil.page.diffControlContainer
697
+ : undefined;
698
+ const keySbsScroll = 'sync-diff-scroll' /* F.storage key for persistent user preference */;
672699
if( eToggleParent ){
673700
/* Add a checkbox to toggle sbs scroll sync. Remember that in
674701
order to be UI-consistent in the /vdiff page we have to ensure
675702
that the checkbox is to the LEFT of of its label. We store the
676703
sync-scroll preference in F.storage (not a cookie) so that it
677704
--- src/fossil.diff.js
+++ src/fossil.diff.js
@@ -1,43 +1,81 @@
1 /**
2 diff-related JS APIs for fossil.
3 */
4 "use strict";
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
5 window.fossil.onPageLoad(function(){
6 /**
7 Adds toggle checkboxes to each file entry in the diff views for
8 /info and similar pages.
9 */
10 const D = window.fossil.dom;
11 const allToggles = [/*collection of all diff-toggle checkboxes */];
12 const addToggle = function(diffElem){
13 const sib = diffElem.previousElementSibling,
14 btnOne = sib ? D.addClass(D.checkbox(true), 'diff-toggle') : 0;
15 if(!sib) return;
16 const lblToggle = D.append(D.label(null, " Toggle "), btnOne);
 
17 const wrapper = D.append(D.span(), lblToggle);
18 const btnAll = D.button("all");
19 btnAll.$cb = btnOne;
20 allToggles.push(btnOne);
21 D.append(sib, D.append(wrapper, lblToggle, D.text(" "), btnAll));
22 btnOne.addEventListener('change', function(){
23 diffElem.classList[this.checked ? 'remove' : 'add']('hidden');
24 }, false);
25 btnAll.addEventListener('click', function(){
26 /* Toggle all entries to match this line's new state. Note that
27 we use click() instead of cb.checked=... so that the
28 on-change event handler fires. */
29 const checked = !this.$cb.checked;
30 allToggles.forEach( (cb)=>{
31 if(cb.checked!==checked) cb.click();
32 });
33 }, false);
34 };
35 if( !document.querySelector('body.fdiff') ){
36 /* Don't show the diff toggle button for /fdiff because it only
37 has a single file to show (and also a different DOM layout). */
38 document.querySelectorAll('table.diff').forEach(addToggle);
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
39 }
40 });
41
42 window.fossil.onPageLoad(function(){
43 const F = window.fossil, D = F.dom;
@@ -651,26 +689,15 @@
651 /* Look for a parent element to hold the sbs-sync-scroll toggle
652 checkbox. This differs per page. If we don't find one, simply
653 elide that toggle and use whatever preference the user last
654 specified (defaulting to on). */
655 let cbSync /* scroll-sync checkbox */;
656 let eToggleParent /* element to put the sync-scroll checkbox in */;
657 const potentialParents = [ /* possible parents for the checkbox */
658 /* Put the most likely pages at the end, as array.pop() is more
659 efficient than array.shift() (see loop below). */
660 /* /filedit */ 'body.cpage-fileedit #fileedit-tab-diff-buttons',
661 /* /wikiedit */ 'body.cpage-wikiedit #wikiedit-tab-diff-buttons',
662 /* /fdiff */ 'body.fdiff form div.submenu',
663 /* /vdiff */ 'body.vdiff form div.submenu',
664 /* /info, /vinfo */ 'body.vinfo div.sectionmenu.info-changes-menu'
665 ];
666 while( potentialParents.length ){
667 if( (eToggleParent = document.querySelector(potentialParents.pop())) ){
668 break;
669 }
670 }
671 const keySbsScroll = 'sync-diff-scroll' /* F.storage key */;
672 if( eToggleParent ){
673 /* Add a checkbox to toggle sbs scroll sync. Remember that in
674 order to be UI-consistent in the /vdiff page we have to ensure
675 that the checkbox is to the LEFT of of its label. We store the
676 sync-scroll preference in F.storage (not a cookie) so that it
677
--- src/fossil.diff.js
+++ src/fossil.diff.js
@@ -1,43 +1,81 @@
1 /**
2 diff-related JS APIs for fossil.
3 */
4 "use strict";
5 /* Locate the UI element (if any) into which we can inject some diff-related
6 UI controls. */
7 window.fossil.onPageLoad(function(){
8 const potentialParents = window.fossil.page.diffControlContainers = [
9 /* CSS selectors for possible parents for injected diff-related UI
10 controls. */
11 /* Put the most likely pages at the end, as array.pop() is more
12 efficient than array.shift() (see loop below). */
13 /* /filedit */ 'body.cpage-fileedit #fileedit-tab-diff-buttons',
14 /* /wikiedit */ 'body.cpage-wikiedit #wikiedit-tab-diff-buttons',
15 /* /fdiff */ 'body.fdiff form div.submenu',
16 /* /vdiff */ 'body.vdiff form div.submenu',
17 /* /info, /vinfo, /ckout */ 'body.vinfo div.sectionmenu.info-changes-menu'
18 ];
19 window.fossil.page.diffControlContainer = undefined;
20 while( potentialParents.length ){
21 if( (window.fossil.page.diffControlContainer
22 = document.querySelector(potentialParents.pop())) ){
23 break;
24 }
25 }
26 });
27
28 window.fossil.onPageLoad(function(){
29 /**
30 Adds toggle checkboxes to each file entry in the diff views for
31 /info and similar pages.
32 */
33 const D = window.fossil.dom;
34 const allToggles = [/*collection of all diff-toggle checkboxes */];
35 const addToggle = function(diffElem){
36 const sib = diffElem.previousElementSibling,
37 ckbox = sib ? D.addClass(D.checkbox(true), 'diff-toggle') : 0;
38 if(!sib) return;
39 const lblToggle = D.label();
40 D.append(lblToggle, ckbox, D.text(" show/hide "));
41 const wrapper = D.append(D.span(), lblToggle);
42 allToggles.push(ckbox);
43 D.append(sib, D.append(wrapper, lblToggle));
44 ckbox.addEventListener('change', function(){
 
 
45 diffElem.classList[this.checked ? 'remove' : 'add']('hidden');
 
 
 
 
 
 
 
 
 
46 }, false);
47 };
48 if( !document.querySelector('body.fdiff') ){
49 /* Don't show the diff toggle button for /fdiff because it only
50 has a single file to show (and also a different DOM layout). */
51 document.querySelectorAll('table.diff').forEach(addToggle);
52 }
53 const icm = allToggles.length>1 ? window.fossil.page.diffControlContainer : 0;
54 if(icm) {
55 const btnAll = D.addClass(D.a("#", "Toggle all diffs"), "button");
56 D.append( icm, btnAll );
57 btnAll.addEventListener('click', function(ev){
58 ev.preventDefault();
59 ev.stopPropagation();
60 /* Figure out whether we want to show all or hide all: if any diffs are
61 toggled off, show all, else hide all. */
62 let show = false;
63 let ckbox;
64 for( ckbox of allToggles ){
65 if( !ckbox.checked ){
66 show = true;
67 break;
68 }
69 }
70 for( ckbox of allToggles ){
71 /* Toggle all entries to match this new state. We use click()
72 instead of ckbox.checked=... so that the on-change event handler
73 fires. */
74 if(ckbox.checked!==show) ckbox.click();
75 }
76 }, false);
77 }
78 });
79
80 window.fossil.onPageLoad(function(){
81 const F = window.fossil, D = F.dom;
@@ -651,26 +689,15 @@
689 /* Look for a parent element to hold the sbs-sync-scroll toggle
690 checkbox. This differs per page. If we don't find one, simply
691 elide that toggle and use whatever preference the user last
692 specified (defaulting to on). */
693 let cbSync /* scroll-sync checkbox */;
694 let eToggleParent = /* element to put the sync-scroll checkbox in */
695 document.querySelector('table.diff.splitdiff')
696 ? window.fossil.page.diffControlContainer
697 : undefined;
698 const keySbsScroll = 'sync-diff-scroll' /* F.storage key for persistent user preference */;
 
 
 
 
 
 
 
 
 
 
 
699 if( eToggleParent ){
700 /* Add a checkbox to toggle sbs scroll sync. Remember that in
701 order to be UI-consistent in the /vdiff page we have to ensure
702 that the checkbox is to the LEFT of of its label. We store the
703 sync-scroll preference in F.storage (not a cookie) so that it
704
+11 -6
--- src/info.c
+++ src/info.c
@@ -668,10 +668,13 @@
668668
if( pCfg->diffFlags & DIFF_SIDEBYSIDE ){
669669
pCfg->diffFlags |= DIFF_HTML | DIFF_NOTTOOBIG;
670670
}else{
671671
pCfg->diffFlags |= DIFF_LINENO | DIFF_HTML | DIFF_NOTTOOBIG;
672672
}
673
+ @ <div class="sectionmenu info-changes-menu">
674
+ /* Filled out by JS */
675
+ @ </div>
673676
while( db_step(&q)==SQLITE_ROW ){
674677
const char *zTreename = db_column_text(&q,0);
675678
int isDeleted = db_column_int(&q, 1);
676679
int isChnged = db_column_int(&q,2);
677680
int isNew = db_column_int(&q,3);
@@ -679,35 +682,37 @@
679682
int isLink = db_column_int(&q, 5);
680683
const char *zUuid = db_column_text(&q, 6);
681684
int showDiff = 1;
682685
683686
pCfg->diffFlags &= (~DIFF_FILE_MASK);
687
+ @ <div class='file-change-line'><span>
684688
if( isDeleted ){
685
- @ <p>DELETED %h(zTreename)</p>
689
+ @ DELETED %h(zTreename)
686690
pCfg->diffFlags |= DIFF_FILE_DELETED;
687691
showDiff = 0;
688692
}else if( file_access(zTreename, F_OK) ){
689
- @ <p>MISSING %h(zTreename)</p>
693
+ @ MISSING %h(zTreename)
690694
showDiff = 0;
691695
}else if( isNew ){
692
- @ <p>ADDED %h(zTreename)</p>
696
+ @ ADDED %h(zTreename)
693697
pCfg->diffFlags |= DIFF_FILE_ADDED;
694698
srcid = 0;
695699
showDiff = 0;
696700
}else if( isChnged==3 ){
697
- @ <p>ADDED_BY_MERGE %h(zTreename)</p>
701
+ @ ADDED_BY_MERGE %h(zTreename)
698702
pCfg->diffFlags |= DIFF_FILE_ADDED;
699703
srcid = 0;
700704
showDiff = 0;
701705
}else if( isChnged==5 ){
702
- @ <p>ADDED_BY_INTEGRATE %h(zTreename)</p>
706
+ @ ADDED_BY_INTEGRATE %h(zTreename)
703707
pCfg->diffFlags |= DIFF_FILE_ADDED;
704708
srcid = 0;
705709
showDiff = 0;
706710
}else{
707
- @ <p>CHANGED %h(zTreename)</p>
711
+ @ CHANGED %h(zTreename)
708712
}
713
+ @ </span></div>
709714
if( showDiff ){
710715
Blob old, new;
711716
if( !isLink != !file_islink(zTreename) ){
712717
@ %s(DIFF_CANNOT_COMPUTE_SYMLINK)
713718
continue;
714719
--- src/info.c
+++ src/info.c
@@ -668,10 +668,13 @@
668 if( pCfg->diffFlags & DIFF_SIDEBYSIDE ){
669 pCfg->diffFlags |= DIFF_HTML | DIFF_NOTTOOBIG;
670 }else{
671 pCfg->diffFlags |= DIFF_LINENO | DIFF_HTML | DIFF_NOTTOOBIG;
672 }
 
 
 
673 while( db_step(&q)==SQLITE_ROW ){
674 const char *zTreename = db_column_text(&q,0);
675 int isDeleted = db_column_int(&q, 1);
676 int isChnged = db_column_int(&q,2);
677 int isNew = db_column_int(&q,3);
@@ -679,35 +682,37 @@
679 int isLink = db_column_int(&q, 5);
680 const char *zUuid = db_column_text(&q, 6);
681 int showDiff = 1;
682
683 pCfg->diffFlags &= (~DIFF_FILE_MASK);
 
684 if( isDeleted ){
685 @ <p>DELETED %h(zTreename)</p>
686 pCfg->diffFlags |= DIFF_FILE_DELETED;
687 showDiff = 0;
688 }else if( file_access(zTreename, F_OK) ){
689 @ <p>MISSING %h(zTreename)</p>
690 showDiff = 0;
691 }else if( isNew ){
692 @ <p>ADDED %h(zTreename)</p>
693 pCfg->diffFlags |= DIFF_FILE_ADDED;
694 srcid = 0;
695 showDiff = 0;
696 }else if( isChnged==3 ){
697 @ <p>ADDED_BY_MERGE %h(zTreename)</p>
698 pCfg->diffFlags |= DIFF_FILE_ADDED;
699 srcid = 0;
700 showDiff = 0;
701 }else if( isChnged==5 ){
702 @ <p>ADDED_BY_INTEGRATE %h(zTreename)</p>
703 pCfg->diffFlags |= DIFF_FILE_ADDED;
704 srcid = 0;
705 showDiff = 0;
706 }else{
707 @ <p>CHANGED %h(zTreename)</p>
708 }
 
709 if( showDiff ){
710 Blob old, new;
711 if( !isLink != !file_islink(zTreename) ){
712 @ %s(DIFF_CANNOT_COMPUTE_SYMLINK)
713 continue;
714
--- src/info.c
+++ src/info.c
@@ -668,10 +668,13 @@
668 if( pCfg->diffFlags & DIFF_SIDEBYSIDE ){
669 pCfg->diffFlags |= DIFF_HTML | DIFF_NOTTOOBIG;
670 }else{
671 pCfg->diffFlags |= DIFF_LINENO | DIFF_HTML | DIFF_NOTTOOBIG;
672 }
673 @ <div class="sectionmenu info-changes-menu">
674 /* Filled out by JS */
675 @ </div>
676 while( db_step(&q)==SQLITE_ROW ){
677 const char *zTreename = db_column_text(&q,0);
678 int isDeleted = db_column_int(&q, 1);
679 int isChnged = db_column_int(&q,2);
680 int isNew = db_column_int(&q,3);
@@ -679,35 +682,37 @@
682 int isLink = db_column_int(&q, 5);
683 const char *zUuid = db_column_text(&q, 6);
684 int showDiff = 1;
685
686 pCfg->diffFlags &= (~DIFF_FILE_MASK);
687 @ <div class='file-change-line'><span>
688 if( isDeleted ){
689 @ DELETED %h(zTreename)
690 pCfg->diffFlags |= DIFF_FILE_DELETED;
691 showDiff = 0;
692 }else if( file_access(zTreename, F_OK) ){
693 @ MISSING %h(zTreename)
694 showDiff = 0;
695 }else if( isNew ){
696 @ ADDED %h(zTreename)
697 pCfg->diffFlags |= DIFF_FILE_ADDED;
698 srcid = 0;
699 showDiff = 0;
700 }else if( isChnged==3 ){
701 @ ADDED_BY_MERGE %h(zTreename)
702 pCfg->diffFlags |= DIFF_FILE_ADDED;
703 srcid = 0;
704 showDiff = 0;
705 }else if( isChnged==5 ){
706 @ ADDED_BY_INTEGRATE %h(zTreename)
707 pCfg->diffFlags |= DIFF_FILE_ADDED;
708 srcid = 0;
709 showDiff = 0;
710 }else{
711 @ CHANGED %h(zTreename)
712 }
713 @ </span></div>
714 if( showDiff ){
715 Blob old, new;
716 if( !isLink != !file_islink(zTreename) ){
717 @ %s(DIFF_CANNOT_COMPUTE_SYMLINK)
718 continue;
719

Keyboard Shortcuts

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