From caad2ba8ef8580c25b29086fd8d29d18b6529c73 Mon Sep 17 00:00:00 2001 From: hesam-init Date: Tue, 2 Jul 2024 17:45:31 +0330 Subject: [PATCH] refactor: eww notifications --- .../hyprland/eww/{src => }/_definitions.yuck | 3 +- .../eww/{setups.yuck => _setups.yuck} | 0 hypr-configs/hyprland/eww/eww.yuck | 4 +- .../hyprland/eww/scripts/iconfetch.py | 1 + hypr-configs/hyprland/eww/scripts/notifManage | 55 ---- .../hyprland/eww/scripts/notification/manage | 59 +++++ .../eww/scripts/notification/notifications.py | 236 ++++++++++++++++++ .../{notif.py => notification/notifs.py} | 0 .../hyprland/eww/src/notification/main.yuck | 174 ++++++------- .../eww/src/windows/_control-panel.yuck | 211 ++++++++-------- 10 files changed, 498 insertions(+), 245 deletions(-) rename hypr-configs/hyprland/eww/{src => }/_definitions.yuck (98%) rename hypr-configs/hyprland/eww/{setups.yuck => _setups.yuck} (100%) delete mode 100755 hypr-configs/hyprland/eww/scripts/notifManage create mode 100755 hypr-configs/hyprland/eww/scripts/notification/manage create mode 100755 hypr-configs/hyprland/eww/scripts/notification/notifications.py rename hypr-configs/hyprland/eww/scripts/{notif.py => notification/notifs.py} (100%) diff --git a/hypr-configs/hyprland/eww/src/_definitions.yuck b/hypr-configs/hyprland/eww/_definitions.yuck similarity index 98% rename from hypr-configs/hyprland/eww/src/_definitions.yuck rename to hypr-configs/hyprland/eww/_definitions.yuck index fe4af36..3bc966a 100644 --- a/hypr-configs/hyprland/eww/src/_definitions.yuck +++ b/hypr-configs/hyprland/eww/_definitions.yuck @@ -73,10 +73,9 @@ (deflisten notifications :initial '{ "count": 0, "dnd": false, - "notifications": [], "popups": [] }' - "./scripts/notif.py" + "./scripts/notification/notifs.py" ) ; Playerctl diff --git a/hypr-configs/hyprland/eww/setups.yuck b/hypr-configs/hyprland/eww/_setups.yuck similarity index 100% rename from hypr-configs/hyprland/eww/setups.yuck rename to hypr-configs/hyprland/eww/_setups.yuck diff --git a/hypr-configs/hyprland/eww/eww.yuck b/hypr-configs/hyprland/eww/eww.yuck index 1854fa9..4160dab 100644 --- a/hypr-configs/hyprland/eww/eww.yuck +++ b/hypr-configs/hyprland/eww/eww.yuck @@ -1,4 +1,4 @@ -(include "./src/_definitions.yuck") +(include "./_definitions.yuck") (include "./src/-components/_helpers.yuck") (include "./src/-components/_separator.yuck") @@ -16,7 +16,7 @@ (include "./src/windows/_dashboard.yuck") (include "./src/windows/_osd.yuck") -(include "./setups.yuck") +(include "./_setups.yuck") (include "./src/wallpapers/main.yuck") (include "./src/dock/main.yuck") diff --git a/hypr-configs/hyprland/eww/scripts/iconfetch.py b/hypr-configs/hyprland/eww/scripts/iconfetch.py index f5d0cc0..ab69f81 100755 --- a/hypr-configs/hyprland/eww/scripts/iconfetch.py +++ b/hypr-configs/hyprland/eww/scripts/iconfetch.py @@ -1,4 +1,5 @@ #!/usr/bin/env python3 + import gi gi.require_version('Gtk', '3.0') from gi.repository import Gtk diff --git a/hypr-configs/hyprland/eww/scripts/notifManage b/hypr-configs/hyprland/eww/scripts/notifManage deleted file mode 100755 index 9e6d1ea..0000000 --- a/hypr-configs/hyprland/eww/scripts/notifManage +++ /dev/null @@ -1,55 +0,0 @@ -#!/usr/bin/bash - -# Taken from Juminai - -dismiss() { - dbus-send --session --type=method_call \ - --dest=org.freedesktop.Notifications \ - /org/freedesktop/Notifications \ - org.freedesktop.Notifications.DismissPopup \ - uint32:$1 -} - -close() { - dbus-send --session --type=method_call \ - --dest=org.freedesktop.Notifications \ - /org/freedesktop/Notifications \ - org.freedesktop.Notifications.CloseNotification \ - uint32:$1 -} - -action() { - dbus-send --session --type=method_call \ - --dest=org.freedesktop.Notifications \ - /org/freedesktop/Notifications \ - org.freedesktop.Notifications.InvokeAction \ - uint32:$1 string:$2 -} - -clear_all() { - dbus-send --session --type=method_call \ - --dest=org.freedesktop.Notifications \ - /org/freedesktop/Notifications \ - org.freedesktop.Notifications.ClearAll -} - -listen() { - dbus-send --session --type=method_call \ - --dest=org.freedesktop.Notifications \ - /org/freedesktop/Notifications \ - org.freedesktop.Notifications.Listen -} - -toggle_dnd() { - dbus-send --session --type=method_call \ - --dest=org.freedesktop.Notifications \ - /org/freedesktop/Notifications \ - org.freedesktop.Notifications.ToggleDND -} - -if [[ $1 == '--dismiss' ]]; then dismiss $2 $3; fi -if [[ $1 == '--close' ]]; then close $2; fi -if [[ $1 == '--action' ]]; then action $2 $3; fi -if [[ $1 == '--clear' ]]; then clear_all; fi -if [[ $1 == '--listen' ]]; then listen; fi -if [[ $1 == '--toggle' ]]; then toggle_dnd; fi diff --git a/hypr-configs/hyprland/eww/scripts/notification/manage b/hypr-configs/hyprland/eww/scripts/notification/manage new file mode 100755 index 0000000..cc43b80 --- /dev/null +++ b/hypr-configs/hyprland/eww/scripts/notification/manage @@ -0,0 +1,59 @@ +#!/usr/bin/bash + +DBUS_CMD="dbus-send --session --type=method_call --dest=org.freedesktop.Notifications /org/freedesktop/Notifications" + +dismiss() { + $DBUS_CMD org.freedesktop.Notifications.DismissPopup uint32:$1 +} + +close() { + $DBUS_CMD org.freedesktop.Notifications.CloseNotification uint32:$1 +} + +action() { + $DBUS_CMD org.freedesktop.Notifications.InvokeAction uint32:$1 string:$2 +} + +get_current() { + $DBUS_CMD org.freedesktop.Notifications.GetCurrent +} + +clear_all() { + $DBUS_CMD org.freedesktop.Notifications.ClearAll +} + +listen() { + $DBUS_CMD org.freedesktop.Notifications.Listen +} + +toggle_dnd() { + $DBUS_CMD org.freedesktop.Notifications.ToggleDND +} + +case "$1" in +--dismiss) + dismiss "$2" + ;; +--close) + close "$2" + ;; +--action) + action "$2" "$3" + ;; +--current) + get_current + ;; +--clear) + clear_all + ;; +--listen) + listen + ;; +--toggle) + toggle_dnd + ;; +*) + echo "Usage: $0 {--dismiss|--close|--action|--clear|--listen|--toggle} [args]" + exit 1 + ;; +esac diff --git a/hypr-configs/hyprland/eww/scripts/notification/notifications.py b/hypr-configs/hyprland/eww/scripts/notification/notifications.py new file mode 100755 index 0000000..69dd236 --- /dev/null +++ b/hypr-configs/hyprland/eww/scripts/notification/notifications.py @@ -0,0 +1,236 @@ +#!/usr/bin/python +import gi +gi.require_version("GdkPixbuf", "2.0") +gi.require_version("Gtk", "3.0") + +import dbus +import dbus.service +from dbus.mainloop.glib import DBusGMainLoop +from gi.repository import GLib +import datetime +import os +import typing +import sys +import json +from gi.repository import Gtk, GdkPixbuf +import subprocess + +cache_dir = f"{os.getenv('HOME')}/.cache/notify_img_data" +log_file = f"{os.getenv('HOME')}/.cache/notifications.json" +os.makedirs(cache_dir, exist_ok=True) +active_popups = {} + +# RECIEVE NOTIFICATIONS + +class NotificationDaemon(dbus.service.Object): + def __init__(self): + bus_name = dbus.service.BusName("org.freedesktop.Notifications", dbus.SessionBus()) + dbus.service.Object.__init__(self, bus_name, "/org/freedesktop/Notifications") + self.dnd = False + + @dbus.service.method("org.freedesktop.Notifications", in_signature="susssasa{sv}i", out_signature="u") + def Notify(self, app_name, replaces_id, app_icon, summary, body, actions, hints, timeout): + replaces_id = int(replaces_id) + actions = list(actions) + app_icon = str(app_icon) + app_name = str(app_name) + summary = str(summary) + body = str(body) + + if replaces_id != 0: + id = replaces_id + else: + log_file = self.read_log_file() + if log_file['notifications'] != []: + id = log_file['notifications'][0]['id'] + 1 + else: + id = 1 + + acts = [] + for i in range(0, len(actions), 2): + acts.append([str(actions[i]), str(actions[i + 1])]) + + details = { + "id": id, + "app": app_name, + "summary": self.format_long_string(summary, 35), + "body": self.format_long_string(body, 35), + "time": datetime.datetime.now().strftime("%H:%M"), + "urgency": hints["urgency"] if "urgency" in hints else 1, + "actions": acts + } + + + if app_icon.strip(): + if os.path.isfile(app_icon) or app_icon.startswith("file://"): + details["image"] = app_icon + else: + details["image"] = self.get_gtk_icon(app_icon) + else: + details["image"] = None + + if "image-data" in hints: + details["image"] = f"{cache_dir}/{details['id']}.png" + self.save_img_byte(hints["image-data"], details["image"]) + + self.save_notifications(details) + if not self.dnd: + self.save_popup(details) + return id + + + + def format_long_string(self, long_string, interval): + split_string = [] + max_length = 256 + + for i in range(0, len(long_string), interval): + split_string.append(long_string[i:i+interval]) + + result = "-\n".join(split_string) + + if len(result) > max_length: + result = result[:max_length] + "..." + + return result + + @dbus.service.method("org.freedesktop.Notifications", in_signature="", out_signature="ssss") + def GetServerInformation(self): + return ("linkfrg's notification daemon", "linkfrg", "1.0", "1.2") + + @dbus.service.method("org.freedesktop.Notifications", in_signature="", out_signature="as") + def GetCapabilities(self): + return ('actions', 'body', 'icon-static', 'persistence') + + @dbus.service.signal("org.freedesktop.Notifications", signature="us") + def ActionInvoked(self, id, action): + return (id, action) + + @dbus.service.method("org.freedesktop.Notifications", in_signature="us", out_signature="") + def InvokeAction(self, id, action): + self.ActionInvoked(id, action) + + @dbus.service.signal("org.freedesktop.Notifications", signature="uu") + def NotificationClosed(self, id, reason): + return (id, reason) + + @dbus.service.method("org.freedesktop.Notifications", in_signature="u", out_signature="") + def CloseNotification(self, id): + current = self.read_log_file() + current["notifications"] = [n for n in current["notifications"] if n["id"] != id] + current["count"] = len(current["notifications"]) + + self.write_log_file(current) + self.NotificationClosed(id, 2) + self.DismissPopup(id) + + @dbus.service.method("org.freedesktop.Notifications", in_signature="", out_signature="") + def ToggleDND(self): + match self.dnd: + case False: + self.dnd = True + case True: + self.dnd = False + + @dbus.service.method("org.freedesktop.Notifications", in_signature="", out_signature="") + def GetDNDState(self): + subprocess.run(["eww", "update", f"do-not-disturb={json.dumps(self.dnd)}"]) + + + def get_gtk_icon(self, icon_name): + theme = Gtk.IconTheme.get_default() + icon_info = theme.lookup_icon(icon_name, 128, 0) + + if icon_info is not None: + return icon_info.get_filename() + + + def save_img_byte(self, px_args: typing.Iterable, save_path: str): + GdkPixbuf.Pixbuf.new_from_bytes( + width=px_args[0], + height=px_args[1], + has_alpha=px_args[3], + data=GLib.Bytes(px_args[6]), + colorspace=GdkPixbuf.Colorspace.RGB, + rowstride=px_args[2], + bits_per_sample=px_args[4], + ).savev(save_path, "png") + + + def write_log_file(self, data): + output_json = json.dumps(data, indent=2) + subprocess.run(["eww", "update", f"notifications={output_json}"]) + with open(log_file, "w") as log: + log.write(output_json) + + def read_log_file(self): + empty = {"count": 0, "notifications": [], "popups": []} + try: + with open(log_file, "r") as log: + return json.load(log) + except FileNotFoundError: + with open(log_file, "w") as log: + json.dump(empty, log) + return empty + + + def save_notifications(self, notification): + current = self.read_log_file() + current["notifications"].insert(0, notification) + current["count"] = len(current["notifications"]) + + self.write_log_file(current) + + @dbus.service.method("org.freedesktop.Notifications", in_signature="", out_signature="") + def ClearAll(self): + for notify in self.read_log_file()['notifications']: + self.NotificationClosed(notify['id'], 2) + data = {"count": 0, "notifications": [], "popups": []} + + self.write_log_file(data) + + + # OPERATIONS WITH POPUPS + + def save_popup(self, notification): + global active_popups + + current = self.read_log_file() + if len(current["popups"]) >= 3: + oldest_popup = current["popups"].pop() + self.DismissPopup(oldest_popup["id"]) + + current["popups"].append(notification) + self.write_log_file(current) + + popup_id = notification["id"] + active_popups[popup_id] = GLib.timeout_add_seconds(5, self.DismissPopup, popup_id) + + @dbus.service.method("org.freedesktop.Notifications", in_signature="u", out_signature="") + def DismissPopup(self, id): + global active_popups + + current = self.read_log_file() + current["popups"] = [n for n in current["popups"] if n["id"] != id] + self.write_log_file(current) + + active_popups.pop(id, None) + + @dbus.service.method("org.freedesktop.Notifications", in_signature="", out_signature="") + def GetCurrent(self): + subprocess.run(["eww", "update", f"notifications={json.dumps(self.read_log_file())}"]) + + +# MAINLOOP + +def main(): + DBusGMainLoop(set_as_default=True) + loop = GLib.MainLoop() + NotificationDaemon() + try: + loop.run() + except KeyboardInterrupt: + exit(0) + +if __name__ == "__main__": + main() diff --git a/hypr-configs/hyprland/eww/scripts/notif.py b/hypr-configs/hyprland/eww/scripts/notification/notifs.py similarity index 100% rename from hypr-configs/hyprland/eww/scripts/notif.py rename to hypr-configs/hyprland/eww/scripts/notification/notifs.py diff --git a/hypr-configs/hyprland/eww/src/notification/main.yuck b/hypr-configs/hyprland/eww/src/notification/main.yuck index 58f8896..e9d5336 100644 --- a/hypr-configs/hyprland/eww/src/notification/main.yuck +++ b/hypr-configs/hyprland/eww/src/notification/main.yuck @@ -1,90 +1,90 @@ - (defwindow notifypopup - :geometry (geometry - :x 0 - :y 0 - :width 480 - :height 0 - :anchor "top right") - :stacking "overlay" - :monitor 0 - (revealer - :reveal { arraylength(notifications.popups) > 0 } - :transition "slidedown" - (box - :orientation "v" - :space-evenly false - :spacing 5 - (for noti in {notifications.popups} - (singlenotif :noti noti :initial true))))) + :geometry (geometry + :x 0 + :y 0 + :width 480 + :height 0 + :anchor "top right") + :stacking "overlay" + :monitor 0 + + (revealer + :reveal { arraylength(notifications.popups) > 0 } + :transition "slidedown" + (box + :orientation "v" + :space-evenly false + :spacing 5 + (for noti in {notifications.popups} + (singlenotif :noti noti :initial true))))) (defwidget singlenotif [noti initial] - (box - :orientation "v" - :class "${initial ? 'popup' : 'notifbox'}" - :space-evenly false - - (centerbox - :orientation "h" - :class "notifbar" - (image :halign "start" :image-width 30 :image-height 30 :path {noti.icon != "null" ? noti.icon : "./assets/image/idk.svg"}) - (scroll - :halign "center" - :valign "center" - :hexpand true - :hscroll true - :vscroll false - :width 200 - (label - :class "notiflabel" - :text {noti.app})) - (button - :halign "end" - :onclick "./scripts/notifManage --close ${noti.id}" - (label - :class "notifclose" - :text ""))) - - (box - :orientation "h" - :halign "fill" - :height 80 - :space-evenly false - :spacing 10 - (image :image-width 80 :image-height 80 :visible {noti.image != "null"} :path {noti.image != "null" ? noti.image : "./assets/image/idk.svg"}) - - (button - :onclick "./scripts/notifManage --dismiss ${noti.id}" - :onrightclick "./scripts/notifManage --close ${noti.id}" - :tooltip "${noti.time}" - :hexpand true - :vexpand true - (box - :orientation "v" - :space-evenly false - :valign "center" - (scroll - :hscroll true - :vscroll false - :hexpand true - (label - :class "notiftitle" - :text {noti.summary})) - (scroll - :hscroll true - :vscroll false - :hexpand true - (label - :class "notifbody" - :visible {noti.body != "null"} - :text {noti.body}))))) - - (box - :orientation "h" - (for action in {noti.actions} - (button - :onclick "./scripts/notifManage --action ${noti.id} ${action[0]} && ./scripts/notifManage --close ${noti.id}" - (label - :class "notifactions" - :text {action[1]})) - )))) + (box + :orientation "v" + :class "${initial ? 'popup' : 'notifbox'}" + :space-evenly false + + (centerbox + :orientation "h" + :class "notifbar" + (image :halign "start" :image-width 30 :image-height 30 :path {noti.icon != "null" ? noti.icon : "./assets/image/idk.svg"}) + (scroll + :halign "center" + :valign "center" + :hexpand true + :hscroll true + :vscroll false + :width 200 + (label + :class "notiflabel" + :text {noti.app})) + (button + :halign "end" + :onclick "./scripts/notification/manage --close ${noti.id}" + (label + :class "notifclose" + :text ""))) + + (box + :orientation "h" + :halign "fill" + :height 80 + :space-evenly false + :spacing 10 + (image :image-width 80 :image-height 80 :visible {noti.image != "null"} :path {noti.image != "null" ? noti.image : "./assets/image/idk.svg"}) + + (button + :onclick "./scripts/notification/manage --dismiss ${noti.id}" + :onrightclick "./scripts/notification/manage --close ${noti.id}" + :tooltip "${noti.time}" + :hexpand true + :vexpand true + (box + :orientation "v" + :space-evenly false + :valign "center" + (scroll + :hscroll true + :vscroll false + :hexpand true + (label + :class "notiftitle" + :text {noti.summary})) + (scroll + :hscroll true + :vscroll false + :hexpand true + (label + :class "notifbody" + :visible {noti.body != "null"} + :text {noti.body}))))) + + (box + :orientation "h" + (for action in {noti.actions} + (button + :onclick "./scripts/notification/manage --action ${noti.id} ${action[0]} && ./scripts/notification/manage --close ${noti.id}" + (label + :class "notifactions" + :text {action[1]})) + )))) diff --git a/hypr-configs/hyprland/eww/src/windows/_control-panel.yuck b/hypr-configs/hyprland/eww/src/windows/_control-panel.yuck index 52bb70e..2ec7dc0 100644 --- a/hypr-configs/hyprland/eww/src/windows/_control-panel.yuck +++ b/hypr-configs/hyprland/eww/src/windows/_control-panel.yuck @@ -5,39 +5,39 @@ :orientation "v" :valign "fill" :vexpand true - - (user) + + (User ) (chooser) ; (weather) - - (MediaPlayer :h 160 :permashow true) - + + ; (MediaPlayer :h 160 :permashow true) + (box :orientation "h" :space-evenly false :height 180 - + (Timer) (bigslides)) - + (box :space-evenly false :orientation "v" :vexpand true :visible true - + (Toolbox) (NotificationsWeatherBox)) - )) + )) (defwidget Toolbox [] (eventbox :cursor "pointer" - + (box :class "tricontrol panel-widget" :orientation "h" - + (button :onclick "./scripts/pop colourpick" (label :text "󰈊")) (button :onclick "./scripts/pop scrop" (label :text "󰆞")) (button :onclick "~/.config/eww/themeswitch/scripts/pop" (label :text ""))))) @@ -48,10 +48,10 @@ :height 60 :class "panel-widget" :space-evenly false - + (box :orientation "h" - + (button :onclick "${EWW_CMD} update reveal4=${!reveal4} reveal5=false reveal6=false" :onrightclick "foot nvim ~/Documents/fuck.txt" @@ -62,7 +62,7 @@ (button :onclick "${EWW_CMD} update reveal6=${!reveal6} reveal5=false reveal4=false" (label :class {reveal6 ? "titlesel" : "title"} :text "Hyprland"))) - + (notes) (sysinfo) (wmctrl))) @@ -99,19 +99,19 @@ :val gapsouter :onchange "swaymsg gaps outer all set {}" :max 300 - :reset "${EWW_CMD} update gapsouter=0 && swaymsg gaps outer all set 0") + :reset "${EWW_CMD} update gapsouter=0 && swaymsg gaps outer all set 0") (wmslider :name "gaps inner" :val gapsinner :onchange "swaymsg gaps inner all set {}" :max 150 - :reset "${EWW_CMD} update gapsinner=15 && swaymsg gaps inner all set 15") + :reset "${EWW_CMD} update gapsinner=15 && swaymsg gaps inner all set 15") (wmslider :name "border size" :val borderpixel :onchange "swaymsg default_border pixel {} && swaymsg '[app_id=\".*\"] border pixel {}'" :max 50 - :reset "${EWW_CMD} update borderpixel=2 && swaymsg default_border pixel 2 && swaymsg '[app_id=\".*\"] border pixel 2'") + :reset "${EWW_CMD} update borderpixel=2 && swaymsg default_border pixel 2 && swaymsg '[app_id=\".*\"] border pixel 2'") (box :orientation "h" :space-evenly false @@ -120,7 +120,7 @@ (label :text "natural scrolling") (checkbox :onchecked "swaymsg input \"type:touchpad\" natural_scroll enable" - :onunchecked "swaymsg input \"type:touchpad\" natural_scroll disable")) + :onunchecked "swaymsg input \"type:touchpad\" natural_scroll disable")) (box :orientation "h" :space-evenly false @@ -130,8 +130,8 @@ (checkbox :onchecked "swaymsg input \"type:touchpad\" dwt enable" :onunchecked "swaymsg input \"type:touchpad\" dwt disable" - )) - + )) + (box :orientation "h" :space-evenly false @@ -141,8 +141,8 @@ (checkbox :onchecked "swaymsg [app_id='.*'] inhibit_idle open && ${EWW_CMD} update caffeine=true" :onunchecked "swaymsg [app_id='.*'] inhibit_idle none && ${EWW_CMD} update caffeine=false" - )) - )))) + )) + )))) (defwidget sysinfo [] (revealer @@ -155,7 +155,7 @@ (systat :icon "󰍛" :val { EWW_RAM.used_mem_perc }) (systat :icon "󰈐" :val { gpu }) (systat :icon "" :val { EWW_BATTERY.BAT0.capacity }) - ))) + ))) (defwidget wmslider [name val onchange max reset] (box @@ -167,18 +167,18 @@ :valign "center" :spacing 10 (label - :text name) + :text name) (scale :min 0 :max max :class "wmctrlslide" :tooltip val :value val - :onchange onchange) + :onchange onchange) (button :onclick reset :style "padding: 0px 8px 0px 3px;" - ""))) + ""))) (defwidget systat [icon val] (overlay @@ -187,8 +187,8 @@ :valign "center" :class "circsys" :thickness 40 - :value val) - + :value val) + (box :class "circiconcontain" :halign "center" @@ -197,7 +197,7 @@ :width 55 (label :text icon)))) -(defwidget user[] +(defwidget User [] (revealer :reveal {!reveal4 && !reveal5 && !reveal6} :transition "slideup" @@ -232,7 +232,7 @@ :vexpand true :class "panel-widget" :space-evenly false - + (box :orientation "h" (button @@ -241,28 +241,28 @@ (button :onclick "${EWW_CMD} update revealWeather=true" (label :class {revealWeather ? "titlesel" : "title"} :text "Weather"))) - + (box :orientation "h" :vexpand true :hexpand true :space-evenly false - + (revealer :reveal {!revealWeather} :hexpand {!revealWeather} :transition "slideleft" - - (notificationlog)) - + + (NotificationsLogs)) + (revealer :reveal revealWeather :hexpand revealWeather :transition "slideleft" + + (Weather))))) - (weather))))) - -(defwidget weather[] +(defwidget Weather [] (overlay (box :orientation "v" @@ -270,8 +270,9 @@ :valign "fill" :vexpand true :space-evenly false - + (weathermain) + (scroll :hscroll false :vscroll true @@ -287,8 +288,66 @@ :hexpand true :vexpand false :height 80 + :class "fadeoutbox") + )) + +(defwidget NotificationsLogs [] + (box + :halign "fill" + :valign "fill" + :width 320 + :vexpand true + :space-evenly false + :orientation "v" + + (overlay + :vexpand true + + (box + :halign "fill" + :valign "fill" + :vexpand true + :space-evenly false + :orientation "v" + + (scroll + :hscroll false + :vscroll true + :vexpand true + :valign "fill" + + (box + :orientation "v" + :valign "start" + :space-evenly false + (for notif in {notifications.notifications} + (singlenotif :noti notif :initial false)))) + ) + + (box + :valign "end" + :hexpand true + :vexpand false + :height 80 :class "fadeoutbox") - )) + ) + + (box + :orientation "h" + :valign "end" + + (button + :onclick "./scripts/notification/manage --clear" + (label + :class "title" + :text "Clear All")) + (button + :onclick "./scripts/notification/manage --toggle" + (label + :class { notifications.dnd ? "titlesel" : "title"} + :text "Do Not Disturb"))) + ) +) (defwidget weatherhour[hour] (box @@ -304,7 +363,7 @@ (image :image-width 50 :image-height 50 - :path "./assets/image/weather/${hour.icon}.svg") + :path "./assets/image/weather/${hour.icon}.svg") (box :orientation "v" :space-evenly false @@ -313,7 +372,7 @@ (label :halign "start" :text "${hour.FeelsLikeC}°C") (label :halign "start" :text "rain: ${hour.chanceofrain}%")))) -(defwidget weathermain[] +(defwidget weathermain [] (box :class "mainentry" :orientation "h" @@ -325,7 +384,7 @@ :image-width 100 :image-height 100 :style "margin: 10px;" - :path "./assets/image/weather/${weatherjson.icon}.svg") + :path "./assets/image/weather/${weatherjson.icon}.svg") (scroll :hscroll true :vscroll false @@ -338,7 +397,7 @@ (label :halign "start" :text "← ${weatherjson.windspeedKmph} km/h") ;; (label :halign "start" :text "${weatherjson.visibility} km") ;; (label :halign "start" :text "${weatherjson.precipMM} mm") - )))) + )))) (defwidget Timer [] (box @@ -347,7 +406,7 @@ :space-evenly false :valign "fill" :width 200 - + (label :class "timer" :valign "center" :vexpand true :text timerdis) (box :orientation "h" @@ -378,11 +437,11 @@ :tooltip "${volume}%" :max 100 :min 0 - :flipped true) + :flipped true) (label :class "slideicon" :valign "end" - :text {volumemute == 'false' ? "󰕾" : "󰖁"}))) + :text {volumemute == 'false' ? "󰕾" : "󰖁"}))) (defwidget bigmic [] (overlay @@ -394,11 +453,11 @@ :tooltip "${mic_volume}%" :max 100 :min 0 - :flipped true) + :flipped true) (label :class "slideicon" :valign "end" - :text {volumemute == 'false' ? "" : "󰖁"}))) + :text {volumemute == 'false' ? "" : "󰖁"}))) (defwidget bigbright [] (overlay @@ -410,57 +469,11 @@ :tooltip "${brightness}%" :max 100 :min 0 - :flipped true) + :flipped true) (label :class "slideicon" :valign "end" - :text "󰃞"))) - -(defwidget notificationlog [] - (overlay - (box - :halign "fill" - :valign "fill" - :vexpand true - :space-evenly false - :orientation "v" - - (scroll - :hscroll false - :vscroll true - :vexpand true - :valign "fill" - - (box - :orientation "v" - :valign "start" - :space-evenly false - (for noti in {notifications.notifications} - (singlenotif :noti noti :initial false)))) - - (box - :valign "end" - :hexpand true - :vexpand false - :height 80 - :class "fadeoutbox") - (box - :orientation "h" - (button - :onclick "./scripts/notifManage --clear" - (label - :class "title" - :text "Clear All")) - (button - :onclick "./scripts/notifManage --toggle" - (label - :class { notifications.dnd ? "titlesel" : "title"} - :text "Do Not Disturb"))) - ) - - ) - - ) + :text "󰃞"))) (defwidget quote [] (box @@ -475,7 +488,7 @@ :class "quote" :text {quotejson.content} :wrap true - :width 300)) + :width 300)) (label :class "quoteauthor" - :text "- ${quotejson.author}"))) \ No newline at end of file + :text "- ${quotejson.author}"))) \ No newline at end of file