import GObject from 'gi://GObject'; import St from 'gi://St'; import Gio from 'gi://Gio'; import GLib from 'gi://GLib'; import Clutter from 'gi://Clutter'; import * as Main from 'resource:///org/gnome/shell/ui/main.js'; import * as PanelMenu from 'resource:///org/gnome/shell/ui/panelMenu.js'; const DESKMETER_API_URL = 'http://localhost:10000/api/current_task'; const UPDATE_INTERVAL = 3000; // 3 seconds const TaskIndicator = GObject.registerClass( class TaskIndicator extends PanelMenu.Button { _init() { super._init(0.0, 'Deskmeter Task Indicator', false); // Create label for task display this._label = new St.Label({ text: 'loading...', y_align: Clutter.ActorAlign.CENTER, style_class: 'deskmeter-task-label' }); this.add_child(this._label); // Start periodic updates this._updateTask(); this._timeout = GLib.timeout_add(GLib.PRIORITY_DEFAULT, UPDATE_INTERVAL, () => { this._updateTask(); return GLib.SOURCE_CONTINUE; }); } _updateTask() { try { // Create HTTP request let file = Gio.File.new_for_uri(DESKMETER_API_URL); file.load_contents_async(null, (source, result) => { try { let [success, contents] = source.load_contents_finish(result); if (success) { let decoder = new TextDecoder('utf-8'); let data = JSON.parse(decoder.decode(contents)); // Update label with task path let displayText = data.task_path || 'no task'; // Optionally truncate long paths if (displayText.length > 40) { let parts = displayText.split('/'); if (parts.length > 2) { displayText = '.../' + parts.slice(-2).join('/'); } else { displayText = displayText.substring(0, 37) + '...'; } } this._label.set_text(displayText); } } catch (e) { this._label.set_text('error'); logError(e, 'Failed to parse deskmeter response'); } }); } catch (e) { this._label.set_text('offline'); logError(e, 'Failed to fetch deskmeter task'); } } destroy() { if (this._timeout) { GLib.source_remove(this._timeout); this._timeout = null; } super.destroy(); } }); export default class Extension { constructor() { this._indicator = null; } enable() { this._indicator = new TaskIndicator(); // Add to panel - position after workspace indicator // Panel boxes: left, center, right // We'll add it to the left panel, after other items Main.panel.addToStatusArea('deskmeter-task-indicator', this._indicator, 1, 'left'); } disable() { if (this._indicator) { this._indicator.destroy(); this._indicator = null; } } }