wakatime / desktop-wakatime

Windows & Linux system tray app for automatic time tracking and metrics generated from your Figma, Postman, etc. usage.
https://wakatime.com/windows
BSD 3-Clause "New" or "Revised" License
57 stars 10 forks source link

[Linux] Monitored app crashes application #44

Open yan-pi opened 1 month ago

yan-pi commented 1 month ago

logs:

./wakatime-linux-x86_64.AppImage

(desktop-wakatime:462009): Gtk-WARNING **: 14:29:19.291: Theme parsing error: gtk.css:6691:68: Invalid name of pseudo-class
[WakaTime][DEBUG] Electron's autoUpdater does not support the 'linux' platform. Ref: https://www.electronjs.org/docs/latest/api/auto-updater#platform-notices
[WakaTime][DEBUG] Starting WakaTime
[WakaTime][DEBUG] Registered as login item
[WakaTime][DEBUG] Fetching code time: /home/yan-fesf/.wakatime/wakatime-cli-linux-amd64 --today,--today-hide-categories,true,--plugin,linux-wakatime/0.5.0

(desktop-wakatime:462009): Gtk-WARNING **: 14:29:19.540: Theme parsing error: gtk-dark.css:6691:68: Invalid name of pseudo-class
thread '<unnamed>' panicked at x-win-rs/src/linux/api/wayland_extension_api.rs:207:6:
called `Result::unwrap()` on an `Err` value: MethodError("org.freedesktop.DBus.Error.UnknownMethod", Some("O objeto não existe no caminho “/org/gnome/Shell/Extensions/XWinWaylandExtension”"), Msg { type: Error, sender: ":1.20", reply-serial: 2, body: Signature: [
    s (115),
] })
note: run with `RUST_BACKTRACE=1` environment variable to display a backtrace
[WakaTime][DEBUG] Skip checking for wakatime-cli updates because recently checked 32 minutes ago
thread '<unnamed>' panicked at x-win-rs/src/linux/api/wayland_extension_api.rs:207:6:
called `Result::unwrap()` on an `Err` value: MethodError("org.freedesktop.DBus.Error.UnknownMethod", Some("O objeto não existe no caminho “/org/gnome/Shell/Extensions/XWinWaylandExtension”"), Msg { type: Error, sender: ":1.20", reply-serial: 2, body: Signature: [
    s (115),
] })
fatal runtime error: failed to initiate panic, error 5
[1]    462009 IOT instruction (core dumped)  ./wakatime-linux-x86_64.AppImage
zackdavidson commented 1 month ago

I've had a crack at changing the source code and managed to get this rendering, however, the solution is not good and does not track selected applications properly.

image

yan-pi commented 1 month ago

How did you manage to fix it? What do you mean by 'not working correctly'? This information can help fix the bug... This is impacting some functionalities of my portfolio that depend on this API.

zackdavidson commented 1 month ago

@yan-pi then let's hope the owner fixes it.

yan-pi commented 1 month ago

@zackdavidson I’m talking about you contributing to the solution or providing guidance on how the problem occurs, and not just “I fixed it but it doesn’t work properly”. And I’m not asking you to help me with my portfolio, LOL.

zackdavidson commented 1 month ago

@zackdavidson I’m talking about you contributing to the solution or providing guidance on how the problem occurs, and not just “I fixed it but it doesn’t work properly”. And I’m not asking you to help me with my portfolio, LOL.

Unfortunately there is no push access to a new branch - the issue seems to be a lack of access on x-win-rs module on rust that can't access /proc/{}/exe - i tried several permissions to no avail.

What i done was the following - created a linux.ts

import { exec } from "child_process";
import fs from "fs";
import path from "path";

import { AppData } from "../../utils/validators";

export async function getInstalledAppsLinux(
  directory = "/usr/share/applications",
): Promise<AppData[]> {
  const directoryContents = await getDirectoryContents(directory);
  const appsFileInfo = getAppsFileInfo(directoryContents);
  return (
    await Promise.all(
      appsFileInfo.map((appFileInfo) => getAppData(appFileInfo)),
    )
  ).filter(Boolean) as AppData[];
}

function getDirectoryContents(directory: string) {
  return new Promise<string[]>((resolve, reject) => {
    exec(`ls ${directory}`, (error, stdout) => {
      if (error) {
        reject(error);
      } else {
        try {
          resolve(getAppsSubDirectory(stdout, directory));
        } catch (err) {
          reject(err);
        }
      }
    });
  });
}

function getAppsSubDirectory(stdout: string, directory: string): string[] {
  let stdoutArr = stdout.split(/[(\r\n)\r\n]+/);
  stdoutArr = stdoutArr
    .filter((o) => o.endsWith(".desktop"))
    .map((i) => {
      return `${directory}/${i}`;
    });
  return stdoutArr;
}

function getAppsFileInfo(appsFile: readonly string[]) {
  // Just return the file paths for desktop files
  return appsFile.map((file) => [file]);
}

async function getAppData(singleAppFileInfo: string[]) {
  const filePath = singleAppFileInfo[0];
  if (!filePath) {
    return;
  }

  const appInfo = parseDesktopFile(filePath);
  if (!appInfo || !appInfo.Name) {
    return;
  }

  const name = appInfo.Name;
  const execName = appInfo.Exec?.split(" ")[0] || name;
  const iconPath = appInfo.Icon ? findIconPath(appInfo.Icon) : null;
  const version = null; // Version is not typically found in desktop files

  return {
    path: filePath,
    icon: iconPath ? `file://${iconPath}` : null,
    name,
    bundleId: filePath,
    id: appInfo.Name,
    isBrowser: false,
    isDefaultEnabled: true,
    isElectronApp: false,
    version,
    execName,
  } satisfies AppData;
}

function parseDesktopFile(filePath: string): Record<string, string> {
  const content = fs.readFileSync(filePath, { encoding: "utf-8" });
  const lines = content.split(/\r?\n/);
  const record: Record<string, string> = {};

  lines.forEach((line) => {
    const [key, ...value] = line.split("=");
    if (key && value.length) {
      record[key.trim()] = value.join("=").trim();
    }
  });

  return record;
}

function findIconPath(iconName: string): string | null {
  // Try to find the icon in common icon directories
  const iconDirs = [
    "/usr/share/icons",
    "/usr/share/pixmaps",
    path.join(process.env.HOME || "", ".local/share/icons"),
  ];

  for (const dir of iconDirs) {
    const iconPathPng = path.join(dir, `${iconName}.png`);
    const iconPathSvg = path.join(dir, `${iconName}.svg`);

    if (fs.existsSync(iconPathPng)) {
      return iconPathPng;
    }
    if (fs.existsSync(iconPathSvg)) {
      return iconPathSvg;
    }
  }
  return null;
}

Which was very similar to the mac.ts and windows.ts and i changed the following:

import { AppData } from "../../utils/validators";
import { getInstalledApps as getInstalledAppsMac} from "./mac";
import { getInstalledApps as getInstalledAppsWindows } from "./windows";
import {getInstalledAppsLinux} from "./linux.ts";

export async function getApps(): Promise<AppData[]> {
  let apps: AppData[] = [];

  if (process.platform === "win32") {
    apps = await getInstalledAppsWindows();
  } else if (process.platform === "darwin") {
    apps = await getInstalledAppsMac();
  } else if (process.platform === "linux") {
    apps = await getInstalledAppsLinux();
    console.log('####### ' + JSON.stringify(apps));
  }

  return apps;
}

The problem lie's with the tracking, whenever i enable an application on the menu, it does nothing. It does not track this properly.

muety commented 1 month ago

Same issue here with Ubuntu 22.04, Gnome 42.9, Wayland.

vycoder commented 1 month ago

I'm having the same issue with Pop!_OS 22.04 LTS x86_64. Is there like a config file where we can use to configure the monitored apps? So at least we can try going that route?

Vitexus commented 1 month ago

Today downloaded v1.0.0 Crash when try to load list of applications on Debian 12

vitex@gamer:~/Downloads$ chmod +x wakatime-linux-x86_64.AppImage 

vitex@gamer:~/Downloads$ ./wakatime-linux-x86_64.AppImage
[WakaTime][DEBUG] Failed to read file: /home/vitex/.config/WakaTime/desktop-wakatime.cfg. Error: Error: ENOENT: no such file or directory, open '/home/vitex/.config/WakaTime/desktop-wakatime.cfg'
[WakaTime][DEBUG] Starting WakaTime v1.0.0
[WakaTime][DEBUG] Registered as login item
Checking for update
[WakaTime][DEBUG] Checking for update
[WakaTime][DEBUG] Fetching code time: /home/vitex/.wakatime/wakatime-cli-linux-amd64 --today,--today-hide-categories,true,--plugin,linux-wakatime/1.0.0
thread '<unnamed>' panicked at x-win-rs/src/linux/api/wayland_extension_api.rs:207:6:
called `Result::unwrap()` on an `Err` value: MethodError("org.freedesktop.DBus.Error.ServiceUnknown", Some("The name org.gnome.Shell was not provided by any .service files"), Msg { type: Error, sender: "org.freedesktop.DBus", reply-serial: 2, body: Signature: [
        s (115),
] })
note: run with `RUST_BACKTRACE=1` environment variable to display a backtrace
Generated new staging user ID: 03a76133-a75c-5c96-ba26-22cbf8fb8ed2
libva error: /usr/lib/x86_64-linux-gnu/dri/iHD_drv_video.so init failed
[WakaTime][DEBUG] Latest wakatime-cli release: v1.102.3
Update for version 1.0.0 is not available (latest version: 1.0.0, downgrade is disallowed).
[WakaTime][DEBUG] Update not available
checkForUpdatesAndNotify called, downloadPromise is null
thread '<unnamed>' panicked at x-win-rs/src/linux/api/wayland_extension_api.rs:207:6:
called `Result::unwrap()` on an `Err` value: MethodError("org.freedesktop.DBus.Error.ServiceUnknown", Some("The name org.gnome.Shell was not provided by any .service files"), Msg { type: Error, sender: "org.freedesktop.DBus", reply-serial: 2, body: Signature: [
        s (115),
] })
thread '<unnamed>' panicked at library/core/src/panicking.rs:221:5:
panic in a function that cannot unwind
stack backtrace:
   0:     0x7f4bbe1f7861 - <unknown>
   1:     0x7f4bbe19742b - <unknown>
   2:     0x7f4bbe1c71b2 - <unknown>
   3:     0x7f4bbe1fc3c7 - <unknown>
   4:     0x7f4bbe1fd665 - <unknown>
   5:     0x7f4bbe1fce32 - <unknown>
   6:     0x7f4bbe1fcdc9 - <unknown>
   7:     0x7f4bbe1fcdb4 - <unknown>
   8:     0x7f4bbe188874 - <unknown>
   9:     0x7f4bbe1888dc - <unknown>
  10:     0x7f4bbe188889 - <unknown>
  11:     0x7f4bbe24ca10 - <unknown>
  12:     0x5558b44d82e8 - <unknown>
thread caused non-unwinding panic. aborting.
Aborted (core dumped)
vycoder commented 3 weeks ago

Just updated to v1.0.1, it now works!

vycoder commented 3 weeks ago

Just updated to v1.0.1, it now works!

Unfortunately, it's not really working properly. I was able to launch the monitored apps BUT the apps I selected are not really being monitored. It's not showing up on the stats. When I'm on Mac, it can monitor zoom, notion etc and being logged properly. But in Ubuntu it's not really recording those activities.

Also, I noticed that if I have another application that is also an Electron (like Ferdium) app, Wakatime desktop will crash.