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 @@ | |||
| 1 | 1 | <script lang="ts"> | |
| 2 | 2 | import { onMount } from 'svelte'; | |
| 3 | + | import Footer from '$components/Footer.svelte'; | |
| 3 | 4 | // Icons disabled for investigation: removed @lucide/svelte imports | |
| 4 | 5 | ||
| 5 | 6 | interface HistoryItem { | |
| @@ -401,7 +402,10 @@ | |||
| 401 | 402 | try { | |
| 402 | 403 | // Set up response handler | |
| 403 | 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 | 409 | topVisitedLoading = false; | |
| 406 | 410 | }; | |
| 407 | 411 | ||
| @@ -417,7 +421,7 @@ | |||
| 417 | 421 | bridge.postMessage(JSON.stringify({ | |
| 418 | 422 | type: 'history_search', | |
| 419 | 423 | q: '', | |
| 420 | - | limit: 5 | |
| 424 | + | limit: 50 // Get more results to sort properly | |
| 421 | 425 | })); | |
| 422 | 426 | } else { | |
| 423 | 427 | throw new Error('WebKit message handler not available'); | |
| @@ -565,33 +569,16 @@ | |||
| 565 | 569 | {#if shortcutsLoading} | |
| 566 | 570 | <div class="loading">Loading shortcuts...</div> | |
| 567 | 571 | {: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} | |
| 595 | 582 | </div> | |
| 596 | 583 | {/if} | |
| 597 | 584 | </div> | |
| @@ -625,8 +612,28 @@ | |||
| 625 | 612 | </div> | |
| 626 | 613 | {/if} | |
| 627 | 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 | 633 | </div> | |
| 629 | 634 | </div> | |
| 635 | + | ||
| 636 | + | <Footer /> | |
| 630 | 637 | </div> | |
| 631 | 638 | ||
| 632 | 639 | <style> | |
| @@ -661,6 +668,7 @@ | |||
| 661 | 668 | .container { | |
| 662 | 669 | flex: 1; | |
| 663 | 670 | display: flex; | |
| 671 | + | align-items: stretch; | |
| 664 | 672 | max-width: 1200px; | |
| 665 | 673 | margin: 0 auto; | |
| 666 | 674 | width: 100%; | |
| @@ -673,6 +681,8 @@ | |||
| 673 | 681 | flex: 2; | |
| 674 | 682 | min-height: 0; | |
| 675 | 683 | min-width: 0; | |
| 684 | + | display: flex; | |
| 685 | + | flex-direction: column; | |
| 676 | 686 | } | |
| 677 | 687 | ||
| 678 | 688 | .shortcuts-section { | |
| @@ -692,8 +702,8 @@ | |||
| 692 | 702 | .history-list { | |
| 693 | 703 | overflow-y: auto; | |
| 694 | 704 | overflow-x: hidden; | |
| 695 | - | max-height: calc(100vh - 8rem); | |
| 696 | 705 | max-width: 100%; | |
| 706 | + | max-height: calc(100vh - 8rem); | |
| 697 | 707 | } | |
| 698 | 708 | ||
| 699 | 709 | .history-item { | |
| @@ -829,45 +839,55 @@ | |||
| 829 | 839 | } | |
| 830 | 840 | ||
| 831 | 841 | .shortcuts-container { | |
| 832 | - | max-height: calc(100vh - 8rem); | |
| 833 | - | overflow-y: auto; | |
| 842 | + | /* Remove height limit to show all shortcuts */ | |
| 834 | 843 | } | |
| 835 | 844 | ||
| 836 | - | .shortcuts-table { | |
| 837 | - | width: 100%; | |
| 838 | - | border-collapse: collapse; | |
| 845 | + | .shortcuts-card { | |
| 839 | 846 | background: #2d2d2d; | |
| 840 | - | border-radius: 6px; | |
| 841 | - | overflow: hidden; | |
| 847 | + | border-radius: 8px; | |
| 848 | + | border: 1px solid #404040; | |
| 849 | + | padding: 1rem; | |
| 842 | 850 | } | |
| 843 | 851 | ||
| 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; | |
| 847 | 858 | } | |
| 848 | 859 | ||
| 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; | |
| 851 | 865 | } | |
| 852 | 866 | ||
| 853 | - | .shortcut-row:hover { | |
| 854 | - | background: #3d3d3d; | |
| 867 | + | .shortcut-separator { | |
| 868 | + | height: 1px; | |
| 869 | + | background: #404040; | |
| 870 | + | margin: 0.25rem 0; | |
| 855 | 871 | } | |
| 856 | 872 | ||
| 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; | |
| 862 | 878 | font-family: 'Monaco', 'Menlo', 'Ubuntu Mono', monospace; | |
| 879 | + | font-size: 0.75rem; | |
| 880 | + | font-weight: 600; | |
| 863 | 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 | 887 | .shortcut-desc { | |
| 868 | - | padding: 0.4rem 0.8rem; | |
| 869 | 888 | color: #e6e6e6; | |
| 870 | - | font-size: 0.85rem; | |
| 889 | + | font-size: 0.9rem; | |
| 890 | + | flex: 1; | |
| 871 | 891 | } | |
| 872 | 892 | ||
| 873 | 893 | .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 imports | 4 | // 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 handler | 403 | // 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: 5 | 424 | + | 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 { | ||