Chore: Bump version to v1.1.0 and implement automated release system

This commit is contained in:
dyzulk
2026-01-17 13:01:05 +07:00
parent 64609a5821
commit 5b0b6de2dc
69 changed files with 3157 additions and 2375 deletions

View File

@@ -8,8 +8,9 @@
<link rel="stylesheet" href="/assets/css/styles.css">
<script src="/assets/js/lucide.min.js"></script>
<script src="/assets/js/sweetalert2.all.min.js" defer></script>
<script src="/assets/js/alert-helper.js" defer></script>
<script src="/assets/js/i18n.js" defer></script>
<script src="/assets/js/mivo.js" defer></script>
<script src="/assets/js/modules/alert.js" defer></script>
<script src="/assets/js/modules/i18n.js" defer></script>
<style>
/* Custom Keyframes */
@keyframes fade-in-up {
@@ -39,30 +40,126 @@
<div class="absolute top-[30%] -right-[15%] w-[60vw] h-[60vw] rounded-full bg-purple-500/20 dark:bg-purple-500/5 blur-[100px] animate-pulse" style="animation-duration: 6s; animation-delay: 1s;"></div>
</div>
<!-- Floating Theme Toggle (Bottom Right) -->
<button id="theme-toggle" class="fixed bottom-6 right-6 z-50 p-3 rounded-full bg-background border border-accents-2 shadow-lg text-accents-5 hover:text-foreground hover:border-foreground transition-all duration-300 group" style="position: fixed; bottom: 1.5rem; right: 1.5rem;">
<i data-lucide="moon" class="w-5 h-5 block dark:hidden group-hover:scale-110 transition-transform"></i>
<i data-lucide="sun" class="w-5 h-5 hidden dark:block group-hover:scale-110 transition-transform"></i>
</button>
<!-- Top Right Controls (Pill Theme Toggle & Lang Switcher) -->
<div class="fixed top-4 right-4 z-50 flex items-center space-x-3">
<!-- Language Switcher -->
<div class="relative group">
<button onclick="toggleMenu('lang-dropdown-public', this)" class="h-9 px-3 rounded-full bg-background/50 backdrop-blur-md border border-accents-2 hover:border-foreground/20 text-accents-5 hover:text-foreground transition-all flex items-center shadow-sm">
<i data-lucide="globe" class="w-4 h-4 mr-2"></i>
<span class="text-xs font-semibold uppercase tracking-wider" id="current-lang-label">EN</span>
<i data-lucide="chevron-down" class="w-3 h-3 ml-2 opacity-50"></i>
</button>
<!-- Dropdown -->
<div id="lang-dropdown-public" class="hidden absolute right-0 mt-2 w-32 bg-background/95 backdrop-blur-2xl border border-white/10 rounded-xl shadow-2xl py-1 z-50 transform origin-top-right transition-all duration-200" onmouseleave="closeMenu('lang-dropdown-public')">
<button onclick="changeLanguage('en')" class="w-full text-left px-4 py-2 text-xs font-medium text-accents-5 hover:text-foreground hover:bg-white/5 flex items-center group">
<span class="mr-2 text-lg">🇺🇸</span> English
</button>
<button onclick="changeLanguage('id')" class="w-full text-left px-4 py-2 text-xs font-medium text-accents-5 hover:text-foreground hover:bg-white/5 flex items-center group">
<span class="mr-2 text-lg">🇮🇩</span> Indonesia
</button>
</div>
</div>
<!-- Theme Toggle Pill -->
<div class="h-9 p-1 bg-accents-2/50 backdrop-blur-md border border-accents-2 rounded-full flex items-center relative" id="theme-pill">
<!-- Gliding Background -->
<div class="absolute top-1 bottom-1 w-[calc(50%-4px)] bg-background rounded-full shadow-sm transition-all duration-300 ease-spring" id="theme-glider" style="left: 4px;"></div>
<button onclick="setTheme('light')" class="relative z-10 w-8 h-full flex items-center justify-center text-accents-5 hover:text-foreground transition-colors rounded-full" id="btn-light">
<i data-lucide="sun" class="w-4 h-4"></i>
</button>
<button onclick="setTheme('dark')" class="relative z-10 w-8 h-full flex items-center justify-center text-accents-5 hover:text-foreground transition-colors rounded-full" id="btn-dark">
<i data-lucide="moon" class="w-4 h-4"></i>
</button>
</div>
</div>
<script>
// Toggle Menu Helper (Reuse or define for public if main footer not loaded)
// Public footer includes site config footer, but maybe not main JS.
// Let's define simple toggle for public page to be safe and independent.
function toggleMenu(id, btn) {
const el = document.getElementById(id);
if (!el) return;
const isHidden = el.classList.contains('hidden');
// Close others if needed (optional)
if (isHidden) {
el.classList.remove('hidden', 'scale-95', 'opacity-0');
el.classList.add('scale-100', 'opacity-100');
} else {
closeMenu(id);
}
}
function closeMenu(id) {
const el = document.getElementById(id);
if (el && !el.classList.contains('hidden')) {
el.classList.remove('scale-100', 'opacity-100');
el.classList.add('hidden', 'scale-95', 'opacity-0');
}
}
document.addEventListener('DOMContentLoaded', () => {
lucide.createIcons();
// Theme Toggle Logic
const themeToggleBtn = document.getElementById('theme-toggle');
// Theme Logic
const glider = document.getElementById('theme-glider');
const btnLight = document.getElementById('btn-light');
const btnDark = document.getElementById('btn-dark');
const htmlElement = document.documentElement;
if(themeToggleBtn){
themeToggleBtn.addEventListener('click', () => {
if (htmlElement.classList.contains('dark')) {
htmlElement.classList.remove('dark');
localStorage.theme = 'light';
} else {
htmlElement.classList.add('dark');
localStorage.theme = 'dark';
}
});
window.setTheme = (theme) => {
if (theme === 'dark') {
htmlElement.classList.add('dark');
localStorage.theme = 'dark';
glider.style.transform = 'translateX(100%)';
// adjustment: logic depends on width.
// container is w-8+w-8+padding.
// simplest is just left/right toggle classes or transform.
// using transform translateX(100%) works if width is exactly 50% parent minus padding.
// padding is 1 (4px). buttons are w-8 (32px).
// let's use explicit left style or class-based positioning if easier.
// Tailwind 'translate-x-full' moves 100% of own width.
// If glider is w-[calc(50%-4px)], moving 100% of itself is almost correct but includes gap.
// Let's rely on simple pixel math or percentage relative to parent?
// actually `left: 4px` vs `left: calc(100% - width - 4px)`.
glider.style.left = 'auto';
glider.style.right = '4px';
} else {
htmlElement.classList.remove('dark');
localStorage.theme = 'light';
glider.style.right = 'auto';
glider.style.left = '4px';
}
// Update Active Colors
if (theme === 'dark') {
btnDark.classList.add('text-foreground');
btnLight.classList.remove('text-foreground');
} else {
btnLight.classList.add('text-foreground');
btnDark.classList.remove('text-foreground');
}
};
// Init
if (localStorage.theme === 'dark' || (!('theme' in localStorage) && window.matchMedia('(prefers-color-scheme: dark)').matches)) {
setTheme('dark');
} else {
setTheme('light');
}
// Language Init (Mock)
const currentLang = localStorage.getItem('mivo_lang') || 'en';
const langLabel = document.getElementById('current-lang-label');
if(langLabel) langLabel.innerText = currentLang.toUpperCase();
window.changeLanguage = (lang) => {
localStorage.setItem('mivo_lang', lang);
// Reload or use i18n module to reload
location.reload();
};
});
</script>