Version 0.9.1-2: Fix npm installation and pause button behavior

Critical Fixes:
- FIXED: npm installation verification added
  * Now explicitly checks if npm is installed after nodejs
  * Falls back to installing npm separately if missing
  * Displays npm version after installation
  * Prevents "npm: command not found" error during Electron install

- FIXED: Pause button now appears only on user interaction
  * Hidden by default (display:none)
  * Shows on mousedown/touchstart/keydown events
  * Similar behavior to keyboard icon
  * Throttled to check every 5 seconds
  * Better UX - less visual clutter

- FIXED: Pause button hidden on manual sites (duration=0)
  * Main process checks site duration when visibility requested
  * Sends pause-button-visibility message to views
  * attachView() function controls visibility on tab switch
  * Prevents confusion on sites where return-to-home popup appears

Implementation:
- Added 'request-pause-button-visibility' IPC message
- Main process responds with 'pause-button-visibility' based on duration
- Pause button automatically hidden/shown when switching tabs
- User interaction triggers visibility check
This commit is contained in:
Claude
2025-11-18 16:29:35 +00:00
parent 7e1809faa6
commit f65e99c8fb
+77 -5
View File
@@ -3280,7 +3280,15 @@ first_time_install() {
curl -fsSL https://deb.nodesource.com/setup_20.x | sudo -E bash - curl -fsSL https://deb.nodesource.com/setup_20.x | sudo -E bash -
sudo apt install -y nodejs sudo apt install -y nodejs
fi fi
# Verify npm is installed
if ! command -v npm &>/dev/null; then
echo "⚠ npm not found, attempting to install..."
sudo apt install -y npm
fi
echo "Node.js: $(node -v)" echo "Node.js: $(node -v)"
echo "npm: $(npm -v)"
echo "[7-10/27] Core configuration..." echo "[7-10/27] Core configuration..."
configure_touch_controls configure_touch_controls
@@ -3723,6 +3731,11 @@ function attachView(i){
programmaticNavigation=true; programmaticNavigation=true;
views[i].webContents.loadURL(configuredUrl); views[i].webContents.loadURL(configuredUrl);
} }
// Control pause button visibility based on site duration
const siteDuration=parseInt(tabs[tabIdx].duration)||0;
const shouldShow=siteDuration!==0; // Hide on manual sites (duration=0)
views[i].webContents.send('pause-button-visibility',shouldShow);
} }
views[i].webContents.focus(); views[i].webContents.focus();
@@ -4220,6 +4233,27 @@ function createWindow(){
ipcMain.on('keyboard-activity',()=>{markKeyboardActivity();}); ipcMain.on('keyboard-activity',()=>{markKeyboardActivity();});
ipcMain.on('show-pause-dialog',()=>{showPauseDialog();}); ipcMain.on('show-pause-dialog',()=>{showPauseDialog();});
// Handle pause button visibility request
ipcMain.on('request-pause-button-visibility',()=>{
const currentTabIdx=viewIndexToTabIndex(currentIndex);
let shouldShow=true;
if(currentTabIdx>=0&&tabs[currentTabIdx]){
const siteDuration=parseInt(tabs[currentTabIdx].duration)||0;
// Hide pause button on manual sites (duration=0)
if(siteDuration===0){
shouldShow=false;
}
}
// Send visibility state to all views
views.forEach(v=>{
if(v&&v.webContents){
v.webContents.send('pause-button-visibility',shouldShow);
}
});
});
ipcMain.on('keyboard-type',(event,key)=>{ ipcMain.on('keyboard-type',(event,key)=>{
markKeyboardActivity(); markKeyboardActivity();
@@ -5125,6 +5159,7 @@ window.addEventListener('DOMContentLoaded',()=>{
// Pause button functionality // Pause button functionality
let pauseButton=null; let pauseButton=null;
let pauseButtonVisible=false;
function createPauseButton(){ function createPauseButton(){
if(pauseButton)return; if(pauseButton)return;
@@ -5136,7 +5171,7 @@ window.addEventListener('DOMContentLoaded',()=>{
pauseButton.style.cssText=` pauseButton.style.cssText=`
position:fixed;bottom:20px;left:20px;width:60px;height:60px; position:fixed;bottom:20px;left:20px;width:60px;height:60px;
background:rgba(230,126,34,0.95);border:3px solid rgba(255,255,255,0.9); background:rgba(230,126,34,0.95);border:3px solid rgba(255,255,255,0.9);
border-radius:50%;display:flex;align-items:center;justify-content:center; border-radius:50%;display:none;align-items:center;justify-content:center;
font-size:32px;cursor:pointer;z-index:999999; font-size:32px;cursor:pointer;z-index:999999;
box-shadow:0 4px 12px rgba(0,0,0,0.4);user-select:none; box-shadow:0 4px 12px rgba(0,0,0,0.4);user-select:none;
`; `;
@@ -5150,10 +5185,47 @@ window.addEventListener('DOMContentLoaded',()=>{
document.body.appendChild(pauseButton); document.body.appendChild(pauseButton);
} }
// Create pause button on page load function showPauseButton(){
setTimeout(()=>{ if(!pauseButton)createPauseButton();
createPauseButton(); pauseButton.style.display='flex';
},1000); pauseButtonVisible=true;
}
function hidePauseButton(){
if(pauseButton){
pauseButton.style.display='none';
pauseButtonVisible=false;
}
}
// Listen for pause button visibility control from main process
ipcRenderer.on('pause-button-visibility',(event,visible)=>{
if(visible){
showPauseButton();
}else{
hidePauseButton();
}
});
// Show pause button on user interaction (but not on manual sites)
let lastPauseButtonCheck=0;
const PAUSE_BUTTON_THROTTLE=5000;
function checkAndShowPauseButton(){
const now=Date.now();
if(now-lastPauseButtonCheck>PAUSE_BUTTON_THROTTLE){
lastPauseButtonCheck=now;
ipcRenderer.send('request-pause-button-visibility');
}
}
// Show pause button on any user interaction
const pauseButtonTriggers=['mousedown','touchstart','keydown'];
pauseButtonTriggers.forEach(eventType=>{
document.addEventListener(eventType,()=>{
checkAndShowPauseButton();
},{passive:true,capture:true});
});
function isTextInput(el){ function isTextInput(el){
if(!el)return false; if(!el)return false;