205 lines
		
	
	
		
			6.7 KiB
		
	
	
	
		
			TypeScript
		
	
	
	
	
	
			
		
		
	
	
			205 lines
		
	
	
		
			6.7 KiB
		
	
	
	
		
			TypeScript
		
	
	
	
	
	
import AstalBattery from 'gi://AstalBattery';
 | 
						|
import AstalBluetooth from 'gi://AstalBluetooth';
 | 
						|
import AstalNetwork from 'gi://AstalNetwork';
 | 
						|
import AstalWp from 'gi://AstalWp';
 | 
						|
import Brightness from '../../../util/brightness';
 | 
						|
import {
 | 
						|
    Gtk
 | 
						|
} from 'astal/gtk4';
 | 
						|
import QuickActions from '../../QuickActions/QuickActions';
 | 
						|
import {
 | 
						|
    bind
 | 
						|
} from 'astal';
 | 
						|
import {
 | 
						|
    execAsync
 | 
						|
} from 'astal';
 | 
						|
 | 
						|
const STATE = AstalNetwork.DeviceState;
 | 
						|
 | 
						|
const QuickView = () => {
 | 
						|
    const qa = QuickActions.QuickActions();
 | 
						|
 | 
						|
    const showQuickActions = () => {
 | 
						|
        qa.popup();
 | 
						|
    };
 | 
						|
 | 
						|
    return (
 | 
						|
        <button
 | 
						|
            onClicked={() => showQuickActions()}
 | 
						|
            cssClasses={[ 'quick-action-button' ]}
 | 
						|
            child={
 | 
						|
                <box>
 | 
						|
                    <BatteryWidget></BatteryWidget>
 | 
						|
                    <Audio></Audio>
 | 
						|
                    <BluetoothWidget></BluetoothWidget>
 | 
						|
                    <NetworkWidget></NetworkWidget>
 | 
						|
                    <image iconName={'system-shutdown-symbolic'}></image>
 | 
						|
                    {qa}
 | 
						|
                </box>
 | 
						|
            }
 | 
						|
        ></button>
 | 
						|
    );
 | 
						|
};
 | 
						|
 | 
						|
const NetworkWidget = () => {
 | 
						|
    const network = AstalNetwork.get_default();
 | 
						|
 | 
						|
    return (
 | 
						|
        <box>
 | 
						|
            <image
 | 
						|
                iconName={bind( network, 'state' ).as( state => {
 | 
						|
                    if ( state === AstalNetwork.State.CONNECTING ) {
 | 
						|
                        return 'chronometer-reset-symbolic';
 | 
						|
                    } else if (
 | 
						|
                        state === AstalNetwork.State.CONNECTED_LOCAL
 | 
						|
                        || state === AstalNetwork.State.CONNECTED_SITE
 | 
						|
                        || state === AstalNetwork.State.CONNECTED_GLOBAL
 | 
						|
                    ) {
 | 
						|
                        return 'network-wired-activated-symbolic';
 | 
						|
                    } else {
 | 
						|
                        return 'paint-unknown-symbolic';
 | 
						|
                    }
 | 
						|
                } )}
 | 
						|
                cssClasses={[
 | 
						|
                    'network-widget',
 | 
						|
                    'quick-view-symbol'
 | 
						|
                ]}
 | 
						|
                visible={bind( network.wifi, 'state' ).as( state => state !== STATE.ACTIVATED, )}
 | 
						|
            ></image>
 | 
						|
            <image
 | 
						|
                iconName={bind( network.wifi, 'state' ).as( state => {
 | 
						|
                    if ( state === STATE.ACTIVATED ) {
 | 
						|
                        return network.wifi.iconName;
 | 
						|
                    } else {
 | 
						|
                        return '';
 | 
						|
                    }
 | 
						|
                } )}
 | 
						|
                tooltipText={bind( network.wifi, 'ssid' )}
 | 
						|
                cssClasses={[
 | 
						|
                    'network-widget',
 | 
						|
                    'quick-view-symbol'
 | 
						|
                ]}
 | 
						|
                visible={bind( network.wifi, 'state' ).as( state => state === STATE.ACTIVATED, )}
 | 
						|
            ></image>
 | 
						|
        </box>
 | 
						|
    );
 | 
						|
};
 | 
						|
 | 
						|
const BluetoothWidget = () => {
 | 
						|
    const bluetooth = AstalBluetooth.get_default();
 | 
						|
    const enabled = bind( bluetooth, 'isPowered' );
 | 
						|
    const connected = bind( bluetooth, 'isConnected' );
 | 
						|
 | 
						|
    // For each connected BT device, render status
 | 
						|
    return (
 | 
						|
        <box>
 | 
						|
            <box visible={enabled.as( e => e )}>
 | 
						|
                <image
 | 
						|
                    iconName={'bluetooth-active-symbolic'}
 | 
						|
                    visible={connected.as( c => c )}
 | 
						|
                ></image>
 | 
						|
                <image
 | 
						|
                    iconName={'bluetooth-disconnected-symbolic'}
 | 
						|
                    visible={connected.as( c => !c )}
 | 
						|
                ></image>
 | 
						|
            </box>
 | 
						|
            <image
 | 
						|
                iconName={'bluetooth-disabled-symbolic'}
 | 
						|
                visible={enabled.as( e => !e )}
 | 
						|
            ></image>
 | 
						|
            <box>
 | 
						|
                {bind( bluetooth, 'devices' ).as( devices => {
 | 
						|
                    return devices.map( device => {
 | 
						|
                        return (
 | 
						|
                            <image
 | 
						|
                                iconName={bind( device, 'icon' ).as( icon => icon, )}
 | 
						|
                                visible={bind( device, 'connected' )}
 | 
						|
                                tooltipText={bind( device, 'batteryPercentage' ).as( n => {
 | 
						|
                                    return device.get_name() + ': ' + n + '%';
 | 
						|
                                }, )}
 | 
						|
                            ></image>
 | 
						|
                        );
 | 
						|
                    } );
 | 
						|
                } )}
 | 
						|
            </box>
 | 
						|
        </box>
 | 
						|
    );
 | 
						|
};
 | 
						|
 | 
						|
 | 
						|
let hasSentNotification = false;
 | 
						|
 | 
						|
const BatteryWidget = () => {
 | 
						|
    const battery = AstalBattery.get_default();
 | 
						|
 | 
						|
    if ( battery.get_is_present() ) {
 | 
						|
        return (
 | 
						|
            <image
 | 
						|
                iconName={bind( battery, 'batteryIconName' ).as( icon => icon )}
 | 
						|
                cssClasses={[ 'quick-view-symbol' ]}
 | 
						|
                tooltipText={bind( battery, 'percentage' ).as( p => {
 | 
						|
                    const level = Math.round( p * 100 );
 | 
						|
 | 
						|
                    if ( level < 20 && !hasSentNotification ) {
 | 
						|
                        hasSentNotification = true;
 | 
						|
                        execAsync( 'bash -c "notify-send \'Battery level below 20%\'"' );
 | 
						|
                    }
 | 
						|
 | 
						|
                    return `Battery Level: ${ level }%`;
 | 
						|
                } )}
 | 
						|
            ></image>
 | 
						|
        );
 | 
						|
    } else {
 | 
						|
        return <box></box>;
 | 
						|
    }
 | 
						|
    // Else, no battery available -> Don't show the widget
 | 
						|
};
 | 
						|
 | 
						|
const BrightnessWidget = () => {
 | 
						|
    const brightness = Brightness.get_default();
 | 
						|
    const screen_brightness = bind( brightness, 'screen' );
 | 
						|
 | 
						|
    return (
 | 
						|
        <box cssClasses={[ 'quick-view-symbol' ]}>
 | 
						|
            <image iconName={'brightness-high-symbolic'}></image>
 | 
						|
            <label
 | 
						|
                label={screen_brightness.as( b => '' + Math.round( 100 * b ) )}
 | 
						|
                visible={bind( brightness, 'screenAvailable' )}
 | 
						|
            ></label>
 | 
						|
        </box>
 | 
						|
    );
 | 
						|
};
 | 
						|
 | 
						|
const Audio = () => {
 | 
						|
    const wireplumber = AstalWp.get_default();
 | 
						|
 | 
						|
    if ( wireplumber ) {
 | 
						|
        return (
 | 
						|
            <box orientation={Gtk.Orientation.HORIZONTAL}>
 | 
						|
                <image
 | 
						|
                    iconName={bind( wireplumber.defaultSpeaker, 'volumeIcon' ).as( icon => icon, )}
 | 
						|
                    cssClasses={[ 'quick-view-symbol' ]}
 | 
						|
                    tooltipText={bind( wireplumber.defaultSpeaker, 'volume' ).as( v => Math.round( 100 * v ) + '%' )}
 | 
						|
                ></image>
 | 
						|
                <image
 | 
						|
                    iconName={bind( wireplumber.defaultMicrophone,
 | 
						|
                        'volumeIcon', ).as( icon => icon )}
 | 
						|
                    cssClasses={[ 'quick-view-symbol' ]}
 | 
						|
                    tooltipText={bind( wireplumber.defaultMicrophone, 'volume' ).as( v => Math.round( 100 * v ) + '%' )}
 | 
						|
                ></image>
 | 
						|
            </box>
 | 
						|
        );
 | 
						|
    } else {
 | 
						|
        print( '[ WirePlumber ] Could not connect, Audio support in bar will be missing', );
 | 
						|
 | 
						|
        return <image iconName={'action-unavailable-symbolic'}></image>;
 | 
						|
    }
 | 
						|
};
 | 
						|
 | 
						|
// cssClasses={[ 'quick-view-symbol' ]}
 | 
						|
 | 
						|
export default {
 | 
						|
    QuickView,
 | 
						|
    BrightnessWidget
 | 
						|
};
 |