mirror of
https://github.com/morgan9e/linux-sys-telemetry
synced 2026-04-14 00:04:07 +09:00
Fix
This commit is contained in:
89
org.batteryd/battery-viewer
Normal file → Executable file
89
org.batteryd/battery-viewer
Normal file → Executable file
@@ -167,7 +167,7 @@ class BatteryChart(Gtk.DrawingArea):
|
|||||||
t_span = t_max - t_min
|
t_span = t_max - t_min
|
||||||
|
|
||||||
energies = [s[2] for s in self.samples]
|
energies = [s[2] for s in self.samples]
|
||||||
e_min = min(energies)
|
e_min = 0
|
||||||
e_max = max(energies)
|
e_max = max(energies)
|
||||||
if e_max <= e_min:
|
if e_max <= e_min:
|
||||||
e_max = e_min + 1
|
e_max = e_min + 1
|
||||||
@@ -395,6 +395,7 @@ class SessionRow(Adw.ActionRow):
|
|||||||
t_start = datetime.fromtimestamp(start_ts).strftime('%H:%M')
|
t_start = datetime.fromtimestamp(start_ts).strftime('%H:%M')
|
||||||
t_end = datetime.fromtimestamp(end_ts).strftime('%H:%M')
|
t_end = datetime.fromtimestamp(end_ts).strftime('%H:%M')
|
||||||
duration = end_ts - start_ts
|
duration = end_ts - start_ts
|
||||||
|
hours = duration / 3600
|
||||||
|
|
||||||
if status == 'Discharging':
|
if status == 'Discharging':
|
||||||
icon = 'battery-level-50-symbolic'
|
icon = 'battery-level-50-symbolic'
|
||||||
@@ -406,15 +407,66 @@ class SessionRow(Adw.ActionRow):
|
|||||||
icon = 'battery-level-100-symbolic'
|
icon = 'battery-level-100-symbolic'
|
||||||
arrow = '→'
|
arrow = '→'
|
||||||
|
|
||||||
|
subtitle = f'{t_start} – {t_end} · {format_duration(duration)}'
|
||||||
|
if hours > 0 and status in ('Discharging', 'Charging'):
|
||||||
|
rate = abs(end_level - start_level) / hours
|
||||||
|
subtitle += f' · {rate:.1f}%/hr'
|
||||||
|
|
||||||
self.set_title(status)
|
self.set_title(status)
|
||||||
self.set_subtitle(f'{t_start} – {t_end} · {format_duration(duration)}')
|
self.set_subtitle(subtitle)
|
||||||
|
|
||||||
img = Gtk.Image.new_from_icon_name(icon)
|
img = Gtk.Image.new_from_icon_name(icon)
|
||||||
img.set_pixel_size(24)
|
img.set_pixel_size(24)
|
||||||
self.add_prefix(img)
|
self.add_prefix(img)
|
||||||
|
|
||||||
label = Gtk.Label()
|
label = Gtk.Label()
|
||||||
label.set_markup(f'{start_level:.0f}% {arrow} {end_level:.0f}%')
|
delta = end_level - start_level
|
||||||
|
if status == 'Discharging':
|
||||||
|
label.set_markup(f'−{abs(delta):.0f}%')
|
||||||
|
elif status == 'Charging':
|
||||||
|
label.set_markup(f'+{abs(delta):.0f}%')
|
||||||
|
else:
|
||||||
|
label.set_markup(f'{abs(delta):.0f}%')
|
||||||
|
label.add_css_class('caption')
|
||||||
|
label.set_valign(Gtk.Align.CENTER)
|
||||||
|
self.add_suffix(label)
|
||||||
|
|
||||||
|
|
||||||
|
class GapRow(Adw.ActionRow):
|
||||||
|
"""Inferred gap between sessions (suspend/shutdown)."""
|
||||||
|
|
||||||
|
def __init__(self, prev_end_ts, prev_end_level, next_start_ts, next_start_level):
|
||||||
|
super().__init__()
|
||||||
|
|
||||||
|
t_start = datetime.fromtimestamp(prev_end_ts).strftime('%H:%M')
|
||||||
|
t_end = datetime.fromtimestamp(next_start_ts).strftime('%H:%M')
|
||||||
|
duration = next_start_ts - prev_end_ts
|
||||||
|
delta = next_start_level - prev_end_level
|
||||||
|
|
||||||
|
if abs(delta) < 0.5:
|
||||||
|
kind = 'Shutdown / Hibernate'
|
||||||
|
icon = 'system-shutdown-symbolic'
|
||||||
|
elif delta > 0:
|
||||||
|
kind = 'Suspended (charged)'
|
||||||
|
icon = 'battery-level-50-charging-symbolic'
|
||||||
|
else:
|
||||||
|
kind = 'Suspended'
|
||||||
|
icon = 'media-playback-pause-symbolic'
|
||||||
|
|
||||||
|
self.set_title(kind)
|
||||||
|
self.set_subtitle(f'{t_start} – {t_end} · {format_duration(duration)}')
|
||||||
|
self.add_css_class('dim-label')
|
||||||
|
|
||||||
|
img = Gtk.Image.new_from_icon_name(icon)
|
||||||
|
img.set_pixel_size(24)
|
||||||
|
self.add_prefix(img)
|
||||||
|
|
||||||
|
if abs(delta) >= 0.5:
|
||||||
|
label = Gtk.Label()
|
||||||
|
if delta > 0:
|
||||||
|
label.set_markup(f'+{abs(delta):.0f}%')
|
||||||
|
else:
|
||||||
|
label.set_markup(f'−{abs(delta):.0f}%')
|
||||||
label.add_css_class('caption')
|
label.add_css_class('caption')
|
||||||
label.set_valign(Gtk.Align.CENTER)
|
label.set_valign(Gtk.Align.CENTER)
|
||||||
self.add_suffix(label)
|
self.add_suffix(label)
|
||||||
@@ -572,14 +624,41 @@ class BatteryWindow(Adw.ApplicationWindow):
|
|||||||
self.session_group.set_margin_top(16)
|
self.session_group.set_margin_top(16)
|
||||||
self.content.append(self.session_group)
|
self.content.append(self.session_group)
|
||||||
|
|
||||||
|
# merge adjacent sessions with same status and small gaps
|
||||||
|
MERGE_GAP = 180 # 3 minutes — merge if same status and gap < this
|
||||||
|
GAP_THRESHOLD = 180 # show gap row if gap >= this between different statuses
|
||||||
|
|
||||||
|
merged = []
|
||||||
for s in sessions:
|
for s in sessions:
|
||||||
start_ts, end_ts, start_lvl, end_lvl, status = s
|
start_ts, end_ts, start_lvl, end_lvl, status = s
|
||||||
if end_ts - start_ts < 30:
|
if merged:
|
||||||
|
p_start, p_end, p_slvl, p_elvl, p_status = merged[-1]
|
||||||
|
gap = start_ts - p_end
|
||||||
|
if p_status == status and gap < MERGE_GAP:
|
||||||
|
# extend previous session
|
||||||
|
merged[-1] = (p_start, end_ts, p_slvl, end_lvl, status)
|
||||||
continue
|
continue
|
||||||
|
merged.append(s)
|
||||||
|
|
||||||
|
prev = None
|
||||||
|
for s in merged:
|
||||||
|
start_ts, end_ts, start_lvl, end_lvl, status = s
|
||||||
|
if end_ts - start_ts < 30:
|
||||||
|
prev = s
|
||||||
|
continue
|
||||||
|
|
||||||
|
if prev is not None:
|
||||||
|
_, prev_end, _, prev_end_lvl, _ = prev
|
||||||
|
gap = start_ts - prev_end
|
||||||
|
if gap > GAP_THRESHOLD:
|
||||||
|
gap_row = GapRow(prev_end, prev_end_lvl, start_ts, start_lvl)
|
||||||
|
self.session_group.add(gap_row)
|
||||||
|
|
||||||
row = SessionRow(start_ts, end_ts, start_lvl, end_lvl, status)
|
row = SessionRow(start_ts, end_ts, start_lvl, end_lvl, status)
|
||||||
self.session_group.add(row)
|
self.session_group.add(row)
|
||||||
|
prev = s
|
||||||
|
|
||||||
if not sessions:
|
if not merged:
|
||||||
empty = Adw.ActionRow(title='No sessions recorded')
|
empty = Adw.ActionRow(title='No sessions recorded')
|
||||||
empty.add_css_class('dim-label')
|
empty.add_css_class('dim-label')
|
||||||
self.session_group.add(empty)
|
self.session_group.add(empty)
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
#!/usr/bin/env python3
|
#!/usr/bin/python3 -sP
|
||||||
"""
|
"""
|
||||||
batteryd — battery tracking daemon
|
batteryd — battery tracking daemon
|
||||||
|
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
[Desktop Entry]
|
[Desktop Entry]
|
||||||
Name=ScreenTime
|
Name=Screentime Viewer
|
||||||
Comment=View your screen time usage
|
Comment=View your screen time usage
|
||||||
Exec=screentime-viewer
|
Exec=screentime-viewer
|
||||||
Icon=preferences-system-time-symbolic
|
Icon=preferences-system-time-symbolic
|
||||||
0
screentimed/screentime-viewer
Normal file → Executable file
0
screentimed/screentime-viewer
Normal file → Executable file
0
screentimed/screentimed
Normal file → Executable file
0
screentimed/screentimed
Normal file → Executable file
Reference in New Issue
Block a user