From c8e359ffe4e83ddbc14a35dd57ae8285b4be85f7 Mon Sep 17 00:00:00 2001 From: Sly_tom_cat Date: Fri, 27 Dec 2024 16:41:17 +0300 Subject: [PATCH] Review and code optimization --- .github/workflows/go.yml | 9 ++++---- README.md | 45 ++++++++++++++++++++++------------------ icons/icons.go | 14 ++++++------- icons/img/readme | 29 ++++++++++++++------------ notify/notify.go | 5 ++--- notify/notify_test.go | 8 ++++++- ydisk/ydisk.go | 2 +- ydisk/ydisk_test.go | 13 +++++------- 8 files changed, 67 insertions(+), 58 deletions(-) diff --git a/.github/workflows/go.yml b/.github/workflows/go.yml index 8eeff74..831873a 100644 --- a/.github/workflows/go.yml +++ b/.github/workflows/go.yml @@ -3,7 +3,6 @@ on: push: branches: - master - - dev pull_request: branches: - master @@ -16,10 +15,10 @@ jobs: uses: actions/setup-go@v5 with: go-version-file: './go.mod' - - name: Prepare similator + - name: Prepare simulator run: | - curl -L https://github.com/slytomcat/yandex-disk-simulator/releases/latest/download/yandex-disk-simulator > yandex-disk - chmod a+x yandex-disk + curl -L https://github.com/slytomcat/yandex-disk-simulator/releases/latest/download/yandex-disk-simulator > yandex-disk + chmod a+x yandex-disk - name: Test run: | export PATH=$(pwd):$PATH @@ -61,7 +60,7 @@ jobs: with: name: build_artifacts - name: draft new release and upload assets - env: + env: GH_TOKEN: ${{ secrets.TOKEN }} run: | gh release create "$(git branch --show-current)-$(git rev-parse --short HEAD)" ./yd-go diff --git a/README.md b/README.md index fac10d9..99b471d 100644 --- a/README.md +++ b/README.md @@ -1,4 +1,4 @@ -# yd-go +# yd-go [![Go](https://github.com/slytomcat/yd-go/actions/workflows/go.yml/badge.svg?branch=master)](https://github.com/slytomcat/yd-go/actions/workflows/go.yml) ## Panel indicator for Yandex-disk CLI daemon (linux) @@ -6,7 +6,7 @@ This version of indicator uses B-Bus for communication to the status notification plugin. Therefore it's fully independent of the desktop environment of Linux distribution. -IMPORTANT: +IMPORTANT: Indicator responsible only for showing the synchronization status in the desktop panel. All the synchronization operations are performed by [yandex-disk utility from Yandex](https://yandex.ru/support/disk-desktop-linux/index.html). @@ -16,47 +16,48 @@ Russian wiki: https://github.com/slytomcat/yd-go/wiki STORY: -I've made it as it is rather well-known task for me: I've made the similar indicator (GTK+ version) in YD-tools project in Python language: https://github.com/slytomcat/yandex-disk-indicator. +I've made it as it is rather well-known task for me: I've made the similar indicator (GTK+ version) in [YD-tools project in Python language](https://github.com/slytomcat/yandex-disk-indicator). And when I started to learn golang the rewriting the indicator were rather obvious task to practice a new language. Initially there was two versions of golang indicators: for GTK+ and for QT. But later I've adopted new version of indicator library that uses D-Bus for organizing user interface. DESCRIPTION: -Indicator shows current status by different icons in the status notification area. During synchronization the icon is animated. Indicator supports dark and light themes. The current theme can be changed via menu. +Indicator shows current status by different icons in the status notification area. During synchronization the icon is animated. Indicator supports dark and light themes. The current theme can be changed via menu. Desktop notifications inform user when daemon started/stopped or synchronization started/stopped. Notifications can be switched off. -The status notification icon has menu that allows to: +The status notification icon has a menu that allows to: - see the current daemon status and cloud-disk properties (Used/Total/Free/Trash) - - see paths of the last synchronized files and open them (in default program) + - see paths of the last synchronized files and open them (in default program) - start/stop daemon - see the original output of daemon in the current user language - - open local synchronized path - - open Yandex.Disk in browser + - open local synchronized path into the default file-manager + - open Yandex.Disk in the default browser - open help/support page - - change the indicator settings (see "Theme", "Notifications", "StartDaemon" and "StopDaemon" settings below) + - change the indicator settings (see `"Theme"`, `"Notifications"`, `"StartDaemon"` and `"StopDaemon"` settings below) -Application uses its configuration file with default path ~/.config/yd-go/default.cfg file. File is in JSON format and contain following options: - - "Conf" - Path to daemon config file (default "~/.config/yandex-disk/config.cfg"). This setting can be changed by the -config application option. - - "Theme" - Icons theme name (default "dark", may be set to "dark" or "light"). This setting can be changed via indicator menu. - - "Notifications" - Display or not the desktop notifications (default true). This setting can be changed via indicator menu. - - "StartDaemon" - Flag that shows that the daemon should be started on app start (default true). This setting can be changed via indicator menu. - - "StopDaemon" - Flag that shows that the daemon should be stopped on app closure. This setting can be changed via indicator menu. +Application uses settings from the configuration file. The default path to configuration file is `~/.config/yd-go/default.cfg`. The path can be changed by the `-config` application option. The file is in JSON format and it contain following options: + - `"Conf"` - Path to daemon config file (default `"~/.config/yandex-disk/config.cfg"`). + - `"Theme"` - Icons theme name (default `"dark"`, may be set to `"dark"` or `"light"`). This setting can be changed via indicator menu. + - `"Notifications"` - Display or not the desktop notifications (default `true`). This setting can be changed via indicator menu. + - `"StartDaemon"` - Flag that shows that the daemon should be started on app start (default `true`). This setting can be changed via indicator menu. + - `"StopDaemon"` - Flag that shows that the daemon should be stopped on app closure (defaul `false`). This setting can be changed via indicator menu. ## Get -Download linux-amd64 binary from [releases](https://github.com/slytomcat/yd-go/releases), copy it to path in PATH (/usr/local/bin for example) and make it executable. +Download linux-amd64 binary from [releases](https://github.com/slytomcat/yd-go/releases), copy it to path in PATH (/usr/local/bin for example) and make it executable. -OR +OR Get source from master branch and unzip it or just clone repository build it and install as described below. -## Build -You must have Golang v1.20+ installed to build the binary. There is no additional libraries/packages required for building. Just jump into project directory and run: +## Build +You must have Golang v1.24+ installed to build the binary. There is no additional libraries/packages required for building except the optional `upx` utility. Just jump into project directory and run: ```bash ./build.sh ``` +When `upx` is available then the binary will be additionally compressed. If `upx` is not installed then the binary will be uncompressed and a warning appears abut it. You can use both compressed and not compressed binary, the only difference is the used space on disk for binary (not soo much in both cases). ## Installation -Run +Run ```bash sudo cp yd-go /usr/local/bin/ ``` @@ -73,3 +74,7 @@ sudo cp yd-go /usr/local/bin/ NOTE: the yandex-disk CLI utility must be installed and configured before starting of the yd-go. + +## Icons + +All the indicator icons are embedded into binary during the build time. But You can change them and rebuild the indicator. See more details about icons into [icons/img/readme](icons/img/readme) diff --git a/icons/icons.go b/icons/icons.go index 9100f83..f761c5a 100644 --- a/icons/icons.go +++ b/icons/icons.go @@ -28,15 +28,11 @@ type Icon struct { // NewIcon initializes the icon helper and returns it. // Use icon.CleanUp() for properly utilization of icon helper. func NewIcon(theme string, set func([]byte)) (*Icon, error) { - file, err := os.CreateTemp(os.TempDir(), "yd_notify_icon*.png") + file, err := os.CreateTemp("", "yd_notify_icon*.png") if err != nil { return nil, fmt.Errorf("icon store error: %v", err) } - _, err = file.Write(yd128) - if err != nil { - return nil, fmt.Errorf("icon store error: %v", err) - } - + defer file.Close() ctx, cancel := context.WithCancel(context.Background()) i := &Icon{ currentStatus: "", @@ -50,8 +46,12 @@ func NewIcon(theme string, set func([]byte)) (*Icon, error) { if err = i.SetTheme(theme); err != nil { return nil, err } - go i.loop(ctx) i.setFunc(i.pauseIcon) + _, err = file.Write(yd128) + if err != nil { + return nil, fmt.Errorf("icon store error: %v", err) + } + go i.loop(ctx) return i, nil } diff --git a/icons/img/readme b/icons/img/readme index e9f1182..1fb6e12 100644 --- a/icons/img/readme +++ b/icons/img/readme @@ -1,13 +1,16 @@ -Icons themes are used to display the indicator status. -There are two themes: - dark* - for dark panel - light* - for light panel -Each theme should provide the following set of icons: - *idle.png - displayed when Yandex.disk is synchronized - *pause.png - displayed when Yandex.disk daemon not started or synchronization is paused - *error.png - displayed when some error occurs in synchronization - *busy[1-5].png - set of icons to indicate the synchronization process. -Icons *busy[1-5].png are displayed in loop (to provide animated icon): - *busy1.png -> *busy2.png -> *busy3.png -> *busy4.png -> *busy5.png -> *busy1.png -> *busy2.png ... - -yd128.png - big icon for about dialogue and notifications +Icons are used to display the indicator statuses. + +There are two icons themes: + `dark*` - for dark panel + `light*` - for light panel + +Each theme must support the following set of icons: + `*Idle.png` - displayed when Yandex.disk is synchronized + `*Pause.png` - displayed when Yandex.disk daemon not started or synchronization is paused + `*Error.png` - displayed when some error occurs in synchronization + `*Busy[1-5].png` - set of icons to indicate the synchronization process. + +Icons `*Busy[1-5].png` are displayed sequentially in the loop (to simulate animation): + `*Busy1.png` -> `*Busy2.png` -> `*Busy3.png` -> `*Busy4.png` -> `*Busy5.png` -> `*Busy1.png` -> `*Busy2.png` ... + +The special big icon `yd128.png` is used into about dialogue and into notifications. diff --git a/notify/notify.go b/notify/notify.go index 3fde454..c5568f4 100644 --- a/notify/notify.go +++ b/notify/notify.go @@ -26,7 +26,7 @@ const ( // The application is the name of application. // The defaultIcon is icon name/path to be used for notification when no icon specified during the Send call. // True value of replace means that a new notification will replace the previous one if it is still displayed. -// The time sets the time in milliseconds after which the notification will disappear. Set it to -1 to use default. +// The time sets the time in milliseconds after which the notification will disappear. Set it to -1 to use Desktop default settings. func New(application, defaultIcon string, replace bool, time int) (*Notify, error) { conn, err := dbus.ConnectSessionBus() if err != nil { @@ -40,8 +40,7 @@ func New(application, defaultIcon string, replace bool, time int) (*Notify, erro conn: conn, connObj: conn.Object(dBusDest, dBusPath), } - _, err = notify.Cap() - if err != nil { + if _, err = notify.Cap(); err != nil { return nil, err } return notify, nil diff --git a/notify/notify_test.go b/notify/notify_test.go index 5fec69e..df85bca 100644 --- a/notify/notify_test.go +++ b/notify/notify_test.go @@ -2,6 +2,7 @@ package notify import ( "os" + "path" "testing" "time" @@ -31,5 +32,10 @@ func TestDBusNotify(t *testing.T) { n.Send(icon, "title3", "message3") time.Sleep(time.Second) n.Send("", "title4", "message4") - + time.Sleep(time.Second) + p, err := os.Getwd() + require.NoError(t, err) + p, _ = path.Split(p) + p += "/icons/img/yd128.png" + n.Send(p, "cool title", "cool message") } diff --git a/ydisk/ydisk.go b/ydisk/ydisk.go index b217084..9b52291 100644 --- a/ydisk/ydisk.go +++ b/ydisk/ydisk.go @@ -282,7 +282,7 @@ func (yd YDisk) getOutput(userLang bool) string { } out, err := exec.Command(cmd[0], cmd[1:]...).Output() if err != nil { - log.Error("daemon_status", "error", err.Error()) + log.Error("daemon_status", "error", err.Error(), "message", strings.TrimSuffix(string(out), "\n")) return "" } return string(out) diff --git a/ydisk/ydisk_test.go b/ydisk/ydisk_test.go index 1d038da..a87d84c 100644 --- a/ydisk/ydisk_test.go +++ b/ydisk/ydisk_test.go @@ -35,19 +35,19 @@ func TestMain(m *testing.M) { os.Setenv("Sim_ConfDir", CfgPath) err := os.MkdirAll(CfgPath, 0755) if err != nil { - fmt.Print(CfgPath, " creation error:", err) + fmt.Printf("Path '%s' creation error: %v\n", CfgPath, err) os.Exit(1) } SymExe, err = exec.LookPath("yandex-disk") if err != nil { - fmt.Println("yandex-disk utility lookup error:", err) + fmt.Printf("yandex-disk utility lookup error: %v\n", err) os.Exit(1) } exec.Command(SymExe, "stop").Run() os.RemoveAll(path.Join(os.TempDir(), "yandexdisksimulator.socket")) - fmt.Printf("Tests init completed: yd exe: %v", SymExe) + fmt.Printf("Tests init completed: yd exe: %v\n", SymExe) // Run tests e := m.Run() @@ -93,12 +93,9 @@ func TestFull(t *testing.T) { // prepare for simulation err := exec.Command(SymExe, "setup").Run() require.NoError(t, err) - var YD *YDisk var yds YDvals - t.Run("Create", func(t *testing.T) { - YD, err = NewYDisk(Cfg, slog.Default()) - require.NoError(t, err) - }) + YD, err = NewYDisk(Cfg, slog.Default()) + require.NoError(t, err) t.Run("NotStartedOutput", func(t *testing.T) { output := YD.Output()