| """ |
| Floating Donation Widget Component |
| Separated for better performance and maintainability |
| """ |
|
|
| import streamlit as st |
|
|
| def render_donation_widget(): |
| """Render the floating donation widget with optimized CSS and JS""" |
| |
| st.markdown(""" |
| <style> |
| /* Floating Donation Widgets - Optimized */ |
| .floating-donations { |
| position: fixed; |
| right: 20px; |
| top: 50%; |
| transform: translateY(-50%); |
| z-index: 1000; |
| display: flex; |
| flex-direction: column; |
| gap: 15px; |
| } |
| |
| .floating-btn { |
| width: 60px; |
| height: 60px; |
| border-radius: 50%; |
| display: flex; |
| align-items: center; |
| justify-content: center; |
| text-decoration: none; |
| font-weight: bold; |
| font-size: 14px; |
| box-shadow: 0 4px 20px rgba(0,0,0,0.3); |
| transition: all 0.3s ease; |
| cursor: pointer; |
| border: none; |
| position: relative; |
| overflow: hidden; |
| will-change: transform; |
| } |
| |
| .floating-btn:hover { |
| transform: scale(1.1); |
| box-shadow: 0 6px 30px rgba(0,0,0,0.4); |
| text-decoration: none; |
| } |
| |
| .floating-btn:before { |
| content: ''; |
| position: absolute; |
| top: 0; |
| left: -100%; |
| width: 100%; |
| height: 100%; |
| background: linear-gradient(90deg, transparent, rgba(255,255,255,0.2), transparent); |
| transition: left 0.5s; |
| } |
| |
| .floating-btn:hover:before { |
| left: 100%; |
| } |
| |
| .kofi-floating { |
| background: linear-gradient(135deg, #ff5f5f, #ff3838); |
| color: white; |
| } |
| |
| .saweria-floating { |
| background: linear-gradient(135deg, #ffbd44, #f39c12); |
| color: #2c3e50; |
| } |
| |
| .floating-tooltip { |
| position: absolute; |
| right: 70px; |
| top: 50%; |
| transform: translateY(-50%); |
| background: rgba(0,0,0,0.8); |
| color: white; |
| padding: 8px 12px; |
| border-radius: 6px; |
| font-size: 12px; |
| white-space: nowrap; |
| opacity: 0; |
| visibility: hidden; |
| transition: all 0.3s ease; |
| pointer-events: none; |
| } |
| |
| .floating-tooltip:after { |
| content: ''; |
| position: absolute; |
| left: 100%; |
| top: 50%; |
| transform: translateY(-50%); |
| border: 5px solid transparent; |
| border-left-color: rgba(0,0,0,0.8); |
| } |
| |
| .floating-btn:hover .floating-tooltip { |
| opacity: 1; |
| visibility: visible; |
| } |
| |
| /* Responsive hiding for mobile */ |
| @media (max-width: 768px) { |
| .floating-donations { |
| display: none; |
| } |
| } |
| |
| /* Ko-fi widget custom styling */ |
| .kofi-widget-container { |
| position: fixed !important; |
| bottom: 20px !important; |
| right: 20px !important; |
| z-index: 999 !important; |
| } |
| |
| /* Hide default Ko-fi widget on mobile */ |
| @media (max-width: 768px) { |
| .kofi-widget-container { |
| display: none !important; |
| } |
| } |
| </style> |
| """, unsafe_allow_html=True) |
|
|
| def render_donation_html(): |
| """Render the HTML structure for donation widgets""" |
| |
| st.markdown(""" |
| <!-- Floating Donation Widgets --> |
| <div class="floating-donations"> |
| <a href="https://ko-fi.com/saltudio" target="_blank" class="floating-btn kofi-floating" rel="noopener"> |
| <span>β</span> |
| <div class="floating-tooltip">Support on Ko-fi</div> |
| </a> |
| <a href="https://saweria.co/saltudio" target="_blank" class="floating-btn saweria-floating" rel="noopener"> |
| <span>π</span> |
| <div class="floating-tooltip">Support on Saweria</div> |
| </a> |
| </div> |
| """, unsafe_allow_html=True) |
|
|
| @st.cache_resource |
| def load_donation_scripts(): |
| """Load donation widget scripts with caching""" |
| |
| return """ |
| <!-- Ko-fi Floating Widget Script --> |
| <script src='https://storage.ko-fi.com/cdn/scripts/overlay-widget.js' async defer></script> |
| <script> |
| // Lazy load Ko-fi widget |
| document.addEventListener('DOMContentLoaded', function() { |
| if (typeof kofiWidgetOverlay !== 'undefined') { |
| kofiWidgetOverlay.draw('saltudio', { |
| 'type': 'floating-chat', |
| 'floating-chat.donateButton.text': 'Support me', |
| 'floating-chat.donateButton.background-color': '#ff38b8', |
| 'floating-chat.donateButton.text-color': '#fff' |
| }); |
| } |
| }); |
| |
| // Custom Saweria floating widget - optimized |
| (function() { |
| function initDonationWidgets() { |
| const kofiWidget = document.querySelector('.kofi-widget-container'); |
| const customWidgets = document.querySelector('.floating-donations'); |
| |
| if (kofiWidget && customWidgets) { |
| customWidgets.style.bottom = '100px'; |
| customWidgets.style.top = 'auto'; |
| customWidgets.style.transform = 'none'; |
| } |
| |
| // Add click tracking with throttling |
| let clickThrottle = false; |
| document.querySelectorAll('.floating-btn').forEach(btn => { |
| btn.addEventListener('click', function(e) { |
| if (!clickThrottle) { |
| clickThrottle = true; |
| const platform = this.classList.contains('kofi-floating') ? 'ko-fi' : 'saweria'; |
| console.log(`Donation click: ${platform}`); |
| setTimeout(() => clickThrottle = false, 1000); |
| } |
| }); |
| }); |
| } |
| |
| // Initialize when DOM is ready |
| if (document.readyState === 'loading') { |
| document.addEventListener('DOMContentLoaded', initDonationWidgets); |
| } else { |
| initDonationWidgets(); |
| } |
| })(); |
| </script> |
| """ |
|
|
| def render_donation_scripts(): |
| """Render donation widget scripts""" |
| scripts = load_donation_scripts() |
| st.markdown(scripts, unsafe_allow_html=True) |
|
|
| def render_sidebar_support(): |
| """Render compact support section for sidebar""" |
| |
| st.markdown(""" |
| <div style="text-align: center;"> |
| <p style="color: #9fb0c3; font-size: 0.9rem; margin-bottom: 1rem;"> |
| Help keep this free tool running! |
| </p> |
| <div style="display: flex; gap: 10px; justify-content: center;"> |
| <a href="https://ko-fi.com/saltudio" target="_blank" style="text-decoration: none;" rel="noopener"> |
| <div style="background: linear-gradient(135deg, #ff5f5f, #ff3838); color: white; padding: 8px 16px; border-radius: 20px; font-size: 0.8rem; display: inline-flex; align-items: center; gap: 5px;"> |
| β Ko-fi |
| </div> |
| </a> |
| <a href="https://saweria.co/saltudio" target="_blank" style="text-decoration: none;" rel="noopener"> |
| <div style="background: linear-gradient(135deg, #ffbd44, #f39c12); color: #2c3e50; padding: 8px 16px; border-radius: 20px; font-size: 0.8rem; display: inline-flex; align-items: center; gap: 5px;"> |
| π Saweria |
| </div> |
| </a> |
| </div> |
| </div> |
| """, unsafe_allow_html=True) |
|
|
| def render_footer_support(): |
| """Render footer support section""" |
| |
| st.markdown(""" |
| <div style="text-align: center; padding: 20px; color: #9fb0c3;"> |
| <p>π <strong>Enjoying VidGen?</strong> Support the project to keep it free!</p> |
| <p style="font-size: 0.9rem;"> |
| Use the floating buttons on the right or the links in the sidebar to show your appreciation. |
| <br>Every coffee helps maintain the servers and develop new features! ββ¨ |
| </p> |
| <p style="font-size: 0.8rem; margin-top: 1rem;"> |
| Made with β€οΈ using Streamlit β’ Veo β’ HuggingFace Spaces |
| </p> |
| </div> |
| """, unsafe_allow_html=True) |