diff --git a/git_companion/README.md b/git_companion/README.md index 78f111f9..b921091d 100644 --- a/git_companion/README.md +++ b/git_companion/README.md @@ -31,10 +31,31 @@ your open PR/MR and issue counts. Click it to open the panel. noctalia msg panel-toggle tphilippot/git_companion:main ``` -**Panel** — two tabs, **Pull Requests / Merge Requests** and **Issues**, each -listing your items. Click an item to open it on the web (GitHub or GitLab) in -your browser; the panel closes as it opens. Use the **refresh** button in the -header to re-fetch immediately. The last-updated time is shown next to the tabs. +**Panel** — the header carries a **refresh** button that re-fetches immediately +and a **close** button. Below it, a row shows your avatar, your username and a +subtitle (your `group` if set, otherwise your `repo`, otherwise your profile bio), +with the **last-update** time on the right. The avatar and username appear once +the CLI resolves your account; the last-update time is always shown. + +Then up to three tabs, each listing items by title and reference: + +- **Pull Requests / Merge Requests** — the ones you authored. +- **Issues** — the ones assigned to you. +- **Code Review** — open, unmerged PR/MRs waiting on your review. + +On GitLab a check glyph marks a merge request whose `detailed_merge_status` is +`mergeable`. Click an item to open it on the web (GitHub or GitLab) in your +browser; the panel closes as it opens. + +Each tab can be hidden with its `show_*` setting, and a hidden tab is not +fetched at all. Hide every tab and the panel says so instead of showing an empty +list. + +**Branch badges** — a coloured chip in front of the reference of a PR/MR shows +the branch it targets, so a merge request into `develop` reads differently +from one into `release/18.3.4` at a glance. Issues have no target branch and +never carry one. The chip requires a provider that reports the target branch, +which **GitHub does not** — see Notes. ## Settings @@ -45,9 +66,35 @@ header to re-fetch immediately. The last-updated time is shown next to the tabs. | `group` | `string` | `""` | Filter by group (GitLab) or owner (GitHub). Leave empty to use `repo`. | | `refresh_interval` | `int` | `60` | Seconds between automatic refreshes (minimum 10). | | `bar_display_mode` | `select` | `both` | What the bar shows next to the glyph: `none`, `prs` (PRs/MRs only), `issues` (Issues only), or `both`. | +| `show_prs` | `bool` | `true` | Show the PRs/MRs tab. | +| `show_issues` | `bool` | `true` | Show the Issues tab. | +| `show_reviews` | `bool` | `true` | Show the Code Review tab. | +| `count_reviews_with_prs` | `bool` | `false` | Add the review count to the PR/MR number in the bar. Hidden while `show_reviews` is off. | +| `branch_badge_primary` | `string_list` | `["develop"]` | Branch patterns badged in the theme's primary accent. | +| `branch_badge_secondary` | `string_list` | `["release/*"]` | Branch patterns badged in the secondary accent. | +| `branch_badge_tertiary` | `string_list` | `[]` | Branch patterns badged in the tertiary accent. | +| `branch_badge_alert` | `string_list` | `["master", "main"]` | Branch patterns badged in the theme's alert colour. | + +The four `branch_badge_*` lists decide the colour of the branch chip. Put one +branch pattern per entry: either an exact branch name (`develop`) or a prefix +ending in `*` (`release/*` matches `release/18.3.4`). The lists are checked in +the order above and **the first match wins**, so a branch listed under two +colours takes the earlier one. A branch matching nothing gets no chip. + +The colour is the setting you put the branch in, so there is no colour to type. +Adding a fifth colour requires a plugin change rather than configuration. The +chips only appear for providers that report a target branch, which excludes +GitHub — see Notes. On GitHub the widget lists pull requests **authored by you** and issues **assigned -to you**; on GitLab it lists merge requests and issues **assigned to you**. +to you**. On GitLab it lists merge requests and issues **authored by you** — both +GitLab lists are filtered by author, not by assignee. The Code Review tab is +filtered by **requested reviewer** on both platforms, and includes drafts. + +`show_reviews` is the master switch for the Code Review feature: turned off, the +tab disappears, nothing is fetched for it, and `count_reviews_with_prs` has no +effect. The bar tooltip always lists issues, PRs/MRs and reviews separately, so +a folded count is never ambiguous. ## IPC @@ -63,10 +110,24 @@ fetch completes. - **Network:** each refresh calls the GitHub or GitLab API through the installed CLI (`gh search prs/issues` or `glab mr/issue list`), scoped by your `repo` or - `group` setting. + `group` setting. One call per visible tab, so hiding a tab removes its request. + The Code Review tab uses `glab mr list --reviewer=@me` or + `gh search prs --review-requested=@me`, which **both** platforms support — + unlike the branch badge below. +- **Branch badges are not available on GitHub.** The chip needs each item's + target branch, which the provider has to report. `glab` returns it with every + merge request. `gh search prs` has no base-branch field at all, and it is the + only GitHub call that works across a whole owner, so pull requests fetched + from GitHub render without a chip. This is a per-provider capability rather + than a setting: the `branch_badge_*` lists stay configured and apply to any + provider that does report a target branch. - **Processes:** the service spawns `gh` or `glab` for fetches; the panel spawns `xdg-open` (non-blocking) when you click an item. -- **Filesystem:** nothing is written to disk — plugin state is in-memory only and - is cleared when the plugin stops. +- **Filesystem:** the service downloads your profile picture to the plugin's own + data directory, at `~/.local/state/noctalia/plugins/data/tphilippot/git_companion/avatar` + (it follows `NOCTALIA_STATE_HOME` if you set it), so the panel can show it next + to your username. It is re-downloaded only when the avatar URL changes, and the + file persists until you delete it. Nothing else is written: the PR/MR and issue + lists are in-memory only and are cleared when the plugin stops. - **GitLab scope:** GitLab requires a `repo` or `group` scope in settings; the - service shows an error notification if neither is set. \ No newline at end of file + service shows an error notification if neither is set. diff --git a/git_companion/panel.luau b/git_companion/panel.luau index cb389ca3..37c9497a 100644 --- a/git_companion/panel.luau +++ b/git_companion/panel.luau @@ -8,15 +8,17 @@ local snapshot = { prs = noctalia.state.get("prs") or {}, issues = noctalia.state.get("issues") or {}, + reviews = noctalia.state.get("reviews") or {}, prsCount = noctalia.state.get("prs_count") or 0, issuesCount = noctalia.state.get("issues_count") or 0, + reviewsCount = noctalia.state.get("reviews_count") or 0, updatedAt = noctalia.state.get("last_update") or "", status = noctalia.state.get("status") or "ok", username = noctalia.state.get("username") or "", bio = noctalia.state.get("bio") or "", avatarPath = noctalia.state.get("avatar_path") or "", } -local currentTab = "prs" -- "prs" or "issues" +local currentTab = "prs" -- a TABS id local hoveredKey = nil local render @@ -36,8 +38,80 @@ local function itemsForTab() return type(value) == "table" and value or {} end +local TABS = { + { id = "prs", setting = "show_prs", glyph = "git-pull-request" }, + { id = "issues", setting = "show_issues", glyph = "info-circle" }, + { id = "reviews", setting = "show_reviews", glyph = "eye" }, +} + +local function visibleTabs() + local shown = {} + for _, tab in ipairs(TABS) do + if noctalia.getConfig(tab.setting) ~= false then table.insert(shown, tab) end + end + return shown +end + +local function resolveTab(shown) + for _, tab in ipairs(shown) do + if tab.id == currentTab then return tab end + end + return shown[1] +end + local function itemGlyph() - return currentTab == "prs" and "git-pull-request" or "info-circle" + for _, tab in ipairs(TABS) do + if tab.id == currentTab then return tab.glyph end + end + return "info-circle" +end + +local BADGE_BUCKETS = { + { key = "branch_badge_primary", color = "primary" }, + { key = "branch_badge_secondary", color = "secondary" }, + { key = "branch_badge_tertiary", color = "tertiary" }, + { key = "branch_badge_alert", color = "error" }, +} + +local function matchesBranch(branch, pattern) + local prefix = pattern:match("^(.*)%*$") + if prefix then return branch:sub(1, #prefix) == prefix end + return branch == pattern +end + +-- First bucket holding a matching pattern wins. A branch listed under two +-- colours is the user's call, so there is nothing to arbitrate here. +local function branchColor(branch) + if not branch or branch == "" then return nil end + for _, bucket in ipairs(BADGE_BUCKETS) do + local patterns = noctalia.getConfig(bucket.key) + if type(patterns) == "table" then + for _, pattern in ipairs(patterns) do + if type(pattern) == "string" then + local trimmed = noctalia.string.trim(pattern) + if trimmed ~= "" and matchesBranch(branch, trimmed) then + return bucket.color + end + end + end + end + end + return nil +end + +local function branchBadge(branch, color, hovered) + local textColor = hovered and "on_tertiary" or color + return ui.row({ + fill = textColor .. "/0.18", + border = textColor .. "/0.32", + borderWidth = 1, + radius = 8, + paddingH = 7, + paddingV = 2, + align = "center", + }, { + ui.label({ text = branch, fontSize = 10, fontWeight = "medium", color = textColor }), + }) end local function statusBox(glyph, message) @@ -63,7 +137,7 @@ end local function hasBlockingStatus() local status = snapshot.status - return status ~= nil and status ~= "ok" and status ~= "loading" + return status ~= nil and status ~= "ok" end local function getSubtitle(group, repo, bio) @@ -95,22 +169,44 @@ local function userRow() local repo = noctalia.getConfig("repo") or "" local subtitle = getSubtitle(group, repo, snapshot.bio) local updatedAt = snapshot.updatedAt - return ui.row({ gap = 10, align = "center" }, { - avatar(), - ui.column({ gap = 2, flexGrow = 1 }, { + + + local children = {} + if snapshot.username ~= "" then + table.insert(children, avatar()) + table.insert(children, ui.column({ gap = 2, flexGrow = 1 }, { ui.label({ text = snapshot.username, fontWeight = "bold", color = "on_surface", maxLines = 1 }), ui.label({ text = subtitle, fontWeight = "thin", color = "on_surface", fontSize = 11, maxLines = 1 }), - }), - ui.column({ gap = 2, align = "end" }, { - ui.label({ text = tr("last_update"), color = "on_surface_variant", fontSize = 10 }), - ui.label({ text = updatedAt ~= "" and updatedAt or tr("last_update_placeholder"), color = "on_surface", fontSize = 11 }), - }), - }) + })) + else + table.insert(children, ui.spacer({ flexGrow = 1 })) + end + table.insert(children, ui.column({ gap = 2, align = "end" }, { + ui.label({ text = tr("last_update"), color = "on_surface_variant", fontSize = 10 }), + ui.label({ text = updatedAt ~= "" and updatedAt or tr("last_update_placeholder"), color = "on_surface", fontSize = 11 }), + })) + return ui.row({ gap = 10, align = "center" }, children) end local function itemCard(item) local key = tostring(item.url or item.ref or item.title) local hovered = hoveredKey == key + + -- Second line: the branch badge, when the target branch matches a configured + -- pattern, then the reference. Issues carry no target branch, so they never + -- get a badge without an explicit check. + local subtitle = {} + local badgeColor = branchColor(item.targetBranch) + if badgeColor then + table.insert(subtitle, branchBadge(item.targetBranch, badgeColor, hovered)) + end + table.insert(subtitle, ui.label({ + text = item.ref or "", + fontSize = 11, + color = hovered and "on_tertiary" or "on_surface_variant", + maxLines = 1, + })) + return ui.column({ key = key, gap = 8, @@ -128,7 +224,7 @@ local function itemCard(item) ui.row({ gap = 10, align = "center" }, { ui.column({ gap = 2, flexGrow = 1 }, { ui.label({ text = item.title or tr("untitled"), color = hovered and "on_tertiary" or "on_surface", fontWeight = "bold", maxLines = 2 }), - ui.label({ text = item.ref or "", fontSize = 11, color = hovered and "on_tertiary" or "on_surface_variant", maxLines = 1 }), + ui.row({ gap = 6, align = "center" }, subtitle), }), ui.glyph({ name = "circle-check", size = 24, color = hovered and "on_tertiary" or "primary", visible = item.detailed_merge_status == "mergeable" }), }), @@ -147,6 +243,24 @@ local function itemList() return rows end +-- Only the PR/MR label depends on the platform, so labels stay per-tab. +local function tabLabel(tab) + if tab.id == "prs" then + local platform = noctalia.getConfig("platform") + local requestLabel = platform == "gitlab" and tr("merge_requests") or tr("pull_requests") + return tr("tab_prs", { label = requestLabel, count = snapshot.prsCount }) + elseif tab.id == "issues" then + return tr("tab_issues", { count = snapshot.issuesCount }) + end + return tr("tab_reviews", { count = snapshot.reviewsCount }) +end + +local TAB_ACTIONS = { + prs = "onTabPrs", + issues = "onTabIssues", + reviews = "onTabReviews", +} + local function tabButton(label, tab, callback) return ui.button({ text = label, @@ -164,8 +278,10 @@ end render = function() local platform = noctalia.getConfig("platform") - local requestLabel = platform == "gitlab" and tr("merge_requests") or tr("pull_requests") local blocked = hasBlockingStatus() + local shown = visibleTabs() + local active = resolveTab(shown) + if active then currentTab = active.id end -- Body: the tabbed list when healthy, a centered status box otherwise. -- The tab row is hidden in the blocking state so the card collapses. @@ -173,14 +289,18 @@ render = function() if blocked then local glyph, message = statusInfo() table.insert(body, statusBox(glyph, message)) + elseif not active then + -- Every tab turned off: nothing to select, so say so rather than render an + -- empty strip above an empty list. + table.insert(body, userRow()) + table.insert(body, statusBox("eye-off", tr("no_tabs"))) else - if snapshot.username ~= "" then - table.insert(body, userRow()) + table.insert(body, userRow()) + local strip = {} + for _, tab in ipairs(shown) do + table.insert(strip, tabButton(tabLabel(tab), tab.id, TAB_ACTIONS[tab.id])) end - table.insert(body, ui.row({ gap = 4, align = "center" }, { - tabButton(tr("tab_prs", { label = requestLabel, count = snapshot.prsCount }), "prs", "onTabPrs"), - tabButton(tr("tab_issues", { count = snapshot.issuesCount }), "issues", "onTabIssues"), - })) + table.insert(body, ui.row({ gap = 4, align = "center" }, strip)) table.insert(body, ui.scroll({ flexGrow = 1, gap = 8, align = "stretch", justify = "start" }, itemList())) end @@ -198,6 +318,7 @@ end function onTabPrs() switchTab("prs") end function onTabIssues() switchTab("issues") end +function onTabReviews() switchTab("reviews") end function onCloseClicked() panel.close() end @@ -208,8 +329,10 @@ end -- Watch for state changes from the service noctalia.state.watch("prs", function(value) snapshot.prs = value or {}; render() end) noctalia.state.watch("issues", function(value) snapshot.issues = value or {}; render() end) +noctalia.state.watch("reviews", function(value) snapshot.reviews = value or {}; render() end) noctalia.state.watch("prs_count", function(value) snapshot.prsCount = value or 0; render() end) noctalia.state.watch("issues_count", function(value) snapshot.issuesCount = value or 0; render() end) +noctalia.state.watch("reviews_count", function(value) snapshot.reviewsCount = value or 0; render() end) noctalia.state.watch("last_update", function(value) snapshot.updatedAt = value or ""; render() end) noctalia.state.watch("status", function(value) snapshot.status = value or "ok"; render() end) noctalia.state.watch("username", function(value) snapshot.username = value or ""; render() end) diff --git a/git_companion/plugin.toml b/git_companion/plugin.toml index cf22aaf3..4be0eea5 100644 --- a/git_companion/plugin.toml +++ b/git_companion/plugin.toml @@ -1,6 +1,6 @@ id = "tphilippot/git_companion" name = "Git Companion" -version = "1.0.0" +version = "1.1.0" plugin_api = 23 author = "thomas-philippot" license = "MIT" @@ -57,6 +57,67 @@ options = [ { value = "both", label_key = "settings.bar_display_mode.options.both" } ] +# Tab visibility. Each list is only fetched when its tab is shown. +[[setting]] +key = "show_prs" +type = "bool" +label_key = "settings.show_prs.label" +description_key = "settings.show_prs.description" +default = true + +[[setting]] +key = "show_issues" +type = "bool" +label_key = "settings.show_issues.label" +description_key = "settings.show_issues.description" +default = true + +[[setting]] +key = "show_reviews" +type = "bool" +label_key = "settings.show_reviews.label" +description_key = "settings.show_reviews.description" +default = true + +# Hidden while the Code Review tab is off, since it would have no effect. +[[setting]] +key = "count_reviews_with_prs" +type = "bool" +label_key = "settings.count_reviews_with_prs.label" +description_key = "settings.count_reviews_with_prs.description" +default = false +visible_when = { key = "show_reviews", values = ["true"] } + +# Branch badges: one list of branch patterns per theme colour. Declaration +# order is match priority — the first bucket holding a matching pattern wins. +[[setting]] +key = "branch_badge_primary" +type = "string_list" +label_key = "settings.branch_badge_primary.label" +description_key = "settings.branch_badge.description" +default = ["develop"] + +[[setting]] +key = "branch_badge_secondary" +type = "string_list" +label_key = "settings.branch_badge_secondary.label" +description_key = "settings.branch_badge.description" +default = ["release/*"] + +[[setting]] +key = "branch_badge_tertiary" +type = "string_list" +label_key = "settings.branch_badge_tertiary.label" +description_key = "settings.branch_badge.description" +default = [] + +[[setting]] +key = "branch_badge_alert" +type = "string_list" +label_key = "settings.branch_badge_alert.label" +description_key = "settings.branch_badge.description" +default = ["master", "main"] + # ── Entryfiles ──────────────────────────────────── [[service]] diff --git a/git_companion/service.luau b/git_companion/service.luau index 72cb3338..365ea287 100644 --- a/git_companion/service.luau +++ b/git_companion/service.luau @@ -31,18 +31,25 @@ end local function buildCommand(kind) local parts = {} if platform == "gitlab" then - local sub = kind == "pr" and "mr" or "issue" + local sub = kind == "issue" and "issue" or "mr" + -- glab lists only open merge requests by default, so "unmerged" is free. + local filter = kind == "review" and "--reviewer=@me" or "--author=@me" table.insert(parts, bin) table.insert(parts, sub) table.insert(parts, "list") for _, v in ipairs(scopeArgs()) do table.insert(parts, v) end - table.insert(parts, "--author=@me") + table.insert(parts, filter) table.insert(parts, "--output") table.insert(parts, "json") else -- GitHub - local sub = kind == "pr" and "prs" or "issues" - local filter = kind == "pr" and "--author=@me" or "--assignee=@me" + local sub = kind == "issue" and "issues" or "prs" + local filter = "--assignee=@me" + if kind == "pr" then + filter = "--author=@me" + elseif kind == "review" then + filter = "--review-requested=@me" + end table.insert(parts, bin) table.insert(parts, "search") table.insert(parts, sub) @@ -59,12 +66,13 @@ end local function normalizeItem(raw, kind) if platform == "gitlab" then - local prefix = kind == "pr" and "!" or "#" + local prefix = kind == "issue" and "#" or "!" return { title = raw.title or "", url = raw.web_url or "", ref = (raw.references and raw.references.full) or (prefix .. (raw.iid or "")), detailed_merge_status = raw.detailed_merge_status or "", + targetBranch = raw.target_branch or "", } end -- GitHub @@ -72,7 +80,8 @@ local function normalizeItem(raw, kind) return { title = raw.title or "", url = raw.url or "", - ref = repoName .. "#" .. (raw.number or "") + ref = repoName .. "#" .. (raw.number or ""), + targetBranch = "", } end @@ -88,13 +97,25 @@ local function processList(kind, output) return list end +-- A hidden tab is never fetched, so its state is emptied instead of keeping a +-- stale count the bar would still display. +local function clearList(kind) + noctalia.state.set(kind .. "s", {}) + noctalia.state.set(kind .. "s_count", 0) +end + local function fetchList(kind) local cmd = buildCommand(kind) noctalia.log("[Git Companion] Running: " .. cmd) noctalia.runAsync(cmd, function(res) + if res.exitCode ~= 0 then + noctalia.log("[Git Companion] " .. kind .. " fetch failed: " .. (res.stderr or "")) + return + end local list = processList(kind, res.stdout) noctalia.state.set(kind .. "s", list) -- "issues" or "prs" noctalia.state.set(kind .. "s_count", #list) + noctalia.state.set("last_update", noctalia.formatTime("%H:%M:%S")) end) end @@ -142,14 +163,25 @@ local function refresh() end -- All preconditions met: the panel can render the lists. Individual fetch - -- failures are surfaced per-list (see fetchList), not by flipping this. + -- failures are logged per-list (see fetchList) and leave the previous list + -- in place, so they don't flip this back. noctalia.state.set("status", "ok") - noctalia.state.set("loading", true) fetchUser() - fetchList("issue") - fetchList("pr") - noctalia.state.set("loading", false) - noctalia.state.set("last_update", noctalia.formatTime("%H:%M:%S")) + + -- Settings are read here rather than at module scope so toggling a tab takes + -- effect on the next tick. show_reviews is the master switch for the Code + -- Review feature: off means no fetch, and count_reviews_with_prs is ignored. + for _, entry in ipairs({ + { kind = "pr", setting = "show_prs" }, + { kind = "issue", setting = "show_issues" }, + { kind = "review", setting = "show_reviews" }, + }) do + if noctalia.getConfig(entry.setting) ~= false then + fetchList(entry.kind) + else + clearList(entry.kind) + end + end end -- Initial fetch diff --git a/git_companion/translations/en.json b/git_companion/translations/en.json index 3b8425e1..aa1820bf 100644 --- a/git_companion/translations/en.json +++ b/git_companion/translations/en.json @@ -6,9 +6,11 @@ "last_update_placeholder": "...", "merge_requests": "Merge Requests", "no_items": "No items", + "no_tabs": "Every tab is hidden. Enable one in the plugin settings.", "pull_requests": "Pull Requests", "tab_issues": "Issues ({count})", "tab_prs": "{label} ({count})", + "tab_reviews": "Code Review ({count})", "title": "Git Companion", "untitled": "Untitled" }, @@ -28,6 +30,25 @@ "prs": "PRs/MRs only" } }, + "branch_badge": { + "description": "Choose which target branch to display in a colored badge. (Github not supported)" + }, + "branch_badge_alert": { + "label": "Badge — alert" + }, + "branch_badge_primary": { + "label": "Badge — primary" + }, + "branch_badge_secondary": { + "label": "Badge — secondary" + }, + "branch_badge_tertiary": { + "label": "Badge — tertiary" + }, + "count_reviews_with_prs": { + "description": "Add reviews to the PR/MR count in the bar. The tooltip always lists both.", + "label": "Count Code Reviews with PRs/MRs" + }, "group": { "description": "Filter by group (GitLab) or owner (GitHub). Leave empty to use repo.", "label": "Group / Owner" @@ -47,11 +68,23 @@ "repo": { "description": "e.g. owner/repo (GitHub) or project path (GitLab). Leave empty to use group/owner.", "label": "Repository" + }, + "show_issues": { + "description": "Show the tab listing the issues assigned to you.", + "label": "Show Issues tab" + }, + "show_prs": { + "description": "Show the tab listing the pull/merge requests you authored.", + "label": "Show PRs/MRs tab" + }, + "show_reviews": { + "description": "Show the tab listing open pull/merge requests awaiting your review.", + "label": "Show Code Review tab" } }, "widget": { "mrs": "MRs", "prs": "PRs", - "tooltip": "{issues} Issues, {prs} {label}" + "tooltip": "{issues} Issues, {prs} {label}, {reviews} to review" } } diff --git a/git_companion/widget.luau b/git_companion/widget.luau index b3d2287d..93ee492c 100644 --- a/git_companion/widget.luau +++ b/git_companion/widget.luau @@ -1,6 +1,6 @@ -- Git Companion Bar Widget -- Shows the platform icon and counts of issues/PRs from the service state. --- This is purely an indicator; the data is displayed on the Desktop Widget. +-- This is purely an indicator; the full lists are displayed in the panel. local function tr(key, args) return noctalia.tr("widget." .. key, args) end @@ -17,18 +17,27 @@ end local function render() local issuesCount = noctalia.state.get("issues_count") or 0 local prsCount = noctalia.state.get("prs_count") or 0 + local reviewsCount = noctalia.state.get("reviews_count") or 0 local platform = noctalia.getConfig("platform") + + -- show_reviews is the master switch, so a count_reviews_with_prs left on + -- cannot fold in a feature the user has turned off. The tooltip below keeps + -- the numbers separate either way. + local barPrsCount = prsCount + if noctalia.getConfig("show_reviews") ~= false and noctalia.getConfig("count_reviews_with_prs") == true then + barPrsCount = prsCount + reviewsCount + end local requestLabel = platform == "gitlab" and tr("mrs") or tr("prs") local mode = noctalia.getConfig("bar_display_mode") or "both" -- Format text based on display mode local text = "" if mode == "both" then - if issuesCount > 0 or prsCount > 0 then - text = string.format("%d/%d", issuesCount, prsCount) + if issuesCount > 0 or barPrsCount > 0 then + text = string.format("%d/%d", issuesCount, barPrsCount) end elseif mode == "prs" then - if prsCount > 0 then text = tostring(prsCount) end + if barPrsCount > 0 then text = tostring(barPrsCount) end elseif mode == "issues" then if issuesCount > 0 then text = tostring(issuesCount) end end @@ -37,7 +46,7 @@ local function render() barWidget.setGlyph(getPlatformIcon()) barWidget.setText(text) - local tooltip = tr("tooltip", { issues = issuesCount, prs = prsCount, label = requestLabel }) + local tooltip = tr("tooltip", { issues = issuesCount, prs = prsCount, label = requestLabel, reviews = reviewsCount }) barWidget.setTooltip(tooltip) end @@ -47,6 +56,7 @@ render() -- Watch for state changes from the service noctalia.state.watch("issues_count", render) noctalia.state.watch("prs_count", render) +noctalia.state.watch("reviews_count", render) function onClick() noctalia.togglePanel("tphilippot/git_companion:main")