;-------------------------------------------------------
; SYSTEM MONITOR WITH TABS - UPDATED VERSION
;-------------------------------------------------------
(defvar performance_monitor_visible false)
;; Variable active tab
(defvar active_tab "dashboard")
;; ===== POLLING VARIABLES =====
;; Profile polls
(defpoll profile
:interval "60s"
:initial '{"username": "loading...", "wm": "loading...", "uptime": "...", "image": ""}'
"~/.config/eww/scripts/profile.sh json")
(defpoll system
:interval "2s"
:initial '{"cpu_usage": 0, "cpu_temp": 0, "mem_perc": 0, "mem_used": "0G", "mem_total": "0G", "disk_perc": 0, "disk_used": "0G", "disk_total": "0G"}'
:run-while performance_monitor_visible
"~/.config/eww/scripts/sys_info.sh")
;; Music polls
(deflisten media_info
:initial '{"player": "", "status": "Stopped", "title": "No Media", "artist": "", "cover": ""}'
"~/.config/eww/scripts/media_listener.sh")
;;Cava polls
(deflisten cava :initial "" `~/.config/eww/scripts/cava.sh`)
;; Weather polls
(defpoll WEATHER_ICON :interval "1800s" "~/.config/eww/scripts/weather-wrapper.sh icon")
(defpoll WEATHER_DESC :interval "1800s" "~/.config/eww/scripts/weather-wrapper.sh desc")
(defpoll WEATHER_CITY :interval "86400s" "~/.config/eww/scripts/weather-wrapper.sh city")
;; ===== CLOCK POLLING =====
(defpoll times
:interval "1s"
"date '+{\"h\":\"%H\",\"m\":\"%M\",\"d\":\"%a, %d %b\"}'")
(defpoll my_notes
:interval "30s"
:run-while performance_monitor_visible
"~/.config/eww/scripts/read_note.sh")
;; Variables info laptop
(defpoll laptop_info :interval "86400s"
:initial '{"brand":"Loading...","model":"Loading...","cpu":"...","gpu":"...","ram":"...","disk":"...","logo_path":"..."}'
"~/.config/eww/scripts/get-laptop-info.sh")
;; Tab Navigation Widget
(defwidget tab_navigation []
(box :class "tab-navigation"
:orientation "h"
:space-evenly true
:spacing 0
;; Tab Performance
(button :class "tab-button ${active_tab == 'performance' ? 'active' : ''}"
:onclick "eww update active_tab=performance"
(box :orientation "h"
:spacing 8
:space-evenly false
:halign "center"
(label :class "tab-label" :text "Performance")))
;; Tab Dashboard
(button :class "tab-button ${active_tab == 'dashboard' ? 'active' : ''}"
:onclick "eww update active_tab=dashboard"
(box :orientation "h"
:spacing 8
:space-evenly false
:halign "center"
(label :class "tab-label" :text "Dashboard")))
;; Tab Information
(button :class "tab-button ${active_tab == 'information' ? 'active' : ''}"
:onclick "eww update active_tab=information"
(box :orientation "h"
:spacing 8
:space-evenly false
:halign "center"
(label :class "tab-label" :text "Information")))
))
;; Metric Bar Widget
(defwidget metric_bar [icon label value usage_text color_class]
(box :class "metric-bar-container"
:orientation "v"
:space-evenly false
:spacing 8
;; Header dengan icon dan label
(box :class "metric-header"
:orientation "h"
:space-evenly false
:spacing 10
:valign "center"
(label :class "metric-icon ${color_class}"
:text icon
:valign "center")
(box :class "description-metric"
:orientation "v"
:space-evenly false
:spacing 2
:valign "center"
(label :class "metric-label"
:text label
:xalign 0)
(label :class "metric-value-text"
:text value
:xalign 0)
(label :class "metric-usage-text"
:text usage_text
:xalign 0)))))
;;Profile Widget
(defwidget profile_widget []
(box :class "info-card"
:orientation "h"
:space-evenly false
:spacing 12
:valign "center"
;; Profile Image
;; Akses via profile.image
(box :class "image"
:style {profile.image != "" ? "background-image: url('${profile.image}');" : "background-image: none;"})
;; Profile Info
(box :class "card-content"
:orientation "v"
:space-evenly false
:valign "center"
;; Username
;; Akses via profile.username
(box :class "info-row"
:orientation "h" :space-evenly false :spacing 6
(label :class "info-icon" :text "")
(label :class "info-text" :limit-width 17 :text {profile.username} :xalign 0))
;; Window Manager
;; Akses via profile.wm
(box :class "info-row"
:orientation "h" :space-evenly false :spacing 6
(label :class "info-icon" :text "")
(label :class "info-text" :text {profile.wm} :xalign 0))
;; Uptime
;; Akses via profile.uptime
(box :class "info-row"
:orientation "h" :space-evenly false :spacing 6
(label :class "info-icon" :text "")
(label :class "info-text" :limit-width 17 :text {profile.uptime} :xalign 0)))))
;; Weather Widget
(defwidget weather_widget []
(box :class "info-card-weather"
:orientation "h"
:space-evenly false
:hexpand true
(box :class "info-row-weather"
:orientation "h"
:spacing 0
:width 133
:height 106
(label :class "weather-icon" :text WEATHER_ICON))
;; Weather info
(box :class "card-content"
:orientation "v"
:space-evenly false
:spacing 5
:valign "center"
(label :class "info-weather" :limit-width 12 :wrap true :wrap-mode "wordchar" :lines 2 :justify "center" :text WEATHER_CITY :xalign 0.5)
(label :class "info-text" :limit-width 21 :wrap true :wrap-mode "wordchar" :lines 2 :justify "center" :text WEATHER_DESC :xalign 0.5))
))
(defwidget calendar_box []
(box :class "calendar-box"
:orientation "v"
:space-evenly false
(calendar :class "cal-widget"
:vexpand false
:valign "start")))
;; Clock & Date Widget
(defwidget clock_box []
(box :class "clock-box"
:orientation "v"
:vexpand true
:valign "fill"
(box :orientation "v"
:space-evenly false
:spacing 8
:valign "center"
:vexpand true
;; Time Display
(label :class "clock-time"
:text {times.h})
(label :class "clock-separator"
:text "---")
(label :class "clock-time"
:text {times.m})
;; Date Display
(label :class "clock-date"
:text {times.d}))))
;; Quick Apps Widget
(defwidget apps_box []
(box :class "apps-box"
:orientation "v"
:space-evenly true
:spacing 5
;; Row 1
(box :orientation "h"
:space-evenly true
:spacing 5
;; alacritty
(button :class "app-button"
:onclick "alacritty & eww close performance_monitor"
(label :class "app-icon" :xalign 0.5 :text ""))
;; pcmanfm
(button :class "app-button"
:onclick "pcmanfm & eww close performance_monitor"
(label :class "app-icon-1" :text "")))
;; Row 2
(box :orientation "h"
:space-evenly true
:spacing 5
;; neovim
(button :class "app-button"
:onclick "alacritty -e nvim & eww close performance_monitor"
(label :class "app-icon-2" :text ""))
;; calibre
(button :class "app-button"
:onclick "calibre & eww close performance_monitor"
(label :class "app-icon-3" :text "")))
;; Row 3
(box :orientation "h"
:space-evenly true
:spacing 5
;; image viewer
(button :class "app-button"
:onclick "qimgv & eww close performance_monitor"
(label :class "app-icon-4" :text ""))
;; Terminal
(button :class "app-button"
:onclick "cheese & eww close performance_monitor"
(label :class "app-icon-5" :text "")))
))
;; WIDGET MEDIA PLAYER
(defwidget media_widget []
(box :class "media-widget-container"
:orientation "v"
:space-evenly false
:spacing 10
:vexpand true
;; Cover Art
(box :class "media-cover-widget"
:style {media_info.cover != "" ? "background-image: url('${media_info.cover}'); background-size: contain; background-repeat: no-repeat; background-position: center;" : "background-image: none;"}
:visible {media_info.cover != ""})
;; Media Info
(box :class "media-widget-info"
:orientation "v"
:space-evenly false
:spacing 5
;; Label section
(box :orientation "v"
:space-evenly false
:hexpand true
:halign "center"
(label :class "media-widget-name"
:text {media_info.player}
:visible {media_info.player != ""}
:xalign 0.5)
(label :class "media-widget-title"
:text {media_info.title}
:limit-width 24
:xalign 0.5)
(label :class "media-widget-artist"
:text {media_info.artist}
:limit-width 27
:xalign 0.5))
;; Controls
(box :class "media-widget-controls" :halign "center" :spacing 10
(button :class "media-widget-btn"
:onclick "playerctl -p ${media_info.player} previous"
(box :width 40 :height 40 :halign "center" :valign "center"
(label :text "" :style "font-size: 37px;")))
(button :class "media-widget-btn-play"
:onclick "playerctl -p ${media_info.player} play-pause"
(box :width 40 :height 40 :halign "center" :valign "center"
(label :text {media_info.status == "Playing" ? "" : ""}
:style "font-size: 43px;")))
(button :class "media-widget-btn"
:onclick "playerctl -p ${media_info.player} next"
(box :width 40 :height 40 :halign "center" :valign "center"
(label :text "" :style "font-size: 37px;"))))
)))
;;CAVA Widget
(defwidget cava []
(box :class "cava-container"
:orientation "v"
(label :text "${cava}"
:class "cava")))
;; NOTE BOX
(defwidget note_box []
(box :class "note-container"
:orientation "v"
:halign "center"
:valign "center"
(button :class "edit-btn"
:onclick "xdg-open ~/.config/eww/my-notes.txt &"
(box :orientation "v"
:space-evenly false
:valign "center"
(label :text my_notes
:class "note-text"
:xalign 0.5
:yalign 0.5
:limit-width 21
:wrap true
:wrap-mode "wordchar"
:lines 2
:justify "center")))))
;; Performance Content Widget
(defwidget performance_content []
(box :class "tab-content"
:orientation "h"
:spacing 10
:space-evenly true
;; CPU
(metric_bar
:icon ""
:label "CPU"
:value "${system.cpu_temp}°C"
:usage_text "${system.cpu_usage}% Usage"
:color_class "cpu-color")
;; Memory
(metric_bar
:icon ""
:label "RAM"
:value "${system.mem_used} / ${system.mem_total}"
:usage_text "${system.mem_perc}% Used"
:color_class "mem-color")
;; Disk
(metric_bar
:icon ""
:label "Disk"
:value "${system.disk_used} / ${system.disk_total}"
:usage_text "${system.disk_perc}% Used"
:color_class "disk-color")))
;; Widget box utama
(defwidget laptop-info-widget []
(box :class "laptop-container"
:orientation "h"
:space-evenly false
:spacing 10
;; Logo laptop dari cache
(box :class "logo-section"
:halign "center"
(image :path {laptop_info.logo_path}
:image-width 67
:image-height 67
:visible {laptop_info.logo_path != ""}))
;; Info spesifikasi
(box :class "specs-section"
:orientation "v"
:space-evenly false
:spacing 0
;; Brand & Model
(box :class "brand-row"
:space-evenly false
:spacing 10
:orientation "h"
(label :class "spec-brand" :text "${laptop_info.model}"))
;; CPU
(box :class "spec-row"
:space-evenly false
:spacing 10
(box :orientation "h" :space-evenly false :spacing 10
(label :class "spec-label" :width 93 :text "CPU" :xalign 0)
(label :class "spec-value" :text "${laptop_info.cpu}" :halign "start")))
;; GPU
(box :class "spec-row"
:space-evenly false
:spacing 10
(box :orientation "h"
:space-evenly false
:spacing 10
:width 400
(label :class "spec-label" :text "GPU" :width 93 :xalign 0)
(label :class "spec-value"
:text "${laptop_info.gpu}"
:wrap true
:limit-width 47
:lines 2
:justify "left"
:halign "start")))
;; RAM
(box :class "spec-row"
:space-evenly false
:spacing 0
(box :orientation "h" :space-evenly false :spacing 10
(label :class "spec-label" :text "Memory" :width 93 :xalign 0)
(label :class "spec-value" :text "${laptop_info.ram}" :halign "start")))
;; Disk
(box :class "spec-row"
:space-evenly false
:spacing 0
(box :orientation "h" :space-evenly false :spacing 10
(label :class "spec-label" :text "Storage" :width 93 :xalign 0)
(label :class "spec-value" :text "${laptop_info.disk}" :halign "start"))))))
;; Dashboard Content Widget
(defwidget dashboard_content []
(box :class "tab-content other-content"
:orientation "h"
:space-evenly false
:spacing 10
;;KOLOM KIRI
(box :orientation "v"
:spacing 10
:space-evenly false
;; Row 1: Profile and Weather
(box :class "column"
:orientation "h"
:spacing 10
:space-evenly false
(profile_widget)
(weather_widget))
;; Row 2: Calendar, Clock, Apps
(box :class "column"
:orientation "h"
:spacing 10
:hexpand true
:space-evenly false
(clock_box)
(calendar_box)
(apps_box)))
;; KOLOM KANAN
(box :class "right-column"
:orientation "v"
:spacing 10
:space-evenly false
:vexpand true
(media_widget)
(cava)
(note_box))
))
;; Main Widget
(defwidget main_widget []
(box :class "main-container"
:orientation "v"
:space-evenly false
;; Tab Navigation (Tombol Atas)
(tab_navigation)
;; Kita mapping logic: dashboard=0, performance=1, information=2
(box :class "content-area"
(stack :selected {active_tab == "dashboard" ? 0 : active_tab == "performance" ? 1 : 2}
:transition "slideleft" ;; Animasi gratis! (bisa crossfade, slideright, dll)
;; Index 0: Dashboard Content
(dashboard_content)
;; Index 1: Performance Content
(performance_content)
;; Index 2: Information Content
(laptop-info-widget)
)
)
)
)
;; ----------------------------------------
;; CLICKABLE OVERLAY TO CLOSE DASHBOARD
;; ----------------------------------------
(defwindow dashboard_overlay
:monitor 0
:geometry (geometry :x "0%"
:y "0%"
:width "100%"
:height "100%"
:anchor "center center")
:stacking "bg"
:windowtype "dock"
:wm-ignore true
:focusable false
(eventbox :onclick "eww close performance_monitor dashboard_overlay && eww update performance_monitor_visible=false"
(box :class "dashboard-overlay")))
;; ----------------------------------------
;; JENDELA UTAMA
;; ----------------------------------------
(defwindow performance_monitor
:monitor 0
:geometry (geometry :x "0%"
:y "45px"
:width "930px"
:height "510px"
:anchor "top center")
:stacking "overlay"
:exclusive true
:windowtype "dialog"
:wm-ignore true
:focusable false
:resizable false
(main_widget))