Timer, stopwatch, Pomodoro and time stats in your top bar. Countdown and Pomodoro modes, a stopwatch with laps, tasks and projects, searchable history, weekly to yearly stats, and fifteen clock styles that follow your light/dark appearance and accent color.
Note: Binary files aren't shown on the web site. To see all files, please download the extension zipfile.
EGO-L-002 warning
objects created by extension should be destroyed in disable()
Objects assigned in `enable()` are missing matching `.destroy()` calls in `disable()` or its helper methods.
extension.js:722
this._historySearch = new St.Entry({hint_text:'Search timer and stopwatch history…', text:this._historyQuery ?? '', style_class:'history-search', can_focus:true, x_expand:true})
extension.js:118
this._icon = new St.Icon({...(brand ? {gicon: brand} : {icon_name: 'alarm-symbolic'}), icon_size: 18, style_class: 'system-status-icon'})
extension.js:438
this._lapButton = new St.Button({child: lapContent, style_class: 'timer-control panelmate-action', can_focus: true, reactive: true, track_hover: true})
extension.js:420
this._play = new St.Button({child: this._playIcon, style_class: 'timer-play panelmate-action', can_focus: true, reactive: true, track_hover: true})
extension.js:419
this._playIcon = new St.Icon({icon_name: 'media-playback-start-symbolic', icon_size: 18})
extension.js:775
this._renameEditor = editor
EGO-L-003 warning
signals connected by extension should be disconnected in disable()
Signals assigned in `enable()` are missing matching disconnect calls in `disable()` or its helper methods.
extension.js:725
this._historySearch.clutter_text.connect('text-changed',()=>{this._historyQuery=this._historySearch.get_text();this._renderHistoryList();})
extension.js:343
this._indicator.menu.connect('open-state-changed', (_menu, open) => {
if (!open) this._finishRename?.();
})
extension.js:441
this._lapButton.connect('clicked', () => { if (this._state.lap()) { this._save(); this._update(); } })
extension.js:346
this._panel.connect('captured-event', (_actor, event) => {
if (this._handlePanelKey(event) === Clutter.EVENT_STOP) return Clutter.EVENT_STOP;
if (this._renameEditor && event.type() === Clutter.EventType.BUTTON_PRESS) {
const [x, y] = event.get_coords()
extension.js:422
this._play.connect('clicked', () => this._playPause())
extension.js:397
this._resetButton.connect('clicked', () => this._reset())
extension.js:730
this._undoButton.connect('clicked',()=>this._undoDelete())
extension.js:561
entry.clutter_text.connect('activate', () => { this._save(); this._play?.grab_key_focus(); })
extension.js:588
entry.clutter_text.connect('activate', () => { if (entry.get_text().trim()) choose(entry.get_text()); })
extension.js:782
editor.clutter_text.connect('activate', () => finish())
extension.js:69
actor.connect('button-press-event', hide)
extension.js:71
actor.connect('destroy', hide)
extension.js:67
actor.connect('key-focus-in', show)
extension.js:68
actor.connect('key-focus-out', hide)
extension.js:66
actor.connect('notify::hover', () => actor.hover ? show() : hide())
extension.js:70
actor.connect('notify::mapped', () => { if (!actor.mapped) hide(); })
extension.js:394
appearance.connect('clicked', () => { this._buildAppearancePage(); this._styleButtons.find(([style]) => style === this._style)?.[1].grab_key_focus(); })
extension.js:428
control.connect('clicked', () => { this._adjustTime(delta); })
extension.js:829
control.connect('clicked',()=>this._buildProjectPage(page))
extension.js:657
done.connect('clicked', () => { this._buildClockPage(); this._appearanceButton?.grab_key_focus(); })
extension.js:844
done.connect('clicked',back)
extension.js:535
info.connect('clicked', () => { this._indicator.menu.close(); this.openPreferences(); })
extension.js:601
item.connect('clicked', () => choose(project))
extension.js:855
item.connect('clicked',()=>{this._projectFilter=project;this._openPage(returnPage);})
extension.js:562
entry.clutter_text.connect('key-focus-out', () => this._save())
extension.js:781
editor.clutter_text.connect('key-focus-out', () => finish())
extension.js:783
editor.clutter_text.connect('key-press-event', (_text, event) => {
if (event.get_key_symbol() === Clutter.KEY_Escape) { finish(true); return Clutter.EVENT_STOP; }
return Clutter.EVENT_PROPAGATE;
})
extension.js:788
name.connect('clicked', () => {
const now = GLib.get_monotonic_time() / 1000;
const interval = Clutter.Settings.get_default().double_click_time;
if (lastClick && now - lastClick <= interval) { lastClick = 0; rename(); }
else
extension.js:794
name.connect('key-press-event', (_actor, event) => {
if (event.get_key_symbol() === Clutter.KEY_F2) { rename(); return Clutter.EVENT_STOP; }
return Clutter.EVENT_PROPAGATE;
})
extension.js:244
option.connect('clicked',()=>{this._statisticsPeriod=period;this._buildStatisticsPage();this._periodButton?.grab_key_focus();})
extension.js:480
option.connect('clicked', () => {
option.checked = selected;
if (!selected) this._switchTimerMode(enable);
})
extension.js:391
preferences.connect('clicked', () => { this._indicator.menu.close(); this.openPreferences(); })
extension.js:456
preset.connect('clicked', () => {
this._selectPreset(minutes);
this._play?.grab_key_focus();
})
extension.js:624
remove.connect('clicked', () => {
// The first click asks for confirmation inside the row; the second deletes.
if (!armed) {
armed = true;
remove.set_child(new St.Label({text: 'Delete', y_align: Clutter.ActorAlign.CENTER}));
extension.js:814
remove.connect('clicked', () => this._deleteRecord(entry))
extension.js:818
repeat.connect('clicked',()=>this._prepareTimer(entry.durationMs,{task:entry.name,project:entry.project},false,entry.pomodoro ?? (entry.phase ? {enabled:true,phase:entry.phase,round:1} : null)))
extension.js:805
reveal.connect('clicked', () => {
lapList.visible = !lapList.visible;
reveal.set_label(`${entry.laps.length} laps ${lapList.visible ? '▴' : '▾'}`);
reveal.accessible_name = `${entry.laps.length} laps, ${lapList.visible ? 'ex
extension.js:538
skip.connect('clicked', () => { this._skipPhase(); this._play?.grab_key_focus(); })
extension.js:1031
source.connect('destroy', () => { this._notificationSource = null; })
extension.js:184
tab.connect('clicked', () => { this._openPage(id); this._tabs.get(id)?.grab_key_focus(); })
extension.js:185
tab.connect('key-press-event', (_actor, event) => {
const ids = ['timer', 'stopwatch', 'history', 'statistics'];
const key = event.get_key_symbol();
let next = ids.indexOf(id);
if (key === Clutter.KEY_Right) next = (next + 1
extension.js:557
entry.clutter_text.connect('text-changed', () => {
this._state.details[mode].task = entry.get_text().trim().slice(0, 80);
syncClear();
})
extension.js:128
this._systemSettings.connect(`changed::${key}`, () => {
this._refreshSystemTheme();
})
| Version | Status |
|---|---|
| 1.0 (1) | Unreviewed |