263 lines
8.8 KiB
JavaScript
263 lines
8.8 KiB
JavaScript
const { shell, app, Tray, Menu, powerMonitor, nativeTheme } = require( 'electron' )
|
|
const { enable_battery_limiter, disable_battery_limiter, initialize_battery, is_limiter_enabled, get_battery_status, uninstall_battery } = require( './battery' )
|
|
const { log } = require( "./helpers" )
|
|
const { get_logo_template } = require( './theme' )
|
|
const { get_force_discharge_setting, update_force_discharge_setting } = require( './settings' )
|
|
|
|
/* ///////////////////////////////
|
|
// Menu helpers
|
|
// /////////////////////////////*/
|
|
let tray = undefined
|
|
|
|
|
|
// Set interface to usable
|
|
const generate_app_menu = async () => {
|
|
|
|
try {
|
|
// Get battery and daemon status
|
|
const { battery_state, daemon_state, maintain_percentage=80, percentage } = await get_battery_status()
|
|
|
|
// Check if limiter is on
|
|
const limiter_on = await is_limiter_enabled()
|
|
|
|
// Check force discharge setting
|
|
const allow_discharge = get_force_discharge_setting()
|
|
|
|
// Set tray icon
|
|
log( `Generate app menu percentage: ${ percentage } (discharge ${ allow_discharge ? 'allowed' : 'disallowed' }, limited ${ limiter_on ? 'on' : 'off' })` )
|
|
tray.setImage( get_logo_template( percentage, limiter_on ) )
|
|
|
|
// Build menu
|
|
return Menu.buildFromTemplate( [
|
|
|
|
{
|
|
label: `Enable ${ maintain_percentage }% battery limit`,
|
|
type: 'radio',
|
|
checked: limiter_on,
|
|
click: enable_limiter
|
|
},
|
|
{
|
|
label: `Disable ${ maintain_percentage }% battery limit`,
|
|
type: 'radio',
|
|
checked: !limiter_on,
|
|
click: disable_limiter
|
|
},
|
|
{
|
|
type: 'separator'
|
|
},
|
|
{
|
|
label: `Battery: ${ battery_state }`,
|
|
enabled: false
|
|
},
|
|
{
|
|
label: `Power: ${ daemon_state }`,
|
|
enabled: false
|
|
},
|
|
{
|
|
type: 'separator'
|
|
},
|
|
{
|
|
label: `Advanced settings`,
|
|
submenu: [
|
|
{
|
|
label: `Allow force-discharging`,
|
|
type: 'checkbox',
|
|
checked: allow_discharge,
|
|
click: async () => {
|
|
const success = await update_force_discharge_setting()
|
|
if( limiter_on && success ) await restart_limiter()
|
|
}
|
|
}
|
|
]
|
|
},
|
|
{
|
|
label: `About v${ app.getVersion() }`,
|
|
submenu: [
|
|
{
|
|
label: `Check for updates`,
|
|
click: () => shell.openExternal( `https://github.com/actuallymentor/battery/releases` )
|
|
},
|
|
{
|
|
type: 'normal',
|
|
label: `Uninstall Battery ${ app.getVersion() }`,
|
|
click: async () => {
|
|
const uninstalled = await uninstall_battery()
|
|
if( !uninstalled ) return
|
|
tray.destroy()
|
|
app.quit()
|
|
}
|
|
},
|
|
{
|
|
type: 'separator'
|
|
},
|
|
{
|
|
label: `User manual`,
|
|
click: () => shell.openExternal( `https://github.com/actuallymentor/battery#readme` )
|
|
},
|
|
{
|
|
type: 'normal',
|
|
label: 'Command-line usage',
|
|
click: () => shell.openExternal( `https://github.com/actuallymentor/battery#-command-line-version` )
|
|
},
|
|
{
|
|
type: 'normal',
|
|
label: 'Help and feature requests',
|
|
click: () => shell.openExternal( `https://github.com/actuallymentor/battery/issues` )
|
|
}
|
|
]
|
|
},
|
|
{
|
|
label: 'Quit',
|
|
click: () => {
|
|
tray.destroy()
|
|
app.quit()
|
|
}
|
|
}
|
|
|
|
] )
|
|
} catch ( e ) {
|
|
log( `Error generating menu: `, e )
|
|
}
|
|
|
|
}
|
|
|
|
// Periodic refreshing of icon and state
|
|
let refresh_timer = undefined
|
|
const set_interface_update_timer = async ( disable_only=false ) => {
|
|
|
|
if( !disable_only ) log( `Refreshing interface update timer` )
|
|
else log( `Disabling interface update timer due to disable_only set to `, disable_only )
|
|
|
|
// Calculate update speed
|
|
const { maintain_percentage=80, percentage, charging } = await get_battery_status()
|
|
const percentage_delta = Math.floor( Math.abs( percentage - maintain_percentage ) )
|
|
const slow_refresh_interval_in_ms = 1000 * 60 * 10
|
|
const fast_refresh_interval_in_ms = 1000 * 60 * .5
|
|
const battery_full_and_charging = charging && percentage == 100
|
|
const refresh_speed = percentage_delta < 5 || powerMonitor.onBatteryPower || battery_full_and_charging ? slow_refresh_interval_in_ms : fast_refresh_interval_in_ms
|
|
log( `Setting interface refresh speed to ${ refresh_speed / 1000 / 60 } minutes` )
|
|
if( refresh_timer ) clearInterval( refresh_timer )
|
|
// eslint-disable-next-line no-use-before-define
|
|
if( !disable_only ) refresh_timer = setInterval( refresh_tray, refresh_speed )
|
|
|
|
}
|
|
|
|
// Refresh tray with battery status values
|
|
const refresh_tray = async ( force_interactive_refresh = false ) => {
|
|
|
|
log( "Refreshing tray icon..." )
|
|
const new_menu = await generate_app_menu()
|
|
if( force_interactive_refresh ) {
|
|
log( `Forcing interactive refresh ${ force_interactive_refresh }` )
|
|
tray.closeContextMenu()
|
|
tray.popUpContextMenu( new_menu )
|
|
}
|
|
tray.setContextMenu( new_menu )
|
|
|
|
// Refresh timer
|
|
log( `Resetting interface timer speed` )
|
|
set_interface_update_timer()
|
|
|
|
}
|
|
|
|
// Refresh app logo
|
|
const refresh_logo = async ( percent=80, force ) => {
|
|
|
|
log( `Refresh logo for percentage ${ percent }, force ${ force }` )
|
|
if( force == 'active' ) return tray.setImage( get_logo_template( percent, true ) )
|
|
if( force == 'inactive' ) return tray.setImage( get_logo_template( percent, false ) )
|
|
|
|
const is_enabled = await is_limiter_enabled()
|
|
return tray.setImage( get_logo_template( percent, is_enabled ) )
|
|
}
|
|
|
|
|
|
/* ///////////////////////////////
|
|
// Initialisation
|
|
// /////////////////////////////*/
|
|
async function set_initial_interface() {
|
|
|
|
log( "Starting tray app" )
|
|
tray = new Tray( get_logo_template( 100, true ) )
|
|
|
|
// Set "loading" context
|
|
tray.setTitle( ' updating...' )
|
|
|
|
log( "Tray app boot complete" )
|
|
|
|
log( "Triggering boot-time auto-update" )
|
|
await initialize_battery()
|
|
log( "App initialisation process complete" )
|
|
|
|
// Start battery handler
|
|
await enable_battery_limiter()
|
|
|
|
// Set tray styles
|
|
tray.setTitle( '' )
|
|
await refresh_tray()
|
|
|
|
// Set tray open listener
|
|
tray.on( 'mouse-enter', () => refresh_tray() )
|
|
tray.on( 'click', () => refresh_tray() )
|
|
nativeTheme.on( 'updated', () => refresh_tray() )
|
|
|
|
// Set refresh timer for the battery icon
|
|
set_interface_update_timer()
|
|
powerMonitor.on( 'lock-screen', () => set_interface_update_timer( true ) )
|
|
powerMonitor.on( 'unlock-screen', () => set_interface_update_timer() )
|
|
powerMonitor.on( 'suspend', () => set_interface_update_timer( true ) )
|
|
powerMonitor.on( 'resume', () => set_interface_update_timer() )
|
|
|
|
}
|
|
|
|
/* ///////////////////////////////
|
|
// User interactions
|
|
// /////////////////////////////*/
|
|
async function enable_limiter() {
|
|
|
|
try {
|
|
log( 'Enable limiter' )
|
|
await refresh_logo( 80, 'active' )
|
|
const percent_left = await enable_battery_limiter()
|
|
log( `Interface enabled limiter, percentage remaining: ${ percent_left }` )
|
|
await refresh_logo( percent_left, 'active' )
|
|
await refresh_tray()
|
|
} catch ( e ) {
|
|
log( `Error in enable_limiter: `, e )
|
|
}
|
|
|
|
}
|
|
|
|
async function disable_limiter() {
|
|
|
|
try {
|
|
log( 'Disable limiter' )
|
|
await refresh_logo( 80, 'inactive' )
|
|
const percent_left = await disable_battery_limiter()
|
|
log( `Interface enabled limiter, percentage remaining: ${ percent_left }` )
|
|
await refresh_logo( percent_left, 'inactive' )
|
|
await refresh_tray()
|
|
} catch ( e ) {
|
|
log( `Error in disable_limiter: `, e )
|
|
}
|
|
|
|
}
|
|
|
|
async function restart_limiter() {
|
|
|
|
try {
|
|
log( 'Restart limiter' )
|
|
const percent_left = await disable_battery_limiter()
|
|
await enable_battery_limiter()
|
|
await refresh_logo( percent_left, 'active' )
|
|
await refresh_tray()
|
|
} catch ( e ) {
|
|
log( `Error in restart_limiter: `, e )
|
|
}
|
|
|
|
}
|
|
|
|
|
|
module.exports = {
|
|
set_initial_interface
|
|
} |