|
44 | 44 | e.preventDefault(); |
45 | 45 | deferredPrompt = e; |
46 | 46 |
|
47 | | - // Deployment of the personalized installation suggestion at the top. |
| 47 | + // Deployment of the personalized installation notification. |
48 | 48 | renderInstallSuggestion(); |
49 | 49 | }); |
50 | 50 |
|
51 | 51 | /** |
52 | | - * renderInstallSuggestion: Orchestrates a non-intrusive UI suggestion |
53 | | - * at the document apex, encouraging the archival of AmeyArc to the device. |
| 52 | + * renderInstallSuggestion: Orchestrates a premium UI notification |
| 53 | + * at the document apex, encouraging device-level archival of AmeyArc. |
54 | 54 | */ |
55 | 55 | function renderInstallSuggestion() { |
56 | | - if (localStorage.getItem('pwa-suggestion-dismissed')) return; |
| 56 | + // Suppress if already dismissed or if the banner is already present. |
| 57 | + if (localStorage.getItem('pwa-suggestion-dismissed') || document.getElementById('pwa-install-banner')) return; |
57 | 58 |
|
58 | 59 | const banner = document.createElement('div'); |
59 | 60 | banner.id = 'pwa-install-banner'; |
|
63 | 64 | left: 0; |
64 | 65 | width: 100%; |
65 | 66 | background: var(--entry); |
66 | | - border-bottom: 1px solid var(--border); |
67 | | - padding: 10px 24px; |
| 67 | + border-bottom: 2px solid var(--primary); |
| 68 | + padding: 14px 24px; |
68 | 69 | z-index: 10001; |
69 | 70 | display: flex; |
70 | 71 | align-items: center; |
71 | 72 | justify-content: center; |
72 | 73 | cursor: pointer; |
73 | | - box-shadow: 0 2px 8px rgba(0,0,0,0.1); |
74 | | - animation: slideDown 0.5s cubic-bezier(0.4, 0, 0.2, 1); |
75 | | - transition: opacity 0.3s ease; |
| 74 | + box-shadow: 0 4px 20px rgba(0,0,0,0.15); |
| 75 | + animation: slideDown 0.6s cubic-bezier(0.23, 1, 0.32, 1); |
| 76 | + transition: all 0.4s ease; |
| 77 | + backdrop-filter: blur(10px); |
76 | 78 | `; |
77 | 79 |
|
78 | 80 | banner.innerHTML = ` |
79 | | - <div style="display: flex; align-items: center; gap: 12px;"> |
80 | | - <span style="font-size: 1.2rem;">💭</span> |
81 | | - <span style="font-size: 13px; color: var(--primary); font-weight: 500;"> |
82 | | - Install <strong>AmeyArc</strong> for a focused, offline-ready archival experience. |
83 | | - </span> |
| 81 | + <div style="display: flex; align-items: center; gap: 16px; max-width: 800px; width: 100%;"> |
| 82 | + <span style="font-size: 1.5rem; filter: drop-shadow(0 2px 4px rgba(0,0,0,0.1));">💭</span> |
| 83 | + <div style="flex-grow: 1;"> |
| 84 | + <div style="font-size: 14px; color: var(--primary); font-weight: 600; line-height: 1.2;">Archive AmeyArc to your device</div> |
| 85 | + <div style="font-size: 11px; color: var(--secondary); margin-top: 2px; opacity: 0.8;">Experience a distraction-free, offline-ready intellectual space.</div> |
| 86 | + </div> |
| 87 | + <button id="pwa-install-btn" style="background: var(--primary); color: var(--theme); border: none; padding: 6px 18px; border-radius: 20px; font-size: 12px; font-weight: 600; cursor: pointer; transition: transform 0.2s;">Install</button> |
84 | 88 | </div> |
85 | | - <button id="pwa-dismiss" style="position: absolute; right: 24px; background: none; border: none; color: var(--secondary); cursor: pointer; font-size: 16px;">×</button> |
| 89 | + <button id="pwa-dismiss" style="margin-left: 20px; background: none; border: none; color: var(--secondary); cursor: pointer; font-size: 20px; line-height: 1;">×</button> |
86 | 90 | `; |
87 | 91 |
|
| 92 | + const installBtn = banner.querySelector('#pwa-install-btn'); |
| 93 | + const dismissBtn = banner.querySelector('#pwa-dismiss'); |
| 94 | + |
88 | 95 | banner.onclick = (e) => { |
89 | | - if (e.target.id === 'pwa-dismiss') { |
90 | | - banner.style.opacity = '0'; |
91 | | - setTimeout(() => banner.remove(), 300); |
92 | | - localStorage.setItem('pwa-suggestion-dismissed', 'true'); |
| 96 | + if (e.target.id === 'pwa-dismiss' || e.target.parentElement.id === 'pwa-dismiss') { |
| 97 | + dismissBanner(); |
93 | 98 | return; |
94 | 99 | } |
95 | | - banner.remove(); |
96 | | - deferredPrompt.prompt(); |
97 | | - deferredPrompt.userChoice.then((choiceResult) => { |
98 | | - deferredPrompt = null; |
99 | | - }); |
| 100 | + if (deferredPrompt) { |
| 101 | + deferredPrompt.prompt(); |
| 102 | + deferredPrompt.userChoice.then(() => { |
| 103 | + deferredPrompt = null; |
| 104 | + dismissBanner(); |
| 105 | + }); |
| 106 | + } |
100 | 107 | }; |
101 | 108 |
|
| 109 | + function dismissBanner() { |
| 110 | + banner.style.transform = 'translateY(-100%)'; |
| 111 | + banner.style.opacity = '0'; |
| 112 | + setTimeout(() => banner.remove(), 400); |
| 113 | + localStorage.setItem('pwa-suggestion-dismissed', 'true'); |
| 114 | + } |
| 115 | + |
102 | 116 | document.body.prepend(banner); |
103 | 117 |
|
104 | 118 | // Inject animation keyframes |
105 | | - const style = document.createElement('style'); |
106 | | - style.textContent = ` |
107 | | - @keyframes slideDown { |
108 | | - from { transform: translateY(-100%); } |
109 | | - to { transform: translateY(0); } |
110 | | - } |
111 | | - `; |
112 | | - document.head.appendChild(style); |
| 119 | + if (!document.getElementById('pwa-styles')) { |
| 120 | + const style = document.createElement('style'); |
| 121 | + style.id = 'pwa-styles'; |
| 122 | + style.textContent = ` |
| 123 | + @keyframes slideDown { |
| 124 | + from { transform: translateY(-100%); opacity: 0; } |
| 125 | + to { transform: translateY(0); opacity: 1; } |
| 126 | + } |
| 127 | + #pwa-install-btn:hover { transform: scale(1.05); } |
| 128 | + #pwa-dismiss:hover { color: var(--primary); } |
| 129 | + `; |
| 130 | + document.head.appendChild(style); |
| 131 | + } |
113 | 132 | } |
114 | 133 | })(); |
0 commit comments