Skip to content

Commit a93fd3f

Browse files
committed
feat: Add persistent storage request, enhance player controls, and update manifest shortcuts
1 parent 9f2f779 commit a93fd3f

File tree

4 files changed

+64
-20
lines changed

4 files changed

+64
-20
lines changed

.github/workflows/deploy.yml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,7 @@ jobs:
2626
uses: actions/setup-node@v4
2727
with:
2828
node-version: 20
29+
cache: 'npm'
2930

3031
- name: Install dependencies
3132
run: npm install

App.tsx

Lines changed: 10 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -123,6 +123,13 @@ const App: React.FC = () => {
123123

124124
window.addEventListener('beforeinstallprompt', handleBeforeInstall);
125125

126+
// Request persistent storage to protect user's library
127+
if (navigator.storage && navigator.storage.persist) {
128+
navigator.storage.persist().then(persistent => {
129+
if (persistent) console.log("AuraPod storage is persistent.");
130+
});
131+
}
132+
126133
const loadedPodcasts = storageService.getPodcasts();
127134
setPodcasts(loadedPodcasts);
128135
setHistory(storageService.getHistory());
@@ -456,7 +463,7 @@ const App: React.FC = () => {
456463
</button>
457464
<button
458465
onClick={() => { setView('history'); syncHistory(); }}
459-
className={`w-full flex items-center gap-3 px-3 py-2.5 rounded-xl transition ${view === 'history' ? 'bg-history' === view ? 'bg-indigo-50 dark:bg-zinc-800 text-indigo-600 dark:text-white font-medium' : 'hover:bg-zinc-200/50 dark:hover:bg-zinc-800/50' : 'hover:bg-zinc-200/50 dark:hover:bg-zinc-800/50'}`}
466+
className={`w-full flex items-center gap-3 px-3 py-2.5 rounded-xl transition ${view === 'history' ? 'bg-indigo-50 dark:bg-zinc-800 text-indigo-600 dark:text-white font-medium' : 'hover:bg-zinc-200/50 dark:hover:bg-zinc-800/50'}`}
460467
>
461468
<i className="fa-solid fa-clock-rotate-left text-sm"></i> History
462469
</button>
@@ -500,12 +507,12 @@ const App: React.FC = () => {
500507
<div className="mt-8 p-4 bg-indigo-500/10 dark:bg-indigo-900/20 border border-indigo-500/20 rounded-2xl animate-fade-in relative overflow-hidden group">
501508
<div className="absolute inset-0 aura-logo opacity-5 group-hover:opacity-10 transition"></div>
502509
<p className="text-[10px] font-bold text-indigo-600 dark:text-indigo-400 uppercase tracking-widest mb-2 relative">Always Ready</p>
503-
<h4 className="text-xs font-bold text-zinc-900 dark:text-white leading-tight mb-3 relative">Keep AuraPod on your Device</h4>
510+
<h4 className="text-xs font-bold text-zinc-900 dark:text-white leading-tight mb-3 relative">Use AuraPod as an App</h4>
504511
<button
505512
onClick={installApp}
506513
className="w-full py-2 bg-indigo-600 text-white text-[10px] font-bold rounded-xl shadow-lg shadow-indigo-500/20 hover:bg-indigo-700 transition relative"
507514
>
508-
SAVE TO DEVICE
515+
ADD TO YOUR APPS
509516
</button>
510517
<button
511518
onClick={() => setShowInstallBanner(false)}

components/Player.tsx

Lines changed: 47 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,7 @@ interface PlayerProps {
1414
onClose: () => void;
1515
onShare: () => void;
1616
onProgress?: () => void;
17-
autoPlay?: boolean; // New prop to control autoplay
17+
autoPlay?: boolean;
1818
}
1919

2020
const SPEEDS = [0.5, 0.8, 1, 1.2, 1.5, 1.7, 2];
@@ -29,7 +29,7 @@ const Player: React.FC<PlayerProps> = ({
2929
onClose,
3030
onShare,
3131
onProgress,
32-
autoPlay = true // Defaults to true for normal usage
32+
autoPlay = true
3333
}) => {
3434
const audioRef = useRef<HTMLAudioElement>(null);
3535
const [isPlaying, setIsPlaying] = useState(false);
@@ -52,6 +52,45 @@ const Player: React.FC<PlayerProps> = ({
5252
}
5353
}, [episode, podcast, error, onProgress]);
5454

55+
const togglePlay = useCallback(() => {
56+
if (audioRef.current) {
57+
if (isPlaying) {
58+
audioRef.current.pause();
59+
setIsPlaying(false);
60+
saveProgress();
61+
} else {
62+
audioRef.current.play().then(() => setIsPlaying(true)).catch(() => setIsPlaying(false));
63+
}
64+
}
65+
}, [isPlaying, saveProgress]);
66+
67+
// Media Session API Integration
68+
useEffect(() => {
69+
if ('mediaSession' in navigator) {
70+
navigator.mediaSession.metadata = new MediaMetadata({
71+
title: episode.title,
72+
artist: podcast.title,
73+
album: podcast.title,
74+
artwork: [
75+
{ src: episode.image || podcast.image, sizes: '512x512', type: 'image/png' }
76+
]
77+
});
78+
79+
navigator.mediaSession.setActionHandler('play', () => togglePlay());
80+
navigator.mediaSession.setActionHandler('pause', () => togglePlay());
81+
navigator.mediaSession.setActionHandler('seekbackward', () => {
82+
if (audioRef.current) audioRef.current.currentTime -= 15;
83+
});
84+
navigator.mediaSession.setActionHandler('seekforward', () => {
85+
if (audioRef.current) audioRef.current.currentTime += 30;
86+
});
87+
navigator.mediaSession.setActionHandler('previoustrack', () => {
88+
if (audioRef.current) audioRef.current.currentTime = 0;
89+
});
90+
navigator.mediaSession.setActionHandler('nexttrack', () => onNext());
91+
}
92+
}, [episode, podcast, onNext, togglePlay]);
93+
5594
useEffect(() => {
5695
setError(null);
5796
if (!episode.audioUrl) {
@@ -108,17 +147,13 @@ const Player: React.FC<PlayerProps> = ({
108147
const dur = audioRef.current.duration;
109148
setCurrentTime(cur);
110149
setDuration(dur);
111-
}
112-
};
113150

114-
const togglePlay = () => {
115-
if (audioRef.current) {
116-
if (isPlaying) {
117-
audioRef.current.pause();
118-
setIsPlaying(false);
119-
saveProgress();
120-
} else {
121-
audioRef.current.play().then(() => setIsPlaying(true)).catch(() => setIsPlaying(false));
151+
if ('mediaSession' in navigator && isFinite(dur)) {
152+
navigator.mediaSession.setPositionState({
153+
duration: dur,
154+
playbackRate: playbackRate,
155+
position: cur
156+
});
122157
}
123158
}
124159
};

manifest.json

Lines changed: 6 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@
77
"start_url": "./",
88
"scope": "./",
99
"display": "standalone",
10+
"display_override": ["window-controls-overlay", "standalone", "minimal-ui"],
1011
"background_color": "#09090b",
1112
"theme_color": "#8b5cf6",
1213
"categories": ["music", "multimedia", "productivity"],
@@ -26,21 +27,21 @@
2627
],
2728
"shortcuts": [
2829
{
29-
"name": "Discover",
30+
"name": "Discover New Waves",
3031
"short_name": "Discover",
31-
"description": "Find new waves",
32+
"description": "Explore trending and new podcasts",
3233
"url": "./?view=home",
3334
"icons": [{ "src": "icon.svg", "sizes": "512x512" }]
3435
},
3536
{
36-
"name": "History",
37+
"name": "Resume History",
3738
"short_name": "History",
38-
"description": "Resume your past waves",
39+
"description": "Continue listening to your past waves",
3940
"url": "./?view=history",
4041
"icons": [{ "src": "icon.svg", "sizes": "512x512" }]
4142
},
4243
{
43-
"name": "New Releases",
44+
"name": "Fresh Releases",
4445
"short_name": "New",
4546
"url": "./?view=new",
4647
"icons": [{ "src": "icon.svg", "sizes": "512x512" }]

0 commit comments

Comments
 (0)