Skip to content

feat(habitica): add Habitica task dashboard#799

Draft
Vasqs wants to merge 2 commits into
noctalia-dev:mainfrom
Vasqs:feat/habitica-plugin
Draft

feat(habitica): add Habitica task dashboard#799
Vasqs wants to merge 2 commits into
noctalia-dev:mainfrom
Vasqs:feat/habitica-plugin

Conversation

@Vasqs
Copy link
Copy Markdown

@Vasqs Vasqs commented May 1, 2026

Summary

Adds habitica, a Noctalia Shell plugin for Habitica users.

The plugin provides:

  • A bar widget with pending due dailies/open todos count
  • A panel with Habitica profile stats, avatar, currency, dailies, todos, and optional habits
  • Task scoring for dailies, todos, habits, and checklist items
  • Settings for Habitica credentials, refresh interval, task limits, tag filtering, checklist display, and theme colorization
  • Local avatar rendering from official Habitica sprite assets
  • A real 960x540 preview generated from the running Noctalia UI

Why

Habitica is a task manager/game used for daily routines and habits. This plugin lets users check and score their current Habitica work directly from Noctalia without opening the web or mobile app.

Testing

  • Validated habitica/manifest.json and habitica/i18n/en.json with python -m json.tool
  • Verified habitica/preview.png is a 960x540 PNG
  • Ran local grep checks matching this repository's code-quality workflow patterns for:
    • hardcoded user-facing text, label, and description strings
    • hardcoded numeric border.width, spacing, pointSize, radius, and margin style fields
    • console.log
  • Ran a local credential scan; it found only code field names and empty defaults, not credential values
  • Smoke-tested the plugin in Noctalia before packaging, including the panel and avatar assembly

Notes

  • settings.json and cache/ are ignored so local Habitica credentials and cached API responses are not published.
  • The standalone source repository is also available at https://github.com/Vasqs/noctalia-habitica.

Noctalia users can now connect Habitica from the shell, see their avatar and stats, inspect active work, and score supported tasks without switching context. The submission follows the registry shape with a real preview image, English strings, README documentation, and local-only credential/cache ignores.

Constraint: The registry requires the manifest repository field to point at noctalia-dev/noctalia-plugins.
Constraint: The preview image must be 16:9 at 960x540.
Rejected: Submit a mock preview | reviewers need a faithful capture of the real plugin UI
Confidence: high
Scope-risk: narrow
Directive: Keep settings.json and cache/ ignored; do not include local Habitica credentials or cached account data.
Tested: JSON validation for manifest.json and i18n/en.json
Tested: preview.png verified as 960x540 PNG generated from a real Noctalia screenshot
Tested: Local grep checks matching the registry code-quality patterns for hardcoded user-facing strings, hardcoded numeric style fields, and console.log
Tested: Credential scan found only code field names and empty defaults, not credential values
Not-tested: Full GitHub Actions run before PR creation
@github-actions
Copy link
Copy Markdown
Contributor

github-actions Bot commented May 1, 2026

Automatic Code Quality Review


File: habitica/BarWidget.qml

  • (L) Line 154: When it comes to translations there is no need for fallback values. From: pluginApi?.tr("example") || "value". To: pluginApi?.tr("example")
+    tooltip += "\n" + (main?.hpText() || pluginApi?.tr("tooltip.hpFallback")) + " - " + (main?.xpText() || pluginApi?.tr("tooltip.xpFallback")) + " - " + (main?.goldText() || pluginApi?.tr("tooltip.goldFallback"))

The automatic code-quality review flagged a low-priority translation fallback pattern. The tooltip fallbacks now assign translated labels to local variables before composing the string, keeping behavior unchanged while satisfying the registry guidance.

Constraint: Address review automation without changing plugin behavior.
Confidence: high
Scope-risk: narrow
Tested: Local grep check for pluginApi.tr fallback expressions
@Vasqs
Copy link
Copy Markdown
Author

Vasqs commented May 1, 2026

Addressed in d394bab: the tooltip translation fallbacks now use local variables before composing the tooltip string, so the flagged pluginApi?.tr(...) || ... pattern is gone.

Copy link
Copy Markdown
Collaborator

@spiros132 spiros132 left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Some feedback about the PR! :D

Comment thread habitica/Settings.qml
root.editColorizationIcon = settings?.colorizationIcon || defaults?.colorizationIcon || "Primary"
root.editColorizationBadge = settings?.colorizationBadge || defaults?.colorizationBadge || "Error"
root.editColorizationBadgeText = settings?.colorizationBadgeText || defaults?.colorizationBadgeText || "Primary"
}
Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Prefer to use property bindings instead of setting them here. For example:

readonly property var cfg: pluginApi?.pluginSettings ?? ({})
readonly property var defaults: pluginApi?.manifest?.metadata?.defaultSettings ?? ({})

property string foo: cfg.foo ?? defaults.foo ?? "Foo"

Comment thread habitica/.gitignore
@@ -0,0 +1,2 @@
settings.json
Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The settings.json file is already included to get ignored in the root of this repository.

Comment thread habitica/Main.qml
if (!isConfigured) {
root.isLoading = false
root.hasError = true
root.errorMessage = "Configure your Habitica User ID and API Token in settings."
Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Shouldn't this be in the translations?

Comment thread habitica/Main.qml

function logDebug(msg) {
if (debugMode) Logger.d("Habitica", msg)
}
Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This function isn't needed since Logger.d only prints it out when debug mode is active.

Comment thread habitica/Main.qml
}

if (!force && lastFetchTimestamp > 0 && nowSeconds() - lastFetchTimestamp < refreshInterval) {
logDebug("Skipping refresh; cache is fresh")
Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

As before you can use the regular Logger.d function here.

Comment thread habitica/Main.qml
if (response.data) {
root.stats = response.data
}
ToastService.showNotice("Habitica task scored")
Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Shouldn't this also be in the translations?

Comment thread habitica/Main.qml
root.tags = cached.tags || []
root.lastFetchTimestamp = cached.timestamp || 0
root.avatarLastFetchTimestamp = cached.avatarTimestamp || 0
logDebug("Loaded Habitica cache")
Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Here as well prefer to use the regular Logger.d functionality.

Comment thread habitica/Main.qml
} catch (e) {
Logger.w("Habitica", "Failed to save cache: " + e)
}
}
Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is it possible to use the pluginSettings as cache instead of having two separate files?

Comment thread habitica/Main.qml
root.fetchAll(true)
}
}
}
Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

As before both this Process and the FileView could be skipped by using the pluginSettings to save the cache.

@spiros132 spiros132 marked this pull request as draft May 14, 2026 11:49
@Vasqs Vasqs marked this pull request as ready for review May 26, 2026 12:00
@Vasqs Vasqs marked this pull request as draft May 26, 2026 12:00
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants