Skip to content

feat(calendarium): new Calendarium desklet — clock, sun, moon, zodiac, Wikipedia, holidays#1763

Merged
claudiux merged 12 commits intolinuxmint:masterfrom
KAMI911:calendarium@kami911
Mar 23, 2026
Merged

feat(calendarium): new Calendarium desklet — clock, sun, moon, zodiac, Wikipedia, holidays#1763
claudiux merged 12 commits intolinuxmint:masterfrom
KAMI911:calendarium@kami911

Conversation

@KAMI911
Copy link
Copy Markdown
Contributor

@KAMI911 KAMI911 commented Mar 14, 2026

A new desklet: Calendarium — a feature-rich calendar and information desklet for Cinnamon.

Features

• Date & time — configurable date/time display with multiple format presets (including Hungarian and Japanese) and custom strftime support
• Calendar highlights — day of year, ISO week number, month progress, days until New Year
• Traditional month names — Old Hungarian, Old English (Anglo-Saxon), Old German • Folk calendar sayings — daily sayings in hu, en, de, fr, es, it • Moon phase — symbol, name, and age (days since new moon)
• Sunrise & sunset — calculated from coordinates using a built-in solar algorithm
• Western & Chinese zodiac — icon, text, or both; all 60 Chinese zodiac combinations with emoji
• Name days — hu, en, de, fr, es, it calendars; upcoming days configurable
…, Wikipedia, holidays• National holidays — hu, en, de, fr, es, it; upcoming holidays with public holiday highlight
• Additional cities (up to 3) — local time (HH:MM), UTC offset with DST-correct timezone abbreviation (e.g. UTC+1 (CET)), and sunrise/sunset in city-local time
• Wikipedia integration (optional) — "On This Day" events/births/deaths and Featured Article; configurable item count and rotation interval; automatic English fallback for languages with no content; background English cache pre-warm
• Offline city search — built-in geocoder with IANA timezone lookup (no internet needed) • Translations — de, en, es, fr, hu, it (.po + compiled .mo)

Test plan

  • Desklet loads without errors in Cinnamon
  • Date, time, and all toggle-able sections display correctly
  • City sunrise/sunset shows in city-local time when timezone is set
  • Wikipedia 'On This Day' displays and rotates; falls back to English for unsupported languages
  • Settings changes take effect immediately
  • Translations load for de, en, es, fr, hu, it

KAMI911 added 2 commits March 14, 2026 23:46
…, Wikipedia, holidays

A new desklet: Calendarium — a feature-rich calendar and information desklet for Cinnamon.

Features

• Date & time — configurable date/time display with multiple format presets (including Hungarian and Japanese) and custom strftime support
• Calendar highlights — day of year, ISO week number, month progress, days until New Year
• Traditional month names — Old Hungarian, Old English (Anglo-Saxon), Old German
• Folk calendar sayings — daily sayings in hu, en, de, fr, es, it
• Moon phase — symbol, name, and age (days since new moon)
• Sunrise & sunset — calculated from coordinates using a built-in solar algorithm
• Western & Chinese zodiac — icon, text, or both; all 60 Chinese zodiac combinations with emoji
• Name days — hu, en, de, fr, es, it calendars; upcoming days configurable
• National holidays — hu, en, de, fr, es, it; upcoming holidays with public holiday highlight
• Additional cities (up to 3) — local time (HH:MM), UTC offset with DST-correct timezone abbreviation (e.g. UTC+1 (CET)), and sunrise/sunset in city-local time
• Wikipedia integration (optional) — "On This Day" events/births/deaths and Featured Article; configurable item count and rotation interval; automatic English fallback for languages with no content; background English cache pre-warm
• Offline city search — built-in geocoder with IANA timezone lookup (no internet needed)
• Translations — de, en, es, fr, hu, it (.po + compiled .mo)

Test plan

- Desklet loads without errors in Cinnamon
- Date, time, and all toggle-able sections display correctly
- City sunrise/sunset shows in city-local time when timezone is set
- Wikipedia 'On This Day' displays and rotates; falls back to English for unsupported languages
- Settings changes take effect immediately
- Translations load for de, en, es, fr, hu, it
- Replace all Lang.bind() calls with arrow functions; remove unused Lang import
- Convert load_contents(), replace_contents(), query_info() sync calls
  to their async counterparts in folkdays, namedays, holidays, geocoder
  and wikipedia modules
- Remove query_exists() calls; errors are now caught via try/catch
- Refactor _loadNamedayData() to async with callback; _init() and
  _onSettingChanged() updated accordingly
- Split fetchOnThisDay/fetchFeatured into helper methods (_fetchOnThisDayNet,
  _fetchFeaturedNet) to keep async cache-check chains readable
@github-actions
Copy link
Copy Markdown

Best-practices scanner

This is a regex-based check for API usage that can pose security, performance or
maintainability issues, or that may already be provided by Cinnamon. Having code flagged
by it doesn't automatically disqualify a pull request.

This check is not perfect will not replace a normal review.


Found 21 potential issue(s):

⚠️ lang_bind

calendarium@kami911/files/calendarium@kami911/desklet.js:138

let cb = Lang.bind(this, this._onSettingChanged);

Lang.bind() is deprecated. Use arrow functions (() => {}) or Function.prototype.bind() instead.

calendarium@kami911/files/calendarium@kami911/desklet.js:169

Lang.bind(this, this._onLocationSearchChanged));

Lang.bind() is deprecated. Use arrow functions (() => {}) or Function.prototype.bind() instead.

calendarium@kami911/files/calendarium@kami911/desklet.js:173

Lang.bind(this, function() { this._onCityNameChanged(1); }));

Lang.bind() is deprecated. Use arrow functions (() => {}) or Function.prototype.bind() instead.

calendarium@kami911/files/calendarium@kami911/desklet.js:178

Lang.bind(this, function() { this._onCityNameChanged(2); }));

Lang.bind() is deprecated. Use arrow functions (() => {}) or Function.prototype.bind() instead.

calendarium@kami911/files/calendarium@kami911/desklet.js:183

Lang.bind(this, function() { this._onCityNameChanged(3); }));

Lang.bind() is deprecated. Use arrow functions (() => {}) or Function.prototype.bind() instead.

calendarium@kami911/files/calendarium@kami911/desklet.js:679

60, Lang.bind(this, this._refresh)

Lang.bind() is deprecated. Use arrow functions (() => {}) or Function.prototype.bind() instead.

calendarium@kami911/files/calendarium@kami911/desklet.js:689

1000, Lang.bind(this, this._refreshClock)

Lang.bind() is deprecated. Use arrow functions (() => {}) or Function.prototype.bind() instead.

calendarium@kami911/files/calendarium@kami911/desklet.js:700

1000, Lang.bind(this, this._refreshClock)

Lang.bind() is deprecated. Use arrow functions (() => {}) or Function.prototype.bind() instead.

calendarium@kami911/files/calendarium@kami911/desklet.js:1180

Lang.bind(this, this._onWikiOnThisDay));

Lang.bind() is deprecated. Use arrow functions (() => {}) or Function.prototype.bind() instead.

calendarium@kami911/files/calendarium@kami911/desklet.js:1185

Lang.bind(this, this._onWikiFeatured));

Lang.bind() is deprecated. Use arrow functions (() => {}) or Function.prototype.bind() instead.

⚠️ sync_file_load_contents

calendarium@kami911/files/calendarium@kami911/lib/folkdays.js:31

let [ok, contents] = file.load_contents(null);

Synchronous load_contents() blocks the main loop.
Use load_contents_async() instead.

calendarium@kami911/files/calendarium@kami911/lib/geocoder.js:30

let [ok, contents] = file.load_contents(null);

Synchronous load_contents() blocks the main loop.
Use load_contents_async() instead.

calendarium@kami911/files/calendarium@kami911/lib/holidays.js:53

var [ok, contents] = file.load_contents(null);

Synchronous load_contents() blocks the main loop.
Use load_contents_async() instead.

calendarium@kami911/files/calendarium@kami911/lib/namedays.js:32

let [ok, contents] = file.load_contents(null);

Synchronous load_contents() blocks the main loop.
Use load_contents_async() instead.

calendarium@kami911/files/calendarium@kami911/lib/wikipedia.js:65

let [ok, contents] = file.load_contents(null);

Synchronous load_contents() blocks the main loop.
Use load_contents_async() instead.

⚠️ sync_file_query_exists

calendarium@kami911/files/calendarium@kami911/lib/folkdays.js:29

if (!file.query_exists(null)) return null;

query_exists() is a synchronous call that can block on slow/network filesystems.
Prefer attempting the operation and handling a Gio.IOErrorEnum.NOT_FOUND error instead.

calendarium@kami911/files/calendarium@kami911/lib/holidays.js:51

if (!file.query_exists(null)) return null;

query_exists() is a synchronous call that can block on slow/network filesystems.
Prefer attempting the operation and handling a Gio.IOErrorEnum.NOT_FOUND error instead.

calendarium@kami911/files/calendarium@kami911/lib/wikipedia.js:38

if (!dir.query_exists(null)) {

query_exists() is a synchronous call that can block on slow/network filesystems.
Prefer attempting the operation and handling a Gio.IOErrorEnum.NOT_FOUND error instead.

calendarium@kami911/files/calendarium@kami911/lib/wikipedia.js:51

if (!file.query_exists(null)) return false;

query_exists() is a synchronous call that can block on slow/network filesystems.
Prefer attempting the operation and handling a Gio.IOErrorEnum.NOT_FOUND error instead.

⚠️ sync_file_replace_contents

calendarium@kami911/files/calendarium@kami911/lib/wikipedia.js:78

file.replace_contents(bytes, null, false,

Synchronous replace_contents() blocks the main loop.
Use replace_contents_async() instead.

⚠️ sync_file_query_info

calendarium@kami911/files/calendarium@kami911/lib/wikipedia.js:53

let info  = file.query_info("time::modified",

Synchronous query_info() blocks the main loop.
Use query_info_async() instead.


Automated pattern check.

@OnlineLearningTutorials
Copy link
Copy Markdown
Contributor

@KAMI911 nice desklet
I thought of a desklet which takes whole year and tells what it is day now, tells about day and night duration. And in advance form can tell the azimuth, altitude of sun, moon and all new moon in the year. Thanks for making a desklet which visualizes the time in new way.

@KAMI911
Copy link
Copy Markdown
Contributor Author

KAMI911 commented Mar 18, 2026

@tipichris or @mtwebster It seems there are desklets (this and other in the PRs) to include.

@fredcw
Copy link
Copy Markdown
Contributor

fredcw commented Mar 18, 2026

Text is hard to read with light themes.
image

Also, option "Hide desklet decorations" doesn't seem to make any difference.

KAMI911 added 2 commits March 18, 2026 17:15
…tions

- Add bg-opacity scale setting (0=transparent, 1=solid black) to Appearance
- Always hide desklet frame and header via prevent-decorations metadata
- Remove hide-decorations toggle (no longer needed)
- Fix set_style ordering so background survives _updateDecoration() call
- Store desklet name in _deskletName for reuse
- Deduplicate .pot entries
- Add 'Background opacity' and its tooltip to all .po files
@KAMI911
Copy link
Copy Markdown
Contributor Author

KAMI911 commented Mar 19, 2026

@fredcw : Thank you for the heads-up. I hadn’t tested it with the light desktop setting. I’ve now removed it and applied a black background with opacity. I’ve also removed the non-working header setting. I hope it now works as expected.

What features do you think are missing from this app? Do you have any suggestions for how it could be improved in the future?

@fredcw
Copy link
Copy Markdown
Contributor

fredcw commented Mar 19, 2026

The function _installLocale() isn't needed as cinnamon creates the .mo files automatically when the applet is installed and if the user wants to update their local translations after updating a .po file, they can use cinnamon-xlet-makepot -i <UUID>. Although tbf, it probably doesn't do any harm either.

Something to consider about the readme.md:

Extending Name Days

Any user edits to the desklet's files will be overwritten whenever they update to a new version of the desklet.

KAMI911 added 2 commits March 19, 2026 22:34
Cinnamon installs .mo files automatically; the manual copy IIFE is
unnecessary. README "Extending" sections now point contributors to
open a pull request instead of editing installed desklet files.
@KAMI911 KAMI911 force-pushed the calendarium@kami911 branch from bb835e2 to 83fd360 Compare March 20, 2026 15:01
@github-actions
Copy link
Copy Markdown

Best-practices scanner

This is a regex-based check for API usage that can pose security, performance or
maintainability issues, or that may already be provided by Cinnamon. Having code flagged
by it doesn't automatically disqualify a pull request.

This check is not perfect will not replace a normal review.


Found 1 potential issue(s):

⚠️ hardcoded_data_dir

calendarium@kami911/files/calendarium@kami911/desklet.js:44

Gettext.bindtextdomain(UUID, GLib.get_home_dir() + "/.local/share/locale");

Avoid hardcoding .local/share in paths. Use GLib.get_user_data_dir() instead,
which respects the XDG_DATA_HOME environment variable.


Automated pattern check.

@KAMI911
Copy link
Copy Markdown
Contributor Author

KAMI911 commented Mar 20, 2026

I hope now it is better.

@fredcw
Copy link
Copy Markdown
Contributor

fredcw commented Mar 20, 2026

The wikipedia cache leaves outdated files on disk that it will never use again and won't be replaced for another year. This would amount to about 0.5GB of data over the course of a year. The cache should only store the current day's data, as the desklet considers files more than 12 hours old as out of date anyway.

Also, settings.bindProperty() is deprecated, use settings.bind() instead.

….bind()

- wikipedia.js: add _pruneOldCache() to delete cache files not matching
  today's date on each fetch, preventing unbounded disk growth (~0.5 GB/year)
- desklet.js: replace deprecated settings.bindProperty() with settings.bind()
@github-actions
Copy link
Copy Markdown

Best-practices scanner

This is a regex-based check for API usage that can pose security, performance or
maintainability issues, or that may already be provided by Cinnamon. Having code flagged
by it doesn't automatically disqualify a pull request.

This check is not perfect will not replace a normal review.


Found 1 potential issue(s):

⚠️ sync_file_enumerate_children

calendarium@kami911/files/calendarium@kami911/lib/wikipedia.js:48

let enumerator = dir.enumerate_children(

Synchronous enumerate_children() blocks the main loop.
Use enumerate_children_async() instead.


Automated pattern check.

@KAMI911
Copy link
Copy Markdown
Contributor Author

KAMI911 commented Mar 21, 2026

What is the next step?

@fredcw
Copy link
Copy Markdown
Contributor

fredcw commented Mar 21, 2026

The desklet looks OK now but tbh, AI isn't good enough yet to be able to trust it with writing a desklet without manually reviewing the code to verify that it's correct. Since that doesn't seem to be the case here, it means you're placing the burden on someone else to properly review the code and 0.5GB of unused files in the cache directory is not really a trivial issue.

@claudiux
Copy link
Copy Markdown
Member

@KAMI911 Please remove all unused files.

@claudiux claudiux marked this pull request as draft March 21, 2026 18:07
@KAMI911
Copy link
Copy Markdown
Contributor Author

KAMI911 commented Mar 22, 2026

I see only json files in the cache directory which was download by Wikipedia optional module. Now It is handling the case. I am testing.

@claudiux claudiux marked this pull request as ready for review March 22, 2026 22:10
@KAMI911
Copy link
Copy Markdown
Contributor Author

KAMI911 commented Mar 23, 2026

The old files were removed automatically, only actual files are stored:

~/.cache/calendarium@kami911$ LC_ALL=C ls -l

-rw-rw-r-- 1 kami kami  252489 Mar 23 00:00 featured_2026_en_0323.json
-rw-rw-r-- 1 kami kami    4659 Mar 23 00:00 featured_2026_hu_0323.json
-rw-rw-r-- 1 kami kami 1565014 Mar 23 00:00 onthisday_en_0323.json

@claudiux claudiux merged commit 1537f45 into linuxmint:master Mar 23, 2026
4 checks passed
@fredcw
Copy link
Copy Markdown
Contributor

fredcw commented Mar 23, 2026

IMO, I don't think this should have been merged. It's AI generated, which is fine, but it wasn't checked. The readme also seems like 100% unedited AI. This degrades the spices repo IMO because people then cannot tell if they are reading text written by humans or AI. On youtube for instance, creators must disclose AI generated content so that people know what they're watching. I believe this is important to people and will become more so in the future. Programming mistakes and bugs happen of course, but to not even review the code shows a lack of sufficient care and attention. This means that going forward, all changes to the desklet by @KAMI911 must be assumed to be unchecked and potentially harmful.

@claudiux
Copy link
Copy Markdown
Member

@fredcw
#1773

@KAMI911
Copy link
Copy Markdown
Contributor Author

KAMI911 commented Mar 25, 2026

Why do you think it is harmful? Who will able to review the code?

@KAMI911
Copy link
Copy Markdown
Contributor Author

KAMI911 commented Apr 3, 2026

I added an another PR (#1774).

I also reviewed the code with external tools:

══ 1/2 Semgrep SAST (JS + secrets + OWASP) ══
✔ No findings


┌─────────────┐
│ Scan Status │
└─────────────┘
  Scanning 44 files tracked by git with 582 Code rules:
                                                                                                                        
  Language      Rules   Files          Origin      Rules                                                                
 ─────────────────────────────        ───────────────────                                                               
  <multilang>      39      44          Community     582                                                                
  json              3      22                                                                                           
  js               68      12                                                                                           
                                                                                                                        
                
                
┌──────────────┐
│ Scan Summary │
└──────────────┘
✅ Scan completed successfully.
 • Findings: 0 (0 blocking)
 • Rules run: 110
 • Targets scanned: 44
 • Parsed lines: ~100.0%
 • No ignore information available
Ran 110 rules on 44 files: 0 findings.

══ 2/2 njsscan (Node.js / JavaScript security) ══
✔ No security issues

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.

4 participants