Brunwo commited on
Commit
9e47428
·
1 Parent(s): d09fd1e

adding api key to pwa

Browse files
Files changed (3) hide show
  1. index.html +17 -0
  2. script.js +147 -63
  3. styles.css +79 -1
index.html CHANGED
@@ -11,6 +11,23 @@
11
  <body>
12
  <h1>web to podcast player</h1>
13
  <audio id="player" controls></audio>
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
14
 
15
  <script src="/script.js"></script>
16
  </body>
 
11
  <body>
12
  <h1>web to podcast player</h1>
13
  <audio id="player" controls></audio>
14
+
15
+ <!-- Add settings button -->
16
+ <button id="settingsBtn">Settings</button>
17
+
18
+ <!-- Add settings modal -->
19
+ <div id="settingsModal" class="modal">
20
+ <div class="modal-content">
21
+ <span class="close">&times;</span>
22
+ <h2>Settings</h2>
23
+ <label for="apiKey">OpenAI API Key:</label>
24
+ <div class="api-key-container">
25
+ <input type="password" id="apiKey" placeholder="Enter your API key">
26
+ <button id="toggleApiKey">👁️</button>
27
+ </div>
28
+ <button id="saveSettings">Save</button>
29
+ </div>
30
+ </div>
31
 
32
  <script src="/script.js"></script>
33
  </body>
script.js CHANGED
@@ -1,89 +1,173 @@
1
  document.addEventListener("DOMContentLoaded", function() {
2
  const audioPlayer = document.getElementById('player');
3
-
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
4
  // Function to fetch MP3 from API endpoint when a link is shared
5
  async function fetchMp3(link) {
6
- try {
7
- const response = await fetch('/api/generate-audio', {
8
- method: 'POST',
9
- headers: {
10
- 'Content-Type': 'application/json',
11
- },
12
- body: JSON.stringify({
13
- url: link,
14
- // Add other necessary parameters here
15
- openai_api_key: 'your_api_key_here', // Be cautious with API keys in client-side code
16
- text_model: 'gpt-4o-mini',
17
- audio_model: 'tts-1',
18
- speaker_1_voice: 'alloy',
19
- speaker_2_voice: 'echo',
20
- // ... other parameters ...
21
- }),
22
- });
23
-
24
- if (!response.ok) {
25
- throw new Error("Network response was not ok");
26
- }
 
 
 
 
 
27
 
28
- const data = await response.json();
29
- if (data.error) {
30
- throw new Error(data.error);
31
- }
32
 
33
- // Set the audio player source
34
- audioPlayer.src = data.audio_file;
35
- audioPlayer.play();
36
- } catch (error) {
37
- console.error('Error fetching MP3:', error);
38
- }
 
39
  }
40
 
41
- // Get the link from the shared URL or use a default one
42
  const queryParams = new URLSearchParams(window.location.search);
43
- const sharedLink = queryParams.get('link') || 'https://example.com/default-text';
44
 
45
- // Call the API to get MP3
46
- fetchMp3(sharedLink);
47
- });
48
-
 
 
 
 
49
 
50
- if ('mediaSession' in navigator) {
51
  navigator.mediaSession.metadata = new MediaMetadata({
52
- title: 'Sample MP3',
53
- artist: 'Unknown Artist',
54
- album: 'Demo Album',
55
- artwork: [
56
- { src: '/icons/icon-192x192.png', sizes: '192x192', type: 'image/png' },
57
- { src: '/icons/icon-512x512.png', sizes: '512x512', type: 'image/png' }
58
- ]
59
  });
60
 
61
  navigator.mediaSession.setActionHandler('play', function() {
62
- audioPlayer.play();
63
  });
64
 
65
  navigator.mediaSession.setActionHandler('pause', function() {
66
- audioPlayer.pause();
67
  });
68
 
69
  navigator.mediaSession.setActionHandler('seekbackward', function() {
70
- audioPlayer.currentTime = Math.max(audioPlayer.currentTime - 10, 0);
71
  });
72
 
73
  navigator.mediaSession.setActionHandler('seekforward', function() {
74
- audioPlayer.currentTime = Math.min(audioPlayer.currentTime + 10, audioPlayer.duration);
75
  });
76
- }
77
-
78
- // JavaScript code to read URL parameters
79
- const urlParams = new URLSearchParams(window.location.search);
80
 
81
- // Retrieve specific parameters
82
- const name = urlParams.get('name'); // "John"
83
- const age = urlParams.get('age'); // "30"
84
-
85
- // Display the parameters in the output div
86
- document.getElementById('shared-content').innerHTML = `
87
- <p>Name: ${name}</p>
88
- <p>Age: ${age}</p>
89
- `;
 
1
  document.addEventListener("DOMContentLoaded", function() {
2
  const audioPlayer = document.getElementById('player');
3
+ const settingsBtn = document.getElementById('settingsBtn');
4
+ const settingsModal = document.getElementById('settingsModal');
5
+ const closeBtn = document.querySelector('.close');
6
+ const saveSettingsBtn = document.getElementById('saveSettings');
7
+ const apiKeyInput = document.getElementById('apiKey');
8
+ const toggleApiKeyBtn = document.getElementById('toggleApiKey');
9
+
10
+ let originalApiKey = '';
11
+
12
+ // Load saved API key on page load
13
+ const savedApiKey = localStorage.getItem('openaiApiKey');
14
+ if (savedApiKey) {
15
+ apiKeyInput.value = savedApiKey;
16
+ originalApiKey = savedApiKey;
17
+ }
18
+
19
+ // Toggle API key visibility
20
+ toggleApiKeyBtn.onclick = function() {
21
+ if (apiKeyInput.type === "password") {
22
+ apiKeyInput.type = "text";
23
+ toggleApiKeyBtn.textContent = "🔒";
24
+ } else {
25
+ apiKeyInput.type = "password";
26
+ toggleApiKeyBtn.textContent = "👁️";
27
+ }
28
+ }
29
+
30
+ // Open settings modal
31
+ settingsBtn.onclick = function() {
32
+ originalApiKey = apiKeyInput.value;
33
+ settingsModal.style.display = "block";
34
+ apiKeyInput.focus();
35
+ }
36
+
37
+ // Close settings modal
38
+ function closeModal() {
39
+ settingsModal.style.display = "none";
40
+ apiKeyInput.value = originalApiKey; // Revert to original value
41
+ }
42
+
43
+ closeBtn.onclick = closeModal;
44
+
45
+ // Close modal if clicked outside
46
+ window.onclick = function(event) {
47
+ if (event.target == settingsModal) {
48
+ closeModal();
49
+ }
50
+ }
51
+
52
+ // Handle keydown events
53
+ document.addEventListener('keydown', function(event) {
54
+ if (settingsModal.style.display === "block") {
55
+ if (event.key === "Escape") {
56
+ closeModal();
57
+ } else if (event.key === "Enter") {
58
+ saveSettings();
59
+ }
60
+ }
61
+ });
62
+
63
+ // Save settings
64
+ function saveSettings() {
65
+ const apiKey = apiKeyInput.value.trim();
66
+ if (apiKey) {
67
+ localStorage.setItem('openaiApiKey', apiKey);
68
+ originalApiKey = apiKey; // Update original key
69
+ alert('API key saved successfully!');
70
+ closeModal();
71
+ } else {
72
+ alert('Please enter a valid API key.');
73
+ }
74
+ }
75
+
76
+ saveSettingsBtn.onclick = saveSettings;
77
+
78
  // Function to fetch MP3 from API endpoint when a link is shared
79
  async function fetchMp3(link) {
80
+ try {
81
+ const apiKey = localStorage.getItem('openaiApiKey');
82
+ if (!apiKey) {
83
+ throw new Error("API key not set. Please set your OpenAI API key in the settings.");
84
+ }
85
+
86
+ const response = await fetch('/api/generate-audio', {
87
+ method: 'POST',
88
+ headers: {
89
+ 'Content-Type': 'application/json',
90
+ },
91
+ body: JSON.stringify({
92
+ url: link,
93
+ // Use the saved API key
94
+ openai_api_key: apiKey,
95
+ text_model: 'gpt-4o-mini',
96
+ audio_model: 'tts-1',
97
+ speaker_1_voice: 'alloy',
98
+ speaker_2_voice: 'echo',
99
+ // ... other parameters ...
100
+ }),
101
+ });
102
+
103
+ if (!response.ok) {
104
+ throw new Error("Network response was not ok");
105
+ }
106
 
107
+ const data = await response.json();
108
+ if (data.error) {
109
+ throw new Error(data.error);
110
+ }
111
 
112
+ // Set the audio player source
113
+ audioPlayer.src = data.audio_file;
114
+ audioPlayer.play();
115
+ } catch (error) {
116
+ console.error('Error fetching MP3:', error);
117
+ alert(error.message);
118
+ }
119
  }
120
 
121
+ // Get the link from the shared URL
122
  const queryParams = new URLSearchParams(window.location.search);
123
+ const sharedLink = queryParams.get('url');
124
 
125
+ // Only call the API to get MP3 if a valid URL is provided
126
+ if (sharedLink) {
127
+ fetchMp3(sharedLink);
128
+ } else {
129
+ console.log("No URL provided. Waiting for user input.");
130
+ // You might want to update the UI here to indicate that the user needs to provide a URL
131
+ }
132
+ });
133
 
134
+ if ('mediaSession' in navigator) {
135
  navigator.mediaSession.metadata = new MediaMetadata({
136
+ title: 'Sample MP3',
137
+ artist: 'Unknown Artist',
138
+ album: 'Demo Album',
139
+ artwork: [
140
+ { src: '/icons/icon-192x192.png', sizes: '192x192', type: 'image/png' },
141
+ { src: '/icons/icon-512x512.png', sizes: '512x512', type: 'image/png' }
142
+ ]
143
  });
144
 
145
  navigator.mediaSession.setActionHandler('play', function() {
146
+ audioPlayer.play();
147
  });
148
 
149
  navigator.mediaSession.setActionHandler('pause', function() {
150
+ audioPlayer.pause();
151
  });
152
 
153
  navigator.mediaSession.setActionHandler('seekbackward', function() {
154
+ audioPlayer.currentTime = Math.max(audioPlayer.currentTime - 10, 0);
155
  });
156
 
157
  navigator.mediaSession.setActionHandler('seekforward', function() {
158
+ audioPlayer.currentTime = Math.min(audioPlayer.currentTime + 10, audioPlayer.duration);
159
  });
160
+ }
161
+
162
+ // JavaScript code to read URL parameters
163
+ const urlParams = new URLSearchParams(window.location.search);
164
 
165
+ // Retrieve specific parameters
166
+ const name = urlParams.get('name'); // "John"
167
+ const age = urlParams.get('age'); // "30"
168
+
169
+ // Display the parameters in the output div
170
+ document.getElementById('shared-content').innerHTML = `
171
+ <p>Name: ${name}</p>
172
+ <p>Age: ${age}</p>
173
+ `;
styles.css CHANGED
@@ -6,4 +6,82 @@ body {
6
  audio {
7
  width: 100%;
8
  }
9
-
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
6
  audio {
7
  width: 100%;
8
  }
9
+
10
+ /* Add this to your existing styles.css file */
11
+
12
+ .modal {
13
+ display: none;
14
+ position: fixed;
15
+ z-index: 1;
16
+ left: 0;
17
+ top: 0;
18
+ width: 100%;
19
+ height: 100%;
20
+ overflow: auto;
21
+ background-color: rgba(0,0,0,0.4);
22
+ }
23
+
24
+ .modal-content {
25
+ background-color: #fefefe;
26
+ margin: 15% auto;
27
+ padding: 20px;
28
+ border: 1px solid #888;
29
+ width: 80%;
30
+ max-width: 500px;
31
+ }
32
+
33
+ .close {
34
+ color: #aaa;
35
+ float: right;
36
+ font-size: 28px;
37
+ font-weight: bold;
38
+ cursor: pointer;
39
+ }
40
+
41
+ .close:hover,
42
+ .close:focus {
43
+ color: black;
44
+ text-decoration: none;
45
+ cursor: pointer;
46
+ }
47
+
48
+ #apiKey {
49
+ width: 100%;
50
+ padding: 5px;
51
+ margin: 10px 0;
52
+ }
53
+
54
+ #saveSettings {
55
+ background-color: #4CAF50;
56
+ color: white;
57
+ padding: 10px 15px;
58
+ border: none;
59
+ cursor: pointer;
60
+ }
61
+
62
+ #saveSettings:hover {
63
+ background-color: #45a049;
64
+ }
65
+
66
+ .api-key-container {
67
+ display: flex;
68
+ align-items: center;
69
+ margin: 10px 0;
70
+ }
71
+
72
+ #apiKey {
73
+ flex-grow: 1;
74
+ margin-right: 5px;
75
+ }
76
+
77
+ #toggleApiKey {
78
+ background-color: #f0f0f0;
79
+ border: 1px solid #ccc;
80
+ padding: 5px 10px;
81
+ cursor: pointer;
82
+ font-size: 16px;
83
+ }
84
+
85
+ #toggleApiKey:hover {
86
+ background-color: #e0e0e0;
87
+ }