detached b885b9d

feat(gui): enhance homepage with footer, improved history sorting and redesigned shortcuts layout

commit
b885b9da68a625a53ef1ef4fec2d9aea8abe6a5c
author
bamen · · 2025-09-20 06:35 UTC
parent
d23ce77
signature
unsigned
1 file · +72 -52
M gui/src/pages/Homepage.svelte +72 -52
@@ -1,5 +1,6 @@
11 <script lang="ts">
22 import { onMount } from 'svelte';
3+ import Footer from '$components/Footer.svelte';
34 // Icons disabled for investigation: removed @lucide/svelte imports
45
56 interface HistoryItem {
@@ -401,7 +402,10 @@
401402 try {
402403 // Set up response handler
403404 (window as any).__dumber_history_search = (data: any[]) => {
404- topVisited = Array.isArray(data) ? data.slice(0, 5) : [];
405+ // Sort by visit_count in descending order and take top 5
406+ const sortedData = Array.isArray(data) ?
407+ data.sort((a, b) => (b.visit_count || 0) - (a.visit_count || 0)).slice(0, 5) : [];
408+ topVisited = sortedData;
405409 topVisitedLoading = false;
406410 };
407411
@@ -417,7 +421,7 @@
417421 bridge.postMessage(JSON.stringify({
418422 type: 'history_search',
419423 q: '',
420- limit: 5
424+ limit: 50 // Get more results to sort properly
421425 }));
422426 } else {
423427 throw new Error('WebKit message handler not available');
@@ -565,33 +569,16 @@
565569 {#if shortcutsLoading}
566570 <div class="loading">Loading shortcuts...</div>
567571 {:else}
568- <table class="shortcuts-table">
569- <tbody>
570- {#each shortcuts as shortcut (shortcut.key)}
571- <tr class="shortcut-row">
572- <td class="shortcut-key">{shortcut.key}</td>
573- <td class="shortcut-desc">{shortcut.description}</td>
574- </tr>
575- {/each}
576- </tbody>
577- </table>
578- {/if}
579- </div>
580-
581- <h2 class="section-title stats-title">Statistics</h2>
582- <div class="stats-container">
583- {#if statsLoading}
584- <div class="loading">Loading stats...</div>
585- {:else if stats}
586- <div class="stats-grid">
587- <div class="stat-item">
588- <div class="stat-value">{stats.total_entries}</div>
589- <div class="stat-label">History Entries</div>
590- </div>
591- </div>
592- {:else}
593- <div class="empty-state">
594- <p>No statistics available</p>
572+ <div class="shortcuts-card">
573+ {#each shortcuts as shortcut, index (shortcut.key)}
574+ <div class="shortcut-item">
575+ <div class="shortcut-key-badge">{shortcut.key}</div>
576+ <div class="shortcut-desc">{shortcut.description}</div>
577+ </div>
578+ {#if index < shortcuts.length - 1}
579+ <div class="shortcut-separator"></div>
580+ {/if}
581+ {/each}
595582 </div>
596583 {/if}
597584 </div>
@@ -625,8 +612,28 @@
625612 </div>
626613 {/if}
627614 </div>
615+
616+ <h2 class="section-title stats-title">Statistics</h2>
617+ <div class="stats-container">
618+ {#if statsLoading}
619+ <div class="loading">Loading stats...</div>
620+ {:else if stats}
621+ <div class="stats-grid">
622+ <div class="stat-item">
623+ <div class="stat-value">{stats.total_entries}</div>
624+ <div class="stat-label">History Entries</div>
625+ </div>
626+ </div>
627+ {:else}
628+ <div class="empty-state">
629+ <p>No statistics available</p>
630+ </div>
631+ {/if}
632+ </div>
628633 </div>
629634 </div>
635+
636+<Footer />
630637 </div>
631638
632639 <style>
@@ -661,6 +668,7 @@
661668 .container {
662669 flex: 1;
663670 display: flex;
671+ align-items: stretch;
664672 max-width: 1200px;
665673 margin: 0 auto;
666674 width: 100%;
@@ -673,6 +681,8 @@
673681 flex: 2;
674682 min-height: 0;
675683 min-width: 0;
684+ display: flex;
685+ flex-direction: column;
676686 }
677687
678688 .shortcuts-section {
@@ -692,8 +702,8 @@
692702 .history-list {
693703 overflow-y: auto;
694704 overflow-x: hidden;
695- max-height: calc(100vh - 8rem);
696705 max-width: 100%;
706+ max-height: calc(100vh - 8rem);
697707 }
698708
699709 .history-item {
@@ -829,45 +839,55 @@
829839 }
830840
831841 .shortcuts-container {
832- max-height: calc(100vh - 8rem);
833- overflow-y: auto;
842+ /* Remove height limit to show all shortcuts */
834843 }
835844
836- .shortcuts-table {
837- width: 100%;
838- border-collapse: collapse;
845+ .shortcuts-card {
839846 background: #2d2d2d;
840- border-radius: 6px;
841- overflow: hidden;
847+ border-radius: 8px;
848+ border: 1px solid #404040;
849+ padding: 1rem;
842850 }
843851
844- .shortcut-row {
845- border-bottom: 1px solid #404040;
846- transition: background 0.2s;
852+ .shortcut-item {
853+ display: flex;
854+ align-items: center;
855+ gap: 0.75rem;
856+ padding: 0.5rem 0;
857+ transition: all 0.2s ease;
847858 }
848859
849- .shortcut-row:last-child {
850- border-bottom: none;
860+ .shortcut-item:hover {
861+ background: rgba(255, 255, 255, 0.02);
862+ border-radius: 4px;
863+ padding: 0.5rem;
864+ margin: 0 -0.5rem;
851865 }
852866
853- .shortcut-row:hover {
854- background: #3d3d3d;
867+ .shortcut-separator {
868+ height: 1px;
869+ background: #404040;
870+ margin: 0.25rem 0;
855871 }
856872
857- .shortcut-key {
858- padding: 0.4rem 0.8rem;
859- font-weight: bold;
860- color: #0066cc;
861- font-size: 0.85rem;
873+ .shortcut-key-badge {
874+ background: linear-gradient(135deg, #0066cc, #004499);
875+ color: #ffffff;
876+ padding: 0.25rem 0.5rem;
877+ border-radius: 4px;
862878 font-family: 'Monaco', 'Menlo', 'Ubuntu Mono', monospace;
879+ font-size: 0.75rem;
880+ font-weight: 600;
863881 white-space: nowrap;
864- width: 1%;
882+ box-shadow: 0 1px 2px rgba(0, 102, 204, 0.2);
883+ border: 1px solid rgba(255, 255, 255, 0.1);
884+ min-width: fit-content;
865885 }
866886
867887 .shortcut-desc {
868- padding: 0.4rem 0.8rem;
869888 color: #e6e6e6;
870- font-size: 0.85rem;
889+ font-size: 0.9rem;
890+ flex: 1;
871891 }
872892
873893 .stats-title {
@@ -1,5 +1,6 @@
1 <script lang="ts">1 <script lang="ts">
2 import { onMount } from 'svelte';2 import { onMount } from 'svelte';
3+ import Footer from '$components/Footer.svelte';
3 // Icons disabled for investigation: removed @lucide/svelte imports4 // Icons disabled for investigation: removed @lucide/svelte imports
4 5
5 interface HistoryItem {6 interface HistoryItem {
@@ -401,7 +402,10 @@
401 try {402 try {
402 // Set up response handler403 // Set up response handler
403 (window as any).__dumber_history_search = (data: any[]) => {404 (window as any).__dumber_history_search = (data: any[]) => {
404- topVisited = Array.isArray(data) ? data.slice(0, 5) : [];405+ // Sort by visit_count in descending order and take top 5
406+ const sortedData = Array.isArray(data) ?
407+ data.sort((a, b) => (b.visit_count || 0) - (a.visit_count || 0)).slice(0, 5) : [];
408+ topVisited = sortedData;
405 topVisitedLoading = false;409 topVisitedLoading = false;
406 };410 };
407 411
@@ -417,7 +421,7 @@
417 bridge.postMessage(JSON.stringify({421 bridge.postMessage(JSON.stringify({
418 type: 'history_search',422 type: 'history_search',
419 q: '',423 q: '',
420- limit: 5424+ limit: 50 // Get more results to sort properly
421 }));425 }));
422 } else {426 } else {
423 throw new Error('WebKit message handler not available');427 throw new Error('WebKit message handler not available');
@@ -565,33 +569,16 @@
565 {#if shortcutsLoading}569 {#if shortcutsLoading}
566 <div class="loading">Loading shortcuts...</div>570 <div class="loading">Loading shortcuts...</div>
567 {:else}571 {:else}
568- <table class="shortcuts-table">572+ <div class="shortcuts-card">
569- <tbody>573+ {#each shortcuts as shortcut, index (shortcut.key)}
570- {#each shortcuts as shortcut (shortcut.key)}574+ <div class="shortcut-item">
571- <tr class="shortcut-row">575+ <div class="shortcut-key-badge">{shortcut.key}</div>
572- <td class="shortcut-key">{shortcut.key}</td>576+ <div class="shortcut-desc">{shortcut.description}</div>
573- <td class="shortcut-desc">{shortcut.description}</td>577+ </div>
574- </tr>578+ {#if index < shortcuts.length - 1}
575- {/each}579+ <div class="shortcut-separator"></div>
576- </tbody>580+ {/if}
577- </table>581+ {/each}
578- {/if}
579- </div>
580-
581- <h2 class="section-title stats-title">Statistics</h2>
582- <div class="stats-container">
583- {#if statsLoading}
584- <div class="loading">Loading stats...</div>
585- {:else if stats}
586- <div class="stats-grid">
587- <div class="stat-item">
588- <div class="stat-value">{stats.total_entries}</div>
589- <div class="stat-label">History Entries</div>
590- </div>
591- </div>
592- {:else}
593- <div class="empty-state">
594- <p>No statistics available</p>
595 </div>582 </div>
596 {/if}583 {/if}
597 </div>584 </div>
@@ -625,8 +612,28 @@
625 </div>612 </div>
626 {/if}613 {/if}
627 </div>614 </div>
615+
616+ <h2 class="section-title stats-title">Statistics</h2>
617+ <div class="stats-container">
618+ {#if statsLoading}
619+ <div class="loading">Loading stats...</div>
620+ {:else if stats}
621+ <div class="stats-grid">
622+ <div class="stat-item">
623+ <div class="stat-value">{stats.total_entries}</div>
624+ <div class="stat-label">History Entries</div>
625+ </div>
626+ </div>
627+ {:else}
628+ <div class="empty-state">
629+ <p>No statistics available</p>
630+ </div>
631+ {/if}
632+ </div>
628 </div>633 </div>
629 </div>634 </div>
635+
636+<Footer />
630 </div>637 </div>
631 638
632 <style>639 <style>
@@ -661,6 +668,7 @@
661 .container {668 .container {
662 flex: 1;669 flex: 1;
663 display: flex;670 display: flex;
671+ align-items: stretch;
664 max-width: 1200px;672 max-width: 1200px;
665 margin: 0 auto;673 margin: 0 auto;
666 width: 100%;674 width: 100%;
@@ -673,6 +681,8 @@
673 flex: 2;681 flex: 2;
674 min-height: 0;682 min-height: 0;
675 min-width: 0;683 min-width: 0;
684+ display: flex;
685+ flex-direction: column;
676 }686 }
677 687
678 .shortcuts-section {688 .shortcuts-section {
@@ -692,8 +702,8 @@
692 .history-list {702 .history-list {
693 overflow-y: auto;703 overflow-y: auto;
694 overflow-x: hidden;704 overflow-x: hidden;
695- max-height: calc(100vh - 8rem);
696 max-width: 100%;705 max-width: 100%;
706+ max-height: calc(100vh - 8rem);
697 }707 }
698 708
699 .history-item {709 .history-item {
@@ -829,45 +839,55 @@
829 }839 }
830 840
831 .shortcuts-container {841 .shortcuts-container {
832- max-height: calc(100vh - 8rem);842+ /* Remove height limit to show all shortcuts */
833- overflow-y: auto;
834 }843 }
835 844
836- .shortcuts-table {845+ .shortcuts-card {
837- width: 100%;
838- border-collapse: collapse;
839 background: #2d2d2d;846 background: #2d2d2d;
840- border-radius: 6px;847+ border-radius: 8px;
841- overflow: hidden;848+ border: 1px solid #404040;
849+ padding: 1rem;
842 }850 }
843 851
844- .shortcut-row {852+ .shortcut-item {
845- border-bottom: 1px solid #404040;853+ display: flex;
846- transition: background 0.2s;854+ align-items: center;
855+ gap: 0.75rem;
856+ padding: 0.5rem 0;
857+ transition: all 0.2s ease;
847 }858 }
848 859
849- .shortcut-row:last-child {860+ .shortcut-item:hover {
850- border-bottom: none;861+ background: rgba(255, 255, 255, 0.02);
862+ border-radius: 4px;
863+ padding: 0.5rem;
864+ margin: 0 -0.5rem;
851 }865 }
852 866
853- .shortcut-row:hover {867+ .shortcut-separator {
854- background: #3d3d3d;868+ height: 1px;
869+ background: #404040;
870+ margin: 0.25rem 0;
855 }871 }
856 872
857- .shortcut-key {873+ .shortcut-key-badge {
858- padding: 0.4rem 0.8rem;874+ background: linear-gradient(135deg, #0066cc, #004499);
859- font-weight: bold;875+ color: #ffffff;
860- color: #0066cc;876+ padding: 0.25rem 0.5rem;
861- font-size: 0.85rem;877+ border-radius: 4px;
862 font-family: 'Monaco', 'Menlo', 'Ubuntu Mono', monospace;878 font-family: 'Monaco', 'Menlo', 'Ubuntu Mono', monospace;
879+ font-size: 0.75rem;
880+ font-weight: 600;
863 white-space: nowrap;881 white-space: nowrap;
864- width: 1%;882+ box-shadow: 0 1px 2px rgba(0, 102, 204, 0.2);
883+ border: 1px solid rgba(255, 255, 255, 0.1);
884+ min-width: fit-content;
865 }885 }
866 886
867 .shortcut-desc {887 .shortcut-desc {
868- padding: 0.4rem 0.8rem;
869 color: #e6e6e6;888 color: #e6e6e6;
870- font-size: 0.85rem;889+ font-size: 0.9rem;
890+ flex: 1;
871 }891 }
872 892
873 .stats-title {893 .stats-title {

Keyboard shortcuts

Single-key shortcuts are on. ctrl k and esc work whatever this says.

ctrl k :
go to a section, branch, tag, file or repository
?
this list
j k
move the row cursor down / up
enter
open the row under the cursor; on Files, a directory opens or closes in place
↑ ↓ ← → home end
in the file tree (focus on a row): previous / next row, close / open a directory or go to its parent / first entry, first / last row. They never open a file
l h
on Files: open a directory or a file / close a directory or go up to its parent, then to the parent page. Elsewhere: into the side panel (on a merge request, its files) / back to the content; there j k move between its controls
g g G
first / last row
/
filter the list; on Files, find a file anywhere in the repository (esc clears, enter opens the best match)
b
switch branch or tag
g s g f g c g b g m g i g r g a
tabs: summary, files, commits, branches & tags, merge requests, issues, releases, actions (when available)
g h
home
w
wide mode: use the whole width of the screen, or not (remembered)
y
copy a permalink pinned to the commit
d u x
diff: split / unified / collapse or expand all
e E
diff: the whole file in view / every file, with the lines the hunks hide
n
merge request: next note in the diff
esc
close a dialog, leave a field

Branches 8

Tags 42

↑↓ moveenter openesc close