Fossil SCM

Re-enable side-by-side diff sync scrolling and add a client-side persistent toggle for the preference, accessible as a checkbox in various pages which render sbs diffs.

stephan 2024-09-03 11:48 trunk merge
Commit c03ce0f4d43197a3932123d7b7bbe225e2da6e3a56ff13cbe38ec8ff64fe7d7d
+9 -1
--- src/default.css
+++ src/default.css
@@ -1351,20 +1351,28 @@
13511351
.input-with-label {
13521352
border: 1px inset rgba(128, 128, 128, 0.5);
13531353
border-radius: 0.25em;
13541354
padding: 0.1em;
13551355
margin: 0 0.5em;
1356
- display: inline-block;
1356
+ display: inline-block
1357
+ /* We would really like flex layout but changing that
1358
+ currently introduces a good deal of UI breakage
1359
+ to chase down. The advantage would be better alignment
1360
+ of the contained elements. */;
13571361
cursor: default;
13581362
white-space: nowrap;
1363
+}
1364
+.submenu .input-with-label {
1365
+ border: none;
13591366
}
13601367
.input-with-label > * {
13611368
vertical-align: middle;
13621369
}
13631370
.input-with-label > label {
13641371
display: inline; /* some skins set label display to block! */
13651372
cursor: pointer;
1373
+ white-space: nowrap;
13661374
}
13671375
.input-with-label > input {
13681376
margin: 0;
13691377
}
13701378
.input-with-label > button {
13711379
--- src/default.css
+++ src/default.css
@@ -1351,20 +1351,28 @@
1351 .input-with-label {
1352 border: 1px inset rgba(128, 128, 128, 0.5);
1353 border-radius: 0.25em;
1354 padding: 0.1em;
1355 margin: 0 0.5em;
1356 display: inline-block;
 
 
 
 
1357 cursor: default;
1358 white-space: nowrap;
 
 
 
1359 }
1360 .input-with-label > * {
1361 vertical-align: middle;
1362 }
1363 .input-with-label > label {
1364 display: inline; /* some skins set label display to block! */
1365 cursor: pointer;
 
1366 }
1367 .input-with-label > input {
1368 margin: 0;
1369 }
1370 .input-with-label > button {
1371
--- src/default.css
+++ src/default.css
@@ -1351,20 +1351,28 @@
1351 .input-with-label {
1352 border: 1px inset rgba(128, 128, 128, 0.5);
1353 border-radius: 0.25em;
1354 padding: 0.1em;
1355 margin: 0 0.5em;
1356 display: inline-block
1357 /* We would really like flex layout but changing that
1358 currently introduces a good deal of UI breakage
1359 to chase down. The advantage would be better alignment
1360 of the contained elements. */;
1361 cursor: default;
1362 white-space: nowrap;
1363 }
1364 .submenu .input-with-label {
1365 border: none;
1366 }
1367 .input-with-label > * {
1368 vertical-align: middle;
1369 }
1370 .input-with-label > label {
1371 display: inline; /* some skins set label display to block! */
1372 cursor: pointer;
1373 white-space: nowrap;
1374 }
1375 .input-with-label > input {
1376 margin: 0;
1377 }
1378 .input-with-label > button {
1379
+9 -1
--- src/default.css
+++ src/default.css
@@ -1351,20 +1351,28 @@
13511351
.input-with-label {
13521352
border: 1px inset rgba(128, 128, 128, 0.5);
13531353
border-radius: 0.25em;
13541354
padding: 0.1em;
13551355
margin: 0 0.5em;
1356
- display: inline-block;
1356
+ display: inline-block
1357
+ /* We would really like flex layout but changing that
1358
+ currently introduces a good deal of UI breakage
1359
+ to chase down. The advantage would be better alignment
1360
+ of the contained elements. */;
13571361
cursor: default;
13581362
white-space: nowrap;
1363
+}
1364
+.submenu .input-with-label {
1365
+ border: none;
13591366
}
13601367
.input-with-label > * {
13611368
vertical-align: middle;
13621369
}
13631370
.input-with-label > label {
13641371
display: inline; /* some skins set label display to block! */
13651372
cursor: pointer;
1373
+ white-space: nowrap;
13661374
}
13671375
.input-with-label > input {
13681376
margin: 0;
13691377
}
13701378
.input-with-label > button {
13711379
--- src/default.css
+++ src/default.css
@@ -1351,20 +1351,28 @@
1351 .input-with-label {
1352 border: 1px inset rgba(128, 128, 128, 0.5);
1353 border-radius: 0.25em;
1354 padding: 0.1em;
1355 margin: 0 0.5em;
1356 display: inline-block;
 
 
 
 
1357 cursor: default;
1358 white-space: nowrap;
 
 
 
1359 }
1360 .input-with-label > * {
1361 vertical-align: middle;
1362 }
1363 .input-with-label > label {
1364 display: inline; /* some skins set label display to block! */
1365 cursor: pointer;
 
1366 }
1367 .input-with-label > input {
1368 margin: 0;
1369 }
1370 .input-with-label > button {
1371
--- src/default.css
+++ src/default.css
@@ -1351,20 +1351,28 @@
1351 .input-with-label {
1352 border: 1px inset rgba(128, 128, 128, 0.5);
1353 border-radius: 0.25em;
1354 padding: 0.1em;
1355 margin: 0 0.5em;
1356 display: inline-block
1357 /* We would really like flex layout but changing that
1358 currently introduces a good deal of UI breakage
1359 to chase down. The advantage would be better alignment
1360 of the contained elements. */;
1361 cursor: default;
1362 white-space: nowrap;
1363 }
1364 .submenu .input-with-label {
1365 border: none;
1366 }
1367 .input-with-label > * {
1368 vertical-align: middle;
1369 }
1370 .input-with-label > label {
1371 display: inline; /* some skins set label display to block! */
1372 cursor: pointer;
1373 white-space: nowrap;
1374 }
1375 .input-with-label > input {
1376 margin: 0;
1377 }
1378 .input-with-label > button {
1379
--- src/fossil.bootstrap.js
+++ src/fossil.bootstrap.js
@@ -137,11 +137,11 @@
137137
repoUrl( repoRelativePath [,urlParams] )
138138
139139
Creates a URL by prepending this.rootPath to the given path
140140
(which must be relative from the top of the site, without a
141141
leading slash). If urlParams is a string, it must be
142
- paramters encoded in the form "key=val&key2=val2..." WITHOUT
142
+ parameters encoded in the form "key=val&key2=val2..." WITHOUT
143143
a leading '?'. If it's an object, all of its properties get
144144
appended to the URL in that form.
145145
*/
146146
F.repoUrl = function(path,urlParams){
147147
if(!urlParams) return this.rootPath+path;
148148
--- src/fossil.bootstrap.js
+++ src/fossil.bootstrap.js
@@ -137,11 +137,11 @@
137 repoUrl( repoRelativePath [,urlParams] )
138
139 Creates a URL by prepending this.rootPath to the given path
140 (which must be relative from the top of the site, without a
141 leading slash). If urlParams is a string, it must be
142 paramters encoded in the form "key=val&key2=val2..." WITHOUT
143 a leading '?'. If it's an object, all of its properties get
144 appended to the URL in that form.
145 */
146 F.repoUrl = function(path,urlParams){
147 if(!urlParams) return this.rootPath+path;
148
--- src/fossil.bootstrap.js
+++ src/fossil.bootstrap.js
@@ -137,11 +137,11 @@
137 repoUrl( repoRelativePath [,urlParams] )
138
139 Creates a URL by prepending this.rootPath to the given path
140 (which must be relative from the top of the site, without a
141 leading slash). If urlParams is a string, it must be
142 parameters encoded in the form "key=val&key2=val2..." WITHOUT
143 a leading '?'. If it's an object, all of its properties get
144 appended to the URL in that form.
145 */
146 F.repoUrl = function(path,urlParams){
147 if(!urlParams) return this.rootPath+path;
148
--- src/fossil.diff.js
+++ src/fossil.diff.js
@@ -620,5 +620,129 @@
620620
});
621621
return F;
622622
};
623623
Diff.setupDiffContextLoad();
624624
});
625
+/*
626
+** For a side-by-side diff, ensure that horizontal scrolling of either
627
+** side of the diff is synchronized with the other side.
628
+*/
629
+window.fossil.onPageLoad(function(){
630
+ const F = window.fossil, D = F.dom, Diff = F.diff;
631
+
632
+ /* Look for a parent element to hold the sbs-sync-scroll toggle
633
+ checkbox. This differs per page. If we don't find one, simply
634
+ elide that toggle and use whatever preference the user last
635
+ specified (defaulting to on). */
636
+ let cbSync /* scroll-sync checkbox */;
637
+ let eToggleParent /* element to put the sync-scroll checkbox in */;
638
+ const potentialParents = [ /* possible parents for the checkbox */
639
+ /* Put the most likely pages at the end, as array.pop() is more
640
+ efficient than array.shift() (see loop below). */
641
+ /* /filedit */ 'body.cpage-fileedit #fileedit-tab-diff-buttons',
642
+ /* /wikiedit */ 'body.cpage-wikiedit #wikiedit-tab-diff-buttons',
643
+ /* /vdiff */ 'body.vdiff form div.submenu',
644
+ /* /info, /vinfo */ 'body.vinfo div.sectionmenu.info-changes-menu'
645
+ ];
646
+ while( potentialParents.length ){
647
+ if( (eToggleParent = document.querySelector(potentialParents.pop())) ){
648
+ break;
649
+ }
650
+ }
651
+ const keySbsScroll = 'sync-diff-scroll' /* F.storage key */;
652
+ if( eToggleParent ){
653
+ /* Add a checkbox to toggle sbs scroll sync. Remember that in
654
+ order to be UI-consistent in the /vdiff page we have to ensure
655
+ that the checkbox is to the LEFT of of its label. We store the
656
+ sync-scroll preference in F.storage (not a cookie) so that it
657
+ persists across page loads and different apps. */
658
+ cbSync = D.checkbox(keySbsScroll, F.storage.getBool(keySbsScroll,true));
659
+ D.append(eToggleParent, D.append(
660
+ D.addClass(D.create('span'), 'input-with-label'),
661
+ D.append(D.create('label'),
662
+ cbSync, "Sync side-by-side scrolling?")
663
+ ));
664
+ cbSync.addEventListener('change', function(e){
665
+ F.storage.set(keySbsScroll, e.target.checked);
666
+ });
667
+ }
668
+ const useSync = cbSync ? ()=>cbSync.checked : ()=>F.storage.getBool(keySbsScroll,true);
669
+
670
+ /* Now set up the events to enable syncronized scrolling... */
671
+ const scrollLeft = function(event){
672
+ const table = this.parentElement/*TD*/.parentElement/*TR*/.
673
+ parentElement/*TBODY*/.parentElement/*TABLE*/;
674
+ if( useSync() ){
675
+ table.$txtPres.forEach((e)=>(e===this) ? 1 : (e.scrollLeft = this.scrollLeft));
676
+ }
677
+ return false;
678
+ };
679
+ const SCROLL_LEN = 64/* pixels to scroll for keyboard events */;
680
+ const keycodes = Object.assign(Object.create(null),{
681
+ 37/*cursor left*/: -SCROLL_LEN, 39/*cursor right*/: SCROLL_LEN
682
+ });
683
+ /**
684
+ Sets up synchronized scrolling of table.splitdiff element
685
+ `diff`. If passed no argument, it scans the dom for elements to
686
+ initialize. The second argument is for this function's own
687
+ internal use.
688
+
689
+ It's okay (but wasteful) to pass the same element to this
690
+ function multiple times: it will only be set up for sync
691
+ scrolling the first time it's passed to this function.
692
+
693
+ Note that this setup is ignorant of the cbSync toggle: the toggle
694
+ is checked when scrolling, not when initializing the sync-scroll
695
+ capability.
696
+ */
697
+ const initTableDiff = function f(diff, unifiedDiffs){
698
+ if(!diff){
699
+ let i, diffs;
700
+ diffs = document.querySelectorAll('table.splitdiff');
701
+ for(i=0; i<diffs.length; ++i){
702
+ f.call(this, diffs[i], false);
703
+ }
704
+ diffs = document.querySelectorAll('table.udiff');
705
+ for(i=0; i<diffs.length; ++i){
706
+ f.call(this, diffs[i], true);
707
+ }
708
+ return this;
709
+ }
710
+ diff.$txtCols = diff.querySelectorAll('td.difftxt');
711
+ diff.$txtPres = diff.querySelectorAll('td.difftxt pre');
712
+ if(!unifiedDiffs){
713
+ diff.$txtPres.forEach(function(e){
714
+ if(!e.classList.contains('scroller')){
715
+ D.addClass(e, 'scroller');
716
+ e.addEventListener('scroll', scrollLeft, false);
717
+ }
718
+ });
719
+ diff.tabIndex = 0;
720
+ if(!diff.classList.contains('scroller')){
721
+ /* Keyboard-based scrolling requires special-case handling to
722
+ ensure that we scroll the proper side of the diff when sync
723
+ is off. */
724
+ D.addClass(diff, 'scroller');
725
+ diff.addEventListener('keydown', function(e){
726
+ const len = keycodes[e.keyCode];
727
+ if( !len ) return false;
728
+ if( useSync() ){
729
+ this.$txtPres[0].scrollLeft += len;
730
+ }else if( diff.$preCurrent ){
731
+ this.$preCurrent.scrollLeft += len;
732
+ }
733
+ return false;
734
+ }, false);
735
+ diff.$txtPres.forEach((e)=>{
736
+ e.addEventListener('click', function(ev){
737
+ diff.$preCurrent = this /* NOT ev.target, which is probably a child element */;
738
+ }, false);
739
+ })
740
+ }
741
+ }
742
+ return this;
743
+ }
744
+ window.fossil.page.tweakSbsDiffs = function(){
745
+ document.querySelectorAll('table.splitdiff').forEach((e)=>initTableDiff(e));
746
+ };
747
+ initTableDiff();
748
+}, false);
625749
--- src/fossil.diff.js
+++ src/fossil.diff.js
@@ -620,5 +620,129 @@
620 });
621 return F;
622 };
623 Diff.setupDiffContextLoad();
624 });
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
625
--- src/fossil.diff.js
+++ src/fossil.diff.js
@@ -620,5 +620,129 @@
620 });
621 return F;
622 };
623 Diff.setupDiffContextLoad();
624 });
625 /*
626 ** For a side-by-side diff, ensure that horizontal scrolling of either
627 ** side of the diff is synchronized with the other side.
628 */
629 window.fossil.onPageLoad(function(){
630 const F = window.fossil, D = F.dom, Diff = F.diff;
631
632 /* Look for a parent element to hold the sbs-sync-scroll toggle
633 checkbox. This differs per page. If we don't find one, simply
634 elide that toggle and use whatever preference the user last
635 specified (defaulting to on). */
636 let cbSync /* scroll-sync checkbox */;
637 let eToggleParent /* element to put the sync-scroll checkbox in */;
638 const potentialParents = [ /* possible parents for the checkbox */
639 /* Put the most likely pages at the end, as array.pop() is more
640 efficient than array.shift() (see loop below). */
641 /* /filedit */ 'body.cpage-fileedit #fileedit-tab-diff-buttons',
642 /* /wikiedit */ 'body.cpage-wikiedit #wikiedit-tab-diff-buttons',
643 /* /vdiff */ 'body.vdiff form div.submenu',
644 /* /info, /vinfo */ 'body.vinfo div.sectionmenu.info-changes-menu'
645 ];
646 while( potentialParents.length ){
647 if( (eToggleParent = document.querySelector(potentialParents.pop())) ){
648 break;
649 }
650 }
651 const keySbsScroll = 'sync-diff-scroll' /* F.storage key */;
652 if( eToggleParent ){
653 /* Add a checkbox to toggle sbs scroll sync. Remember that in
654 order to be UI-consistent in the /vdiff page we have to ensure
655 that the checkbox is to the LEFT of of its label. We store the
656 sync-scroll preference in F.storage (not a cookie) so that it
657 persists across page loads and different apps. */
658 cbSync = D.checkbox(keySbsScroll, F.storage.getBool(keySbsScroll,true));
659 D.append(eToggleParent, D.append(
660 D.addClass(D.create('span'), 'input-with-label'),
661 D.append(D.create('label'),
662 cbSync, "Sync side-by-side scrolling?")
663 ));
664 cbSync.addEventListener('change', function(e){
665 F.storage.set(keySbsScroll, e.target.checked);
666 });
667 }
668 const useSync = cbSync ? ()=>cbSync.checked : ()=>F.storage.getBool(keySbsScroll,true);
669
670 /* Now set up the events to enable syncronized scrolling... */
671 const scrollLeft = function(event){
672 const table = this.parentElement/*TD*/.parentElement/*TR*/.
673 parentElement/*TBODY*/.parentElement/*TABLE*/;
674 if( useSync() ){
675 table.$txtPres.forEach((e)=>(e===this) ? 1 : (e.scrollLeft = this.scrollLeft));
676 }
677 return false;
678 };
679 const SCROLL_LEN = 64/* pixels to scroll for keyboard events */;
680 const keycodes = Object.assign(Object.create(null),{
681 37/*cursor left*/: -SCROLL_LEN, 39/*cursor right*/: SCROLL_LEN
682 });
683 /**
684 Sets up synchronized scrolling of table.splitdiff element
685 `diff`. If passed no argument, it scans the dom for elements to
686 initialize. The second argument is for this function's own
687 internal use.
688
689 It's okay (but wasteful) to pass the same element to this
690 function multiple times: it will only be set up for sync
691 scrolling the first time it's passed to this function.
692
693 Note that this setup is ignorant of the cbSync toggle: the toggle
694 is checked when scrolling, not when initializing the sync-scroll
695 capability.
696 */
697 const initTableDiff = function f(diff, unifiedDiffs){
698 if(!diff){
699 let i, diffs;
700 diffs = document.querySelectorAll('table.splitdiff');
701 for(i=0; i<diffs.length; ++i){
702 f.call(this, diffs[i], false);
703 }
704 diffs = document.querySelectorAll('table.udiff');
705 for(i=0; i<diffs.length; ++i){
706 f.call(this, diffs[i], true);
707 }
708 return this;
709 }
710 diff.$txtCols = diff.querySelectorAll('td.difftxt');
711 diff.$txtPres = diff.querySelectorAll('td.difftxt pre');
712 if(!unifiedDiffs){
713 diff.$txtPres.forEach(function(e){
714 if(!e.classList.contains('scroller')){
715 D.addClass(e, 'scroller');
716 e.addEventListener('scroll', scrollLeft, false);
717 }
718 });
719 diff.tabIndex = 0;
720 if(!diff.classList.contains('scroller')){
721 /* Keyboard-based scrolling requires special-case handling to
722 ensure that we scroll the proper side of the diff when sync
723 is off. */
724 D.addClass(diff, 'scroller');
725 diff.addEventListener('keydown', function(e){
726 const len = keycodes[e.keyCode];
727 if( !len ) return false;
728 if( useSync() ){
729 this.$txtPres[0].scrollLeft += len;
730 }else if( diff.$preCurrent ){
731 this.$preCurrent.scrollLeft += len;
732 }
733 return false;
734 }, false);
735 diff.$txtPres.forEach((e)=>{
736 e.addEventListener('click', function(ev){
737 diff.$preCurrent = this /* NOT ev.target, which is probably a child element */;
738 }, false);
739 })
740 }
741 }
742 return this;
743 }
744 window.fossil.page.tweakSbsDiffs = function(){
745 document.querySelectorAll('table.splitdiff').forEach((e)=>initTableDiff(e));
746 };
747 initTableDiff();
748 }, false);
749
--- src/fossil.page.fileedit.js
+++ src/fossil.page.fileedit.js
@@ -1245,10 +1245,11 @@
12451245
self.finfo.checkin,
12461246
"]</code> &rarr; Local Edits</div>",
12471247
c||'No changes.'
12481248
].join(''));
12491249
F.diff.setupDiffContextLoad();
1250
+ if(sbs) P.tweakSbsDiffs();
12501251
F.message('Updated diff.');
12511252
self.tabs.switchToTab(self.e.tabs.diff);
12521253
}
12531254
});
12541255
return this;
12551256
--- src/fossil.page.fileedit.js
+++ src/fossil.page.fileedit.js
@@ -1245,10 +1245,11 @@
1245 self.finfo.checkin,
1246 "]</code> &rarr; Local Edits</div>",
1247 c||'No changes.'
1248 ].join(''));
1249 F.diff.setupDiffContextLoad();
 
1250 F.message('Updated diff.');
1251 self.tabs.switchToTab(self.e.tabs.diff);
1252 }
1253 });
1254 return this;
1255
--- src/fossil.page.fileedit.js
+++ src/fossil.page.fileedit.js
@@ -1245,10 +1245,11 @@
1245 self.finfo.checkin,
1246 "]</code> &rarr; Local Edits</div>",
1247 c||'No changes.'
1248 ].join(''));
1249 F.diff.setupDiffContextLoad();
1250 if(sbs) P.tweakSbsDiffs();
1251 F.message('Updated diff.');
1252 self.tabs.switchToTab(self.e.tabs.diff);
1253 }
1254 });
1255 return this;
1256
--- src/fossil.page.wikiedit.js
+++ src/fossil.page.wikiedit.js
@@ -1545,10 +1545,11 @@
15451545
self.winfo.name,
15461546
"]</code> &rarr; Local Edits</div>",
15471547
c||'No changes.'
15481548
].join(''));
15491549
F.diff.setupDiffContextLoad();
1550
+ if(sbs) P.tweakSbsDiffs();
15501551
F.message('Updated diff.');
15511552
self.tabs.switchToTab(self.e.tabs.diff);
15521553
}
15531554
});
15541555
return this;
15551556
--- src/fossil.page.wikiedit.js
+++ src/fossil.page.wikiedit.js
@@ -1545,10 +1545,11 @@
1545 self.winfo.name,
1546 "]</code> &rarr; Local Edits</div>",
1547 c||'No changes.'
1548 ].join(''));
1549 F.diff.setupDiffContextLoad();
 
1550 F.message('Updated diff.');
1551 self.tabs.switchToTab(self.e.tabs.diff);
1552 }
1553 });
1554 return this;
1555
--- src/fossil.page.wikiedit.js
+++ src/fossil.page.wikiedit.js
@@ -1545,10 +1545,11 @@
1545 self.winfo.name,
1546 "]</code> &rarr; Local Edits</div>",
1547 c||'No changes.'
1548 ].join(''));
1549 F.diff.setupDiffContextLoad();
1550 if(sbs) P.tweakSbsDiffs();
1551 F.message('Updated diff.');
1552 self.tabs.switchToTab(self.e.tabs.diff);
1553 }
1554 });
1555 return this;
1556
+2 -1
--- src/info.c
+++ src/info.c
@@ -891,11 +891,12 @@
891891
"<div class=\"section accordion\">References</div>\n");
892892
@ <div class="section accordion">Context</div><div class="accordion_panel">
893893
render_checkin_context(rid, 0, 0, 0);
894894
@ </div><div class="section accordion">Changes</div>
895895
@ <div class="accordion_panel">
896
- @ <div class="sectionmenu">
896
+ @ <div class="sectionmenu info-changes-menu">
897
+ /* ^^^ .info-changes-menu is used by diff scroll sync */
897898
pCfg = construct_diff_flags(diffType, &DCfg);
898899
DCfg.pRe = pRe;
899900
zW = (DCfg.diffFlags&DIFF_IGNORE_ALLWS)?"&w":"";
900901
if( diffType!=0 ){
901902
@ %z(chref("button","%R/%s/%T?diff=0",zPageHide,zName))\
902903
--- src/info.c
+++ src/info.c
@@ -891,11 +891,12 @@
891 "<div class=\"section accordion\">References</div>\n");
892 @ <div class="section accordion">Context</div><div class="accordion_panel">
893 render_checkin_context(rid, 0, 0, 0);
894 @ </div><div class="section accordion">Changes</div>
895 @ <div class="accordion_panel">
896 @ <div class="sectionmenu">
 
897 pCfg = construct_diff_flags(diffType, &DCfg);
898 DCfg.pRe = pRe;
899 zW = (DCfg.diffFlags&DIFF_IGNORE_ALLWS)?"&w":"";
900 if( diffType!=0 ){
901 @ %z(chref("button","%R/%s/%T?diff=0",zPageHide,zName))\
902
--- src/info.c
+++ src/info.c
@@ -891,11 +891,12 @@
891 "<div class=\"section accordion\">References</div>\n");
892 @ <div class="section accordion">Context</div><div class="accordion_panel">
893 render_checkin_context(rid, 0, 0, 0);
894 @ </div><div class="section accordion">Changes</div>
895 @ <div class="accordion_panel">
896 @ <div class="sectionmenu info-changes-menu">
897 /* ^^^ .info-changes-menu is used by diff scroll sync */
898 pCfg = construct_diff_flags(diffType, &DCfg);
899 DCfg.pRe = pRe;
900 zW = (DCfg.diffFlags&DIFF_IGNORE_ALLWS)?"&w":"";
901 if( diffType!=0 ){
902 @ %z(chref("button","%R/%s/%T?diff=0",zPageHide,zName))\
903

Keyboard Shortcuts

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