On the Recent Changes to App Distribution Requirements in the Android System by Google.
-Adrian Victor - 8/29/2025
+Adrian Victor - 8/29/2025 (last edited in 4/23/2026)
Also available in other languages: diff --git a/posts/instalando-fl-studio-no-linux/index.html b/posts/instalando-fl-studio-no-linux/index.html index 19577ad..437cd30 100644 --- a/posts/instalando-fl-studio-no-linux/index.html +++ b/posts/instalando-fl-studio-no-linux/index.html @@ -54,7 +54,10 @@ by: "por", options: "Opções", hideBackground: "Esconder imagem de fundo", - back: "voltar" + back: "voltar", + permissionIssue: "Problema de permissão", + permissionIssueNotificationContent: "Não foi possivel continuar tocando a música de fundo, por favor habilite reprodução automática de áudio para esse website.", + notificationDefaultHint: "Clique para ignorar", }Instalando FL Studio no Linux.
-Adrian Victor - 4/19/2026
+Adrian Victor - 4/19/2026 (editado por último em 4/23/2026)
Também disponível em outros idiomas: diff --git a/posts/installing-fl-studio-on-linux/index.html b/posts/installing-fl-studio-on-linux/index.html index dd83814..950c57f 100644 --- a/posts/installing-fl-studio-on-linux/index.html +++ b/posts/installing-fl-studio-on-linux/index.html @@ -54,7 +54,10 @@ by: "by", options: "Options", hideBackground: "Hide background", - back: "back" + back: "back", + permissionIssue: "Permission issue", + permissionIssueNotificationContent: "Unable to continue playing background music, please enable audio autoplay for this website.", + notificationDefaultHint: "Click to dismiss", }Installing FL Studio on linux.
-Adrian Victor - 4/19/2026
+Adrian Victor - 4/19/2026 (last edited in 4/23/2026)
Also available in other languages: diff --git a/posts/verificacao-de-desenvolvedor-no-android/index.html b/posts/verificacao-de-desenvolvedor-no-android/index.html index 2c0d2de..9875489 100644 --- a/posts/verificacao-de-desenvolvedor-no-android/index.html +++ b/posts/verificacao-de-desenvolvedor-no-android/index.html @@ -54,7 +54,10 @@ by: "por", options: "Opções", hideBackground: "Esconder imagem de fundo", - back: "voltar" + back: "voltar", + permissionIssue: "Problema de permissão", + permissionIssueNotificationContent: "Não foi possivel continuar tocando a música de fundo, por favor habilite reprodução automática de áudio para esse website.", + notificationDefaultHint: "Clique para ignorar", }Sobre as recentes mudanças nos requisitos de distribuição de apps no sistema Android feitas pela Google.
-Adrian Victor - 8/29/2025
+Adrian Victor - 8/29/2025 (editado por último em 4/23/2026)
Também disponível em outros idiomas: diff --git a/pt/blog/index.html b/pt/blog/index.html index 43f958f..41dbc34 100644 --- a/pt/blog/index.html +++ b/pt/blog/index.html @@ -54,7 +54,10 @@ by: "por", options: "Opções", hideBackground: "Esconder imagem de fundo", - back: "voltar" + back: "voltar", + permissionIssue: "Problema de permissão", + permissionIssueNotificationContent: "Não foi possivel continuar tocando a música de fundo, por favor habilite reprodução automática de áudio para esse website.", + notificationDefaultHint: "Clique para ignorar", }Guia para novatos no IFC.
-Adrian Victor - 1/12/2026
+Adrian Victor - 1/12/2026 (editado por último em )
Telnet
-Adrian Victor & Arthur Borges - 8/26/2025
+Adrian Victor & Arthur Borges - 8/26/2025 (last edited in )
Telnet
-Adrian Victor & Arthur Borges - 8/26/2025
+Adrian Victor & Arthur Borges - 8/26/2025 (editado por último em )
Volume
- +${headeri18n.hideBackground}
@@ -54,6 +55,9 @@ optionsAside.classList.add("metromenu"); } body.appendChild(optionsAside); +document.getElementById("volume").addEventListener("input", (e) => { + setVolume(e.target.value / 100); +}); // dirty workaround to replace inline function calling in the volume input const toggleIMG = document.querySelector('#sound'); toggleIMG.addEventListener('click', () => { @@ -146,11 +150,21 @@ let audio = new Audio(`/static/music/${audioSelect.value}`); const savedTime = localStorage.getItem("audioTime"); const savedVolume = localStorage.getItem("volume"); + +if (savedVolume !== null) { + audio.volume = parseFloat(savedVolume); +} else { + audio.volume = 0.8; +} + const wasPlaying = localStorage.getItem("audioPlaying") === 'true'; function play() { - audio.volume = localStorage.getItem("volume"); - audio.play(); + audio.volume = localStorage.getItem("volume") ?? 0.8; + audio.play().catch(() => { + stop(); + showNotification(headeri18n.permissionIssue, headeri18n.permissionIssueNotificationContent, 5000); + });; localStorage.setItem("audioPlaying", "true") toggleIMG.src = "/static/images/sound-on.png" console.log(`[Music Player] playing ${audioSelect.value}`) diff --git a/static/scripts/notification.js b/static/scripts/notification.js new file mode 100644 index 0000000..a05b793 --- /dev/null +++ b/static/scripts/notification.js @@ -0,0 +1,45 @@ +import { registerElementHint } from "./tips.js"; + +const notificationBox = document.createElement('div'); +notificationBox.classList.add('notificationBox'); + +export async function showNotification(title, subtitle, time, hint) { + if (!hint) { + hint = headeri18n.notificationDefaultHint; + } + const notificationBox = document.createElement('div'); + notificationBox.classList.add('notificationBox'); + notificationBox.dataset.tip = hint; + + const notificationTitle = document.createElement('h1'); + notificationTitle.innerHTML = title; + + const notificationSubtitle = document.createElement('p'); + notificationSubtitle.innerHTML = subtitle; + + notificationBox.appendChild(notificationTitle); + notificationBox.appendChild(notificationSubtitle); + document.querySelector('body').appendChild(notificationBox); + + registerElementHint(notificationBox); + + let clicked = false; + + notificationBox.addEventListener('click', () => { + hideNotification(notificationBox); + }) + + requestAnimationFrame(() => { + notificationBox.classList.add('shown'); + }); + await new Promise(r => setTimeout(r, time)); + if (!clicked) { + hideNotification(notificationBox); + } +} + +async function hideNotification(notificationBox) { + notificationBox.classList.remove('shown'); + await new Promise(r => setTimeout(r, 1000)); + notificationBox.remove(); +} \ No newline at end of file diff --git a/static/scripts/tips.js b/static/scripts/tips.js index 8100cd6..acc69be 100644 --- a/static/scripts/tips.js +++ b/static/scripts/tips.js @@ -1,8 +1,4 @@ const isMobile = /Android|webOS|iPhone|iPad|iPod|BlackBerry|IEMobile|Opera Mini/i.test(navigator.userAgent); -if (isMobile) { - return; -} - const body = document.querySelector('body'); const elements = document.querySelectorAll('[data-tip]'); const hint = document.querySelector("#headerSubtitle"); @@ -10,36 +6,11 @@ const hintPanelDefaultText = hint.innerHTML; let fixedHint; let currentObserver; -elements.forEach(el => { - el.addEventListener('mouseenter', function() { - cleanup(); - - if (currentObserver) { - currentObserver.disconnect(); - } - - currentObserver = new IntersectionObserver((entries) => { - entries.forEach(entry => { - if (!entry.isIntersecting) { - fixedHint = document.createElement('p'); - fixedHint.id = "fixedHint"; - fixedHint.innerHTML = el.dataset.tip; - fixedHint.setAttribute('aria-hidden', 'true'); - body.appendChild(fixedHint); - } else { - hint.innerHTML = el.dataset.tip; - } - }) - }); - - hint.innerHTML = el.dataset.tip; - currentObserver.observe(hint); - }); - - el.addEventListener('mouseleave', function() { - cleanup(); - }); -}) +if (!isMobile) { + elements.forEach(el => { + registerElementHint(el); + }) +} function cleanup() { hint.innerHTML = hintPanelDefaultText; @@ -52,3 +23,34 @@ function cleanup() { currentObserver = null; } } + +export function registerElementHint(el) { + el.addEventListener('mouseenter', function() { + cleanup(); + + if (currentObserver) { + currentObserver.disconnect(); + } + + currentObserver = new IntersectionObserver((entries) => { + entries.forEach(entry => { + if (!entry.isIntersecting) { + fixedHint = document.createElement('p'); + fixedHint.id = "fixedHint"; + fixedHint.innerHTML = el.dataset.tip; + fixedHint.setAttribute('aria-hidden', 'true'); + body.appendChild(fixedHint); + } else { + hint.innerHTML = el.dataset.tip; + } + }) + }); + + hint.innerHTML = el.dataset.tip; + currentObserver.observe(hint); + }); + + el.addEventListener('mouseleave', function() { + cleanup(); + }); +} \ No newline at end of file