Skip to content

feat(spotify): basic controls + oauth state validation#1

Open
DanielMouraoti wants to merge 2 commits intomainfrom
feature/spotify-basic-controls
Open

feat(spotify): basic controls + oauth state validation#1
DanielMouraoti wants to merge 2 commits intomainfrom
feature/spotify-basic-controls

Conversation

@DanielMouraoti
Copy link
Copy Markdown
Owner

No description provided.

Copilot AI review requested due to automatic review settings March 14, 2026 20:54
Copy link
Copy Markdown

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

This PR expands the Chrome extension with Spotify integration (OAuth + basic playback controls), a new “stats” visualization in the popup, and a Manifest V3 offscreen-based audio system.

Changes:

  • Add Spotify OAuth flow (PKCE) in the service worker plus popup controls (connect/play/pause/next/prev) and status handling.
  • Introduce a new “productivity” stats rendering in the popup (CSS-based stacked bars + legend) and broaden i18n support.
  • Add MV3 offscreen document audio synthesis (Web Audio API) and update manifests/permissions/locales/assets accordingly.

Reviewed changes

Copilot reviewed 25 out of 28 changed files in this pull request and generated 19 comments.

Show a summary per file
File Description
popup.js Popup UI logic: i18n, stats rendering, timer polling, Spotify controls/status.
popup.html Popup UI markup and styling updates; adds Spotify config UI and stats container.
background.js Timer persistence + Spotify OAuth (PKCE/state validation) + playback API handlers.
offscreen.js Offscreen document to synthesize timer sounds with Web Audio API.
offscreen.html Offscreen document container page.
manifest.json MV3 permissions/host permissions/CSP updates; Spotify oauth2 config.
chart.js Bundled chart library artifact (currently appears unused by the new stats UI).
_locales/pt_BR/messages.json Adds i18n strings (days of week + category labels).
_locales/en/messages.json Adds i18n strings (days of week + category labels).
assets/README.md Documents audio assets and fallback behavior.
assets/sparkle.mp3 Added audio asset placeholder.
assets/piano.mp3 Added audio asset placeholder.
assets/chime.mp3 Added audio asset placeholder.
assets/bell.mp3 Added audio asset placeholder.
.gitignore Adds broad documentation ignore rules and other ignore patterns.
README.md Project documentation updates including Spotify quick start links.
LICENSE Adds MIT license text.
study-ai-v1.0.0-stable/popup.js “Stable” copy of popup logic (same feature set).
study-ai-v1.0.0-stable/popup.html “Stable” popup markup/styles.
study-ai-v1.0.0-stable/background.js “Stable” service worker logic.
study-ai-v1.0.0-stable/offscreen.js “Stable” offscreen audio synthesis.
study-ai-v1.0.0-stable/offscreen.html “Stable” offscreen container page.
study-ai-v1.0.0-stable/manifest.json “Stable” manifest changes.
study-ai-v1.0.0-stable/chart.js “Stable” chart library artifact.
study-ai-v1.0.0-stable/_locales/pt_BR/messages.json “Stable” locale strings.
study-ai-v1.0.0-stable/_locales/en/messages.json “Stable” locale strings.
study-ai-v1.0.0-stable/assets/README.md “Stable” assets documentation.
study-ai-v1.0.0-stable/assets/sparkle.mp3 “Stable” audio asset placeholder.
study-ai-v1.0.0-stable/assets/piano.mp3 “Stable” audio asset placeholder.
study-ai-v1.0.0-stable/assets/chime.mp3 “Stable” audio asset placeholder.
study-ai-v1.0.0-stable/assets/bell.mp3 “Stable” audio asset placeholder.
study-ai-v1.0.0-stable/.gitignore “Stable” ignore rules.
study-ai-v1.0.0-stable/README.md “Stable” README.
study-ai-v1.0.0-stable/LICENSE “Stable” license.
Comments suppressed due to low confidence (1)

study-ai-v1.0.0-stable/assets/sparkle.mp3:2

  • Este arquivo *.mp3 parece ser apenas um placeholder de texto (ID3) e não um MP3 válido. Se a extensão pretende distribuir sons reais, os arquivos precisam ser binários válidos (ou removidos do repo e gerados/baixados via build). Como está, pode confundir e quebrar qualquer tentativa futura de playback por arquivo.
ID3


💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

You can also share your feedback on Copilot code review. Take the survey.

await fullSync();

// PRIORIDADE 2: Iniciar polling do Timer (mantém sincronizado)
setInterval(pollTimer, 200);
Comment on lines +21 to +25
"https://api.spotify.com/*",
"https://actions.google.com/*"
],
"web_accessible_resources": [
{
Comment on lines +22 to +23
"https://accounts.spotify.com/*",
"https://actions.google.com/*"
Comment on lines +65 to 69
- [docs/SPOTIFY_INTEGRATION.md](docs/SPOTIFY_INTEGRATION.md)
- [docs/MESSAGE_CONTRACT.md](docs/MESSAGE_CONTRACT.md)

---

*.md
!README.md
!LICENSE.md
!.github/**/*.md
Comment on lines +258 to +259
const isEnglish = State.language === 'en';
const labels = isEnglish
Comment on lines +1462 to +1483
// Language select
if ($('languageSelect')) {
$('languageSelect').addEventListener('change', async (e) => {
const newLang = e.target.value;
State.language = newLang;
await chrome.storage.local.set({ language: State.language });

// Atualizar título imediatamente se estiver na aba Stats
const titleEl = document.getElementById('productivity-title');
if (titleEl) {
const isEnglish = newLang === 'en';
titleEl.innerText = isEnglish ? '📊 Productivity' : '📊 Produtividade';
}

// Re-renderizar gráfico se estiver na aba Stats
if (State.activeTab === 'stats') {
await new Promise(r => setTimeout(r, 50));
renderStudyMetrics();
}
});
}

Comment on lines +50 to +60
// Calcular duração exata (do modo do timer)
const duration = MODES[timerState.mode] || MODES.focus;

// Registrar sessão com detalhes completos
const session = {
timestamp: now.toISOString(),
duration: MODES[timerState.mode] || MODES.focus,
date: now.toLocaleDateString('pt-BR'),
time: now.toLocaleTimeString('pt-BR'),
duration: duration, // em segundos
mode: timerState.mode,
category: currentCategory
});
category: currentCategory,
Comment on lines +24 to +32
"web_accessible_resources": [
{
"resources": [
"offscreen.html",
"assets/*"
],
"matches": ["<all_urls>"]
}
],
Comment on lines +632 to 638
const state = randomString(16);
const codeVerifier = randomString(64);
const codeChallenge = await sha256Base64Url(codeVerifier);

const url = new URL(redirectUrl);
const token = url.hash.match(/access_token=([^&]+)/)?.[1];
const expiresIn = url.hash.match(/expires_in=([^&]+)/)?.[1];
spotifyRuntimeState.authState = { value: state, createdAt: Date.now() };
spotifyRuntimeState.codeVerifier = codeVerifier;

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants