Personal noctalia plugins collection

feat: fork with location display and event creation

- Show event location on calendar cards when space permits
- Add "+" button to create new events via EDS Python script
- Add event creation dialog with summary, date, time, location,
description and calendar selection
- Add create-event.py script using ECal.Client for EDS integration
- Update en.json and zh-CN.json with new translation keys
- Update manifest and registry to point to forked repository

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>

+350 -886
+5 -879
registry.json
··· 2 2 "version": 1, 3 3 "plugins": [ 4 4 { 5 - "id": "activate-linux", 6 - "name": "Activate Linux Watermark", 7 - "version": "1.1.0", 8 - "official": false, 9 - "author": "Preston Corless (pgattic)", 10 - "description": "Adds a watermark to the bottom-right of the screen similar to the one found on unactivated Windows 10/11", 11 - "repository": "https://github.com/noctalia-dev/noctalia-plugins", 12 - "license": "MIT", 13 - "tags": [ 14 - "Desktop", 15 - "Fun" 16 - ], 17 - "lastUpdated": "2026-02-04T23:08:01-07:00" 18 - }, 19 - { 20 - "id": "assistant-panel", 21 - "name": "Assistant Panel", 22 - "version": "2.1.3", 23 - "official": false, 24 - "author": "j-1in", 25 - "description": "AI Chat and Translation panel", 26 - "repository": "https://github.com/noctalia-dev/noctalia-plugins", 27 - "minNoctaliaVersion": "4.1.2", 28 - "license": "MIT", 29 - "tags": [ 30 - "Bar", 31 - "Panel", 32 - "AI", 33 - "Productivity", 34 - "Network" 35 - ], 36 - "lastUpdated": "2026-02-05T21:36:32+11:00" 37 - }, 38 - { 39 - "id": "battery-actions", 40 - "name": "Battery Actions", 41 - "version": "1.0.1", 42 - "official": false, 43 - "author": "itscrystalline", 44 - "description": "A plugin that allows you to run custom actions when battery state changes.", 45 - "repository": "https://github.com/noctalia-dev/noctalia-plugins", 46 - "minNoctaliaVersion": "4.4.0", 47 - "license": "MIT", 48 - "tags": [ 49 - "System" 50 - ], 51 - "lastUpdated": "2026-02-26T19:55:06+01:00" 52 - }, 53 - { 54 - "id": "battery-threshold", 55 - "name": "Battery Threshold Control", 56 - "version": "1.2.0", 57 - "official": false, 58 - "author": "Wilfred Mallawa", 59 - "description": "Set the battery threshold for laptop batteries to extend battery lifespan", 60 - "repository": "https://github.com/noctalia-dev/noctalia-plugins", 61 - "minNoctaliaVersion": "3.6.0", 62 - "license": "MIT", 63 - "tags": [ 64 - "Bar", 65 - "Panel", 66 - "System" 67 - ], 68 - "lastUpdated": "2026-01-31T13:58:49+07:00" 69 - }, 70 - { 71 - "id": "calibre-provider", 72 - "name": "Calibre Provider", 73 - "version": "1.2.0", 74 - "official": false, 75 - "author": "Krendil", 76 - "description": "Search for books in your Calibre library", 77 - "repository": "https://github.com/noctalia-dev/noctalia-plugins", 78 - "minNoctaliaVersion": "4.4.1", 79 - "license": "MIT", 80 - "tags": [ 81 - "Launcher" 82 - ], 83 - "lastUpdated": "2026-02-23T12:55:52+10:00" 84 - }, 85 - { 86 - "id": "catwalk", 87 - "name": "Catwalk", 88 - "version": "1.1.6", 89 - "official": false, 90 - "author": "MannuVilasara", 91 - "description": "A cute animated cat for your bar.", 92 - "repository": "https://github.com/noctalia-dev/noctalia-plugins", 93 - "minNoctaliaVersion": "3.6.0", 94 - "license": "MIT", 95 - "tags": [ 96 - "Bar", 97 - "Desktop", 98 - "Panel", 99 - "Fun" 100 - ], 101 - "lastUpdated": "2026-02-04T20:40:31-05:00" 102 - }, 103 - { 104 - "id": "clipper", 105 - "name": "Clipper", 106 - "version": "2.1.0", 107 - "official": false, 108 - "author": "blackbartblues", 109 - "description": "Advanced clipboard manager with history, search, keyboard navigation, ToDo integration, pinned items, notecards/sticky notes, and selection-to-notecard feature. Fully translated with comprehensive i18n support.", 110 - "repository": "https://github.com/blackbartblues/noctalia-clipper", 111 - "minNoctaliaVersion": "4.1.2", 112 - "license": "MIT", 113 - "tags": [ 114 - "Utility", 115 - "Bar", 116 - "Panel" 117 - ], 118 - "lastUpdated": "2026-02-23T20:48:07-05:00" 119 - }, 120 - { 121 - "id": "color-scheme-creator", 122 - "name": "Color Scheme Creator", 123 - "version": "1.0.1", 124 - "official": true, 125 - "author": "Noctalia Team", 126 - "description": "Create and manage custom predefined color schemes with a visual color editor.", 127 - "repository": "https://github.com/noctalia-dev/noctalia-plugins", 128 - "minNoctaliaVersion": "4.5.1", 129 - "license": "MIT", 130 - "tags": [ 131 - "Theming", 132 - "Utility" 133 - ], 134 - "lastUpdated": "2026-02-24T17:49:23-05:00" 135 - }, 136 - { 137 - "id": "currency-exchange", 138 - "name": "Currency Exchange", 139 - "version": "1.0.2", 140 - "official": false, 141 - "author": "balor", 142 - "description": "Currency conversion utility via launcher and bar widget", 143 - "repository": "https://github.com/noctalia-dev/noctalia-plugins", 144 - "minNoctaliaVersion": "4.4.1", 145 - "license": "MIT", 146 - "tags": [ 147 - "Launcher", 148 - "Utility" 149 - ], 150 - "lastUpdated": "2026-02-10T10:12:36-05:00" 151 - }, 152 - { 153 - "id": "dns-switcher", 154 - "name": "DNS Switcher", 155 - "version": "1.2.0", 156 - "official": false, 157 - "author": "Ronin-CK", 158 - "description": "DNS Manager with custom server support for Noctalia.", 159 - "repository": "https://github.com/noctalia-dev/noctalia-plugins", 160 - "minNoctaliaVersion": "4.0.0", 161 - "license": "MIT", 162 - "tags": [ 163 - "Bar", 164 - "Network" 165 - ], 166 - "lastUpdated": "2026-02-25T15:40:48+05:30" 167 - }, 168 - { 169 - "id": "fancy-audiovisualizer", 170 - "name": "Fancy Audiovisualizer", 171 - "version": "1.0.8", 172 - "official": true, 173 - "author": "Noctalia Team", 174 - "description": "Lemmy's fancy circular audio visualizer.", 175 - "repository": "https://github.com/noctalia-dev/noctalia-plugins", 176 - "minNoctaliaVersion": "3.7.2", 177 - "license": "MIT", 178 - "tags": [ 179 - "Desktop", 180 - "Audio" 181 - ], 182 - "lastUpdated": "2026-02-17T14:33:04-05:00" 183 - }, 184 - { 185 - "id": "file-search", 186 - "name": "File Search", 187 - "version": "1.0.0", 188 - "official": false, 189 - "author": "ericbreh", 190 - "description": "File search using fd, integrated into the launcher", 191 - "repository": "https://github.com/noctalia-dev/noctalia-plugins", 192 - "minNoctaliaVersion": "4.1.2", 193 - "license": "MIT", 194 - "tags": [ 195 - "Launcher", 196 - "Productivity" 197 - ], 198 - "lastUpdated": "2026-02-10T12:24:50-08:00" 199 - }, 200 - { 201 - "id": "github-feed", 202 - "name": "GitHub Feed", 203 - "version": "1.2.0", 204 - "official": false, 205 - "author": "linuxmobile", 206 - "description": "Display GitHub activity from users you follow and activity on your repos", 207 - "repository": "https://github.com/noctalia-dev/noctalia-plugins", 208 - "minNoctaliaVersion": "3.6.0", 209 - "license": "MIT", 210 - "tags": [ 211 - "Bar", 212 - "Panel", 213 - "Development", 214 - "Network" 215 - ], 216 - "lastUpdated": "2026-02-23T00:37:30+01:00" 217 - }, 218 - { 219 - "id": "hello-world", 220 - "name": "Hello World", 221 - "version": "1.1.1", 222 - "official": true, 223 - "author": "Noctalia Team", 224 - "description": "A simple Hello World plugin demonstrating functionalities. For developers only.", 225 - "repository": "https://github.com/noctalia-dev/noctalia-plugins", 226 - "minNoctaliaVersion": "4.1.2", 227 - "license": "MIT", 228 - "tags": [ 229 - "Development" 230 - ], 231 - "lastUpdated": "2026-02-07T19:13:14+01:00" 232 - }, 233 - { 234 - "id": "hyprland-steam-overlay", 235 - "name": "Steam Overlay (Hyprland)", 236 - "version": "2.1.1", 237 - "official": false, 238 - "author": "blacku", 239 - "description": "Steam overlay with automatic window management for Hyprland. Automatically moves all Steam windows (except fullscreen games) to overlay workspace as floating windows. Main 3 windows (Friends, Client, Chat) are positioned in a row. Additional windows are brought to top. If new windows don't appear on top, toggle overlay off/on (Super+S twice). Fully responsive with percentage-based layout. Requires Hyprland window manager.", 240 - "repository": "https://github.com/noctalia-dev/noctalia-plugins", 241 - "minNoctaliaVersion": "4.1.2", 242 - "license": "MIT", 243 - "tags": [], 244 - "lastUpdated": "2026-01-29T22:32:10+01:00" 245 - }, 246 - { 247 - "id": "ideapad-battery-health", 248 - "name": "Ideapad Battery Health", 249 - "version": "1.0.0", 250 - "official": false, 251 - "author": "Christophe Branchereau", 252 - "description": "Set the battery charging mode for ideapad laptop batteries, to extend battery lifespan", 253 - "repository": "https://github.com/noctalia-dev/noctalia-plugins", 254 - "minNoctaliaVersion": "3.6.0", 255 - "license": "MIT", 256 - "tags": [ 257 - "Bar", 258 - "Panel", 259 - "System" 260 - ], 261 - "lastUpdated": "2026-02-17T15:50:12+01:00" 262 - }, 263 - { 264 - "id": "ip-monitor", 265 - "name": "IP Monitor", 266 - "version": "0.0.1", 267 - "official": false, 268 - "author": "deepalpha", 269 - "description": "Plugin showing current external IP", 270 - "repository": "https://github.com/noctalia-dev/noctalia-plugins", 271 - "minNoctaliaVersion": "4.4.3", 272 - "license": "MIT", 273 - "tags": [ 274 - "Development" 275 - ], 276 - "lastUpdated": "2026-02-12T08:50:25+01:00" 277 - }, 278 - { 279 - "id": "kagi-quick-search", 280 - "name": "Kagi Quick Search", 281 - "version": "1.0.1", 282 - "official": false, 283 - "author": "Kainoa Kanter", 284 - "description": "Get AI answers from Kagi in your launcher", 285 - "repository": "https://github.com/noctalia-dev/noctalia-plugins", 286 - "minNoctaliaVersion": "4.4.1", 287 - "license": "MIT", 288 - "tags": [ 289 - "Launcher", 290 - "Productivity" 291 - ], 292 - "lastUpdated": "2026-02-10T10:12:36-05:00" 293 - }, 294 - { 295 - "id": "kaomoji-provider", 296 - "name": "Kaomoji Provider", 297 - "version": "1.0.3", 298 - "official": true, 299 - "author": "Noctalia Team", 300 - "description": "Browse and search kaomoji emoticons from the launcher", 301 - "repository": "https://github.com/noctalia-dev/noctalia-plugins", 302 - "minNoctaliaVersion": "4.4.1", 303 - "license": "MIT", 304 - "tags": [ 305 - "Launcher", 306 - "Fun" 307 - ], 308 - "lastUpdated": "2026-02-10T10:12:36-05:00" 309 - }, 310 - { 311 - "id": "kde-connect", 312 - "name": "KDE Connect", 313 - "version": "1.0.2", 314 - "official": false, 315 - "author": "WerWolv", 316 - "description": "A Plugin integrating your mobile devices into a panel using KDEConnect", 317 - "repository": "https://github.com/WerWolv/noctalia-kde-connect", 318 - "minNoctaliaVersion": "4.4.0", 319 - "license": "GPLv2", 320 - "tags": [ 321 - "Bar", 322 - "Panel", 323 - "Utility", 324 - "System" 325 - ], 326 - "lastUpdated": "2026-02-20T20:36:40+01:00" 327 - }, 328 - { 329 - "id": "keybind-cheatsheet", 330 - "name": "Keybind Cheatsheet", 331 - "version": "3.2.2", 332 - "official": false, 333 - "author": "blacku", 334 - "description": "Universal keyboard shortcuts keymap that automatically detects and displays keybindings for Hyprland or Niri compositors.", 335 - "minNoctaliaVersion": "3.6.0", 336 - "license": "MIT", 337 - "tags": [], 338 - "lastUpdated": "2026-02-08T21:44:29+01:00" 339 - }, 340 - { 341 - "id": "mangowc-layout-switcher", 342 - "name": "Mangowc Layout Switcher", 343 - "version": "1.1.4", 344 - "official": false, 345 - "author": "atheeq-rhxn", 346 - "description": "Switch between different mangowc layouts", 347 - "repository": "https://github.com/noctalia-dev/noctalia-plugins", 348 - "minNoctaliaVersion": "3.6.0", 349 - "license": "MIT", 350 - "tags": [ 351 - "Bar", 352 - "Panel", 353 - "MangoWC" 354 - ], 355 - "lastUpdated": "2026-02-28T01:32:51+05:30" 356 - }, 357 - { 358 - "id": "mawaqit", 359 - "name": "Mawaqit", 360 - "version": "1.2.1", 361 - "official": false, 362 - "author": "User", 363 - "description": "Shows prayer times and a countdown to the next prayer. Plays azan at prayer time.", 364 - "minNoctaliaVersion": "4.1.0", 365 - "license": "MIT", 366 - "tags": [ 367 - "Bar", 368 - "Panel" 369 - ], 370 - "lastUpdated": "2026-02-27T21:53:04+01:00" 371 - }, 372 - { 373 - "id": "mini-docker", 374 - "name": "Mini Docker", 375 - "version": "2.1.2", 376 - "official": false, 377 - "author": "MannuVilasara", 378 - "description": "Manage Docker containers, images, volumes & networks", 379 - "repository": "https://github.com/noctalia-dev/noctalia-plugins", 380 - "minNoctaliaVersion": "3.6.0", 381 - "license": "MIT", 382 - "tags": [ 383 - "Bar", 384 - "Panel", 385 - "Development" 386 - ], 387 - "lastUpdated": "2026-01-26T23:59:29-05:00" 388 - }, 389 - { 390 - "id": "model-usage", 391 - "name": "Model Usage", 392 - "version": "0.2.0", 393 - "official": false, 394 - "author": "cmptr", 395 - "description": "Shows AI coding assistant usage stats in the bar with detail panel (Claude Code, Codex, OpenRouter, Zen)", 396 - "repository": "https://github.com/noctalia-dev/noctalia-plugins", 397 - "minNoctaliaVersion": "3.6.0", 398 - "license": "MIT", 399 - "tags": [ 400 - "Bar", 401 - "Productivity", 402 - "AI" 403 - ], 404 - "lastUpdated": "2026-02-25T19:27:50-06:00" 405 - }, 406 - { 407 - "id": "mpris-lyric", 408 - "name": "MPRIS Lyric", 409 - "version": "1.0.2", 410 - "official": false, 411 - "author": "DBeidachazi", 412 - "description": "Display synchronized lyrics from MPRIS-compatible music players (e.g., go-musicfox) in the bar.", 413 - "repository": "https://github.com/noctalia-dev/noctalia-plugins", 414 - "minNoctaliaVersion": "3.8.0", 415 - "license": "MIT", 416 - "tags": [ 417 - "Bar", 418 - "Music" 419 - ], 420 - "lastUpdated": "2026-02-23T20:48:07-05:00" 421 - }, 422 - { 423 - "id": "mpvpaper", 424 - "name": "Mpvpaper", 425 - "version": "1.6.2", 426 - "official": false, 427 - "author": "Spyridon Siarapis", 428 - "description": "A plugin that allows having video wallpapers using mpvpaper.", 429 - "repository": "https://github.com/noctalia-dev/noctalia-plugins", 430 - "minNoctaliaVersion": "3.6.0", 431 - "license": "MIT", 432 - "tags": [ 433 - "Bar", 434 - "Panel", 435 - "Fun", 436 - "System" 437 - ], 438 - "lastUpdated": "2026-02-09T20:15:29+01:00" 439 - }, 440 - { 441 - "id": "netbird", 442 - "name": "NetBird", 443 - "version": "1.0.0", 444 - "official": false, 445 - "author": "Cleboost", 446 - "description": "Show NetBird VPN status in the menu bar.", 447 - "repository": "https://github.com/noctalia-dev/noctalia-plugins", 448 - "minNoctaliaVersion": "4.0.0", 449 - "license": "MIT", 450 - "tags": [ 451 - "Bar", 452 - "Network", 453 - "Panel" 454 - ], 455 - "lastUpdated": "2026-02-13T15:08:22+01:00" 456 - }, 457 - { 458 - "id": "network-indicator", 459 - "name": "Network Indicator", 460 - "version": "1.0.5", 461 - "official": false, 462 - "author": "tonigineer", 463 - "description": "A `lively` network traffic indicator.", 464 - "repository": "https://github.com/noctalia-dev/noctalia-plugins", 465 - "minNoctaliaVersion": "3.7.5", 466 - "license": "MIT", 467 - "tags": [ 468 - "Bar", 469 - "Network", 470 - "Indicator" 471 - ], 472 - "lastUpdated": "2026-01-26T23:59:29-05:00" 473 - }, 474 - { 475 - "id": "network-manager-vpn", 476 - "name": "Network Manager VPN", 477 - "version": "1.1.0", 478 - "official": false, 479 - "author": "nZO", 480 - "description": "Connect to VPN via NetworkManager", 481 - "repository": "https://github.com/noctalia-dev/noctalia-plugins", 482 - "minNoctaliaVersion": "3.6.0", 483 - "license": "MIT", 484 - "tags": [ 485 - "Bar", 486 - "Panel", 487 - "Network" 488 - ], 489 - "lastUpdated": "2026-02-23T22:04:26+01:00" 490 - }, 491 - { 492 - "id": "news", 493 - "name": "News Bar", 494 - "version": "1.2.2", 495 - "official": false, 496 - "author": "LazarH", 497 - "description": "Display scrolling news headlines from various sources using NewsAPI.org", 498 - "repository": "https://github.com/noctalia-dev/noctalia-plugins", 499 - "minNoctaliaVersion": "3.6.0", 500 - "license": "MIT", 501 - "tags": [ 502 - "Bar", 503 - "Panel", 504 - "Network", 505 - "Fun" 506 - ], 507 - "lastUpdated": "2026-02-22T10:29:46+02:00" 508 - }, 509 - { 510 - "id": "niri-overview-launcher", 511 - "name": "Niri Overview Launcher", 512 - "version": "1.0.0", 513 - "official": false, 514 - "author": "eliahreeves", 515 - "description": "Opens the launcher when typing in niri's overview mode", 516 - "repository": "https://github.com/noctalia-dev/noctalia-plugins", 517 - "minNoctaliaVersion": "4.1.2", 518 - "license": "MIT", 519 - "tags": [ 520 - "System" 521 - ], 522 - "lastUpdated": "2026-02-05T11:41:54-08:00" 523 - }, 524 - { 525 - "id": "noctalia-supergfxctl", 526 - "name": "SuperGFX Control", 527 - "version": "0.0.3", 528 - "official": false, 529 - "author": "cod3d <cod3ddot@proton.me>", 530 - "description": "GPU control with supergfxctl for noctalia.", 531 - "repository": "https://github.com/noctalia-dev/noctalia-plugins", 532 - "minNoctaliaVersion": "3.8.2", 533 - "license": "MIT", 534 - "tags": [ 535 - "Bar", 536 - "Panel", 537 - "System" 538 - ], 539 - "lastUpdated": "2026-02-23T20:48:07-05:00" 540 - }, 541 - { 542 - "id": "notes-scratchpad", 543 - "name": "Notes Scratchpad", 544 - "version": "1.1.3", 545 - "official": false, 546 - "author": "apt-get", 547 - "description": "A simple scratchpad for quick notes.", 548 - "repository": "https://github.com/noctalia-dev/noctalia-plugins", 549 - "minNoctaliaVersion": "3.7.1", 550 - "license": "MIT", 551 - "tags": [ 552 - "Bar", 553 - "Panel", 554 - "Productivity" 555 - ], 556 - "lastUpdated": "2026-02-26T13:39:10-05:00" 557 - }, 558 - { 559 - "id": "openhue", 560 - "name": "Openhue widget", 561 - "version": "1.0.1", 562 - "official": false, 563 - "author": "alxndrv", 564 - "description": "Plugin for controlling Philips Hue lights from the taskbar", 565 - "repository": "https://github.com/noctalia-dev/noctalia-plugins", 566 - "minNoctaliaVersion": "3.6.0", 567 - "license": "MIT", 568 - "tags": [ 569 - "Bar", 570 - "Panel" 571 - ], 572 - "lastUpdated": "2026-01-26T23:59:29-05:00" 573 - }, 574 - { 575 - "id": "polkit-agent", 576 - "name": "Polkit Agent", 577 - "version": "1.0.1", 578 - "official": true, 579 - "author": "Noctalia Team <team@noctalia.dev>", 580 - "description": "Provides a Polkit authentication agent (requires quickshell-git).", 581 - "repository": "https://github.com/noctalia-dev/noctalia-plugins", 582 - "minNoctaliaVersion": "4.4.3", 583 - "license": "MIT", 584 - "tags": [ 585 - "System", 586 - "Security" 587 - ], 588 - "lastUpdated": "2026-02-15T22:18:12+01:00" 589 - }, 590 - { 591 - "id": "pomodoro", 592 - "name": "Pomodoro", 593 - "version": "1.2.0", 594 - "official": false, 595 - "author": "notprayasmitra", 596 - "description": "A pomodoro timer plugin to help boost productivity.", 597 - "repository": "https://github.com/noctalia-dev/noctalia-plugins", 598 - "minNoctaliaVersion": "4.0.0", 599 - "license": "MIT", 600 - "tags": [ 601 - "Bar", 602 - "Productivity" 603 - ], 604 - "lastUpdated": "2026-02-01T21:52:23+05:30" 605 - }, 606 - { 607 - "id": "privacy-indicator", 608 - "name": "Privacy Indicator", 609 - "version": "1.2.5", 610 - "official": true, 611 - "author": "Noctalia Team", 612 - "description": "A privacy indicator widget that shows when microphone, camera or screen sharing is active.", 613 - "repository": "https://github.com/noctalia-dev/noctalia-plugins", 614 - "minNoctaliaVersion": "3.6.0", 615 - "license": "MIT", 616 - "tags": [ 617 - "Bar", 618 - "Privacy", 619 - "Indicator" 620 - ], 621 - "lastUpdated": "2026-02-26T19:19:12+01:00" 622 - }, 623 - { 624 - "id": "ramadan-iftar", 625 - "name": "Ramadan Iftar", 626 - "version": "1.0.2", 627 - "official": false, 628 - "author": "User", 629 - "description": "Shows prayer times and a countdown to Iftar during Ramadan.", 630 - "minNoctaliaVersion": "4.1.0", 631 - "license": "MIT", 632 - "tags": [ 633 - "Bar", 634 - "Panel" 635 - ], 636 - "lastUpdated": "2026-02-19T09:33:50-05:00" 637 - }, 638 - { 639 - "id": "rss-feed", 640 - "name": "RSS Feed Reader", 641 - "version": "1.0.3", 642 - "official": false, 643 - "author": "Lokize", 644 - "description": "Monitor and read RSS/Atom feeds directly from your desktop", 645 - "repository": "https://github.com/noctalia-dev/noctalia-plugins", 646 - "minNoctaliaVersion": "3.6.0", 647 - "license": "MIT", 648 - "tags": [], 649 - "lastUpdated": "2026-01-26T23:59:29-05:00" 650 - }, 651 - { 652 - "id": "screen-recorder", 653 - "name": "Screen Recorder", 654 - "version": "1.1.7", 655 - "official": true, 656 - "author": "Noctalia Team", 657 - "description": "Hardware-accelerated screen recording using gpu-screen-recorder with customizable video and audio settings", 658 - "repository": "https://github.com/noctalia-dev/noctalia-plugins", 659 - "minNoctaliaVersion": "3.6.0", 660 - "license": "MIT", 661 - "tags": [ 662 - "Bar", 663 - "Utility" 664 - ], 665 - "lastUpdated": "2026-02-10T01:17:08+03:00" 666 - }, 667 - { 668 - "id": "screenshot", 669 - "name": "Screenshot", 670 - "version": "1.0.1", 671 - "official": false, 672 - "author": "Cleboost", 673 - "description": "Quick screenshot button in bar for Hyprland, Sway, and Niri", 674 - "repository": "https://github.com/noctalia-dev/noctalia-plugins", 675 - "minNoctaliaVersion": "3.6.0", 676 - "license": "MIT", 677 - "tags": [ 678 - "Bar", 679 - "Utility" 680 - ], 681 - "lastUpdated": "2026-02-19T17:33:45-05:00" 682 - }, 683 - { 684 - "id": "simple-notes", 685 - "name": "Simple Notes", 686 - "version": "1.0.3", 687 - "official": false, 688 - "author": "fusuyfusuy", 689 - "description": "A simple note taking plugin for Noctalia Shell.", 690 - "repository": "https://github.com/noctalia-dev/noctalia-plugins", 691 - "minNoctaliaVersion": "3.7.1", 692 - "license": "MIT", 693 - "tags": [ 694 - "Bar", 695 - "Panel", 696 - "Productivity" 697 - ], 698 - "lastUpdated": "2026-01-26T23:59:29-05:00" 699 - }, 700 - { 701 - "id": "steam-price-watcher", 702 - "name": "Steam Price Watcher", 703 - "version": "1.0.5", 704 - "official": false, 705 - "author": "Lokize", 706 - "description": "Monitor Steam game prices and get notified when they reach your target price", 707 - "repository": "https://github.com/noctalia-dev/noctalia-plugins", 708 - "minNoctaliaVersion": "3.6.0", 709 - "license": "MIT", 710 - "tags": [], 711 - "lastUpdated": "2026-01-27T07:21:12-03:00" 712 - }, 713 - { 714 - "id": "sticky-notes", 715 - "name": "Sticky Notes", 716 - "version": "0.0.1", 717 - "official": false, 718 - "author": "sapjax", 719 - "description": "A local quick notes plugin with Markdown support.", 720 - "repository": "https://github.com/noctalia-dev/noctalia-plugins", 721 - "minNoctaliaVersion": "3.6.0", 722 - "license": "MIT", 723 - "tags": [ 724 - "Bar", 725 - "Panel", 726 - "Productivity" 727 - ], 728 - "lastUpdated": "2026-02-23T15:20:02+08:00" 729 - }, 730 - { 731 - "id": "tailscale", 732 - "name": "Tailscale", 733 - "version": "1.1.2", 734 - "official": false, 735 - "author": "nineluj", 736 - "description": "Show Tailscale status in the menu bar.", 737 - "repository": "https://github.com/noctalia-dev/noctalia-plugins", 738 - "minNoctaliaVersion": "4.0.0", 739 - "license": "MIT", 740 - "tags": [ 741 - "Bar", 742 - "Network", 743 - "Panel" 744 - ], 745 - "lastUpdated": "2026-02-14T20:25:29+01:00" 746 - }, 747 - { 748 - "id": "timer", 749 - "name": "Timer", 750 - "version": "1.1.0", 751 - "official": true, 752 - "author": "Noctalia Team", 753 - "description": "A timer and stopwatch plugin for the bar & control center.", 754 - "repository": "https://github.com/noctalia-dev/noctalia-plugins", 755 - "minNoctaliaVersion": "4.4.4", 756 - "license": "MIT", 757 - "tags": [ 758 - "Bar", 759 - "Utility" 760 - ], 761 - "lastUpdated": "2026-02-17T08:29:13-05:00" 762 - }, 763 - { 764 - "id": "todo", 765 - "name": "Todo List", 766 - "version": "1.9.4", 767 - "official": false, 768 - "author": "lonerOrz <lonerOrz@qq.com>", 769 - "description": "A simple todo list manager plugin for Noctalia Shell.", 770 - "repository": "https://github.com/noctalia-dev/noctalia-plugins", 771 - "minNoctaliaVersion": "3.7.1", 772 - "license": "MIT", 773 - "tags": [ 774 - "Bar", 775 - "Desktop", 776 - "Panel", 777 - "Productivity" 778 - ], 779 - "lastUpdated": "2026-02-21T20:24:43+08:00" 780 - }, 781 - { 782 - "id": "translator", 783 - "name": "Translator", 784 - "version": "1.2.3", 785 - "official": false, 786 - "author": "Cleboost", 787 - "description": "Quick translate in launcher", 788 - "repository": "https://github.com/noctalia-dev/noctalia-plugins", 789 - "minNoctaliaVersion": "4.4.1", 790 - "license": "MIT", 791 - "tags": [ 792 - "Launcher" 793 - ], 794 - "lastUpdated": "2026-02-10T10:12:36-05:00" 795 - }, 796 - { 797 - "id": "unicode-picker", 798 - "name": "Unicode Picker", 799 - "version": "1.0.2", 800 - "official": false, 801 - "author": "Daddeffe", 802 - "description": "Browse and search Unicode characters from the launcher", 803 - "repository": "https://github.com/noctalia-dev/noctalia-plugins", 804 - "minNoctaliaVersion": "4.4.1", 805 - "license": "MIT", 806 - "tags": [ 807 - "Launcher", 808 - "Utility" 809 - ], 810 - "lastUpdated": "2026-02-10T10:12:36-05:00" 811 - }, 812 - { 813 - "id": "update-count", 814 - "name": "Update Count", 815 - "version": "1.0.12", 816 - "official": false, 817 - "author": "BukoMoon", 818 - "description": "Checks for system updates and shows the update count. Click to run update command in a terminal.", 819 - "repository": "https://github.com/noctalia-dev/noctalia-plugins", 820 - "minNoctaliaVersion": "3.6.0", 821 - "license": "GPLv3", 822 - "tags": [ 823 - "Bar", 824 - "System" 825 - ], 826 - "lastUpdated": "2026-02-05T21:01:51-05:00" 827 - }, 828 - { 829 - "id": "video-wallpaper", 830 - "name": "Video Wallpaper", 831 - "version": "2.0.2", 832 - "official": false, 833 - "author": "Spyridon Siarapis", 834 - "description": "A plugin that uses a backend renderer to play videos as your wallpaper.", 835 - "repository": "https://github.com/noctalia-dev/noctalia-plugins", 836 - "minNoctaliaVersion": "3.6.0", 837 - "license": "MIT", 838 - "tags": [ 839 - "Bar", 840 - "Panel", 841 - "Fun", 842 - "System" 843 - ], 844 - "lastUpdated": "2026-02-20T12:04:37+01:00" 845 - }, 846 - { 847 - "id": "weather-indicator", 848 - "name": "Weather Indicator", 849 - "version": "1.0.9", 850 - "official": false, 851 - "author": "Sovereign", 852 - "description": "Shows the current weather condition and tempurature.", 853 - "repository": "https://github.com/noctalia-dev/noctalia-plugins", 854 - "minNoctaliaVersion": "4.3.0", 855 - "license": "MIT", 856 - "tags": [ 857 - "Bar" 858 - ], 859 - "lastUpdated": "2026-02-25T18:02:47-05:00" 860 - }, 861 - { 862 5 "id": "weekly-calendar", 863 6 "name": "Weekly Calendar", 864 - "version": "1.0.4", 7 + "version": "1.1.0", 865 8 "official": false, 866 9 "author": "dodaars", 867 - "description": "A weekly calendar plugin complementing Noctalia's inbuilt calendar service.", 868 - "repository": "https://github.com/noctalia-dev/noctalia-plugins", 10 + "description": "A weekly calendar plugin with location display and event creation via EDS.", 11 + "repository": "https://github.com/DzmingLi/noctalia-weekly-calendar", 869 12 "minNoctaliaVersion": "4.2.3", 870 13 "license": "MIT", 871 - "tags": [ 872 - "Bar", 873 - "Panel", 874 - "Productivity" 875 - ], 876 - "lastUpdated": "2026-02-05T11:19:10-05:00" 877 - }, 878 - { 879 - "id": "world-clock", 880 - "name": "World Clock", 881 - "version": "1.0.4", 882 - "official": false, 883 - "author": "Lokize", 884 - "description": "Display time from multiple timezones around the world with automatic rotation.", 885 - "repository": "https://github.com/noctalia-dev/noctalia-plugins", 886 - "minNoctaliaVersion": "3.6.0", 887 - "license": "MIT", 888 - "tags": [], 889 - "lastUpdated": "2026-01-27T08:47:06-05:00" 14 + "tags": ["Bar", "Panel", "Productivity"], 15 + "lastUpdated": "2026-02-28T12:00:00+08:00" 890 16 } 891 17 ] 892 18 }
+50 -2
weekly-calendar/Main.qml
··· 73 73 } 74 74 } 75 75 76 - function initializePlugin() { loadEvents() } 76 + function initializePlugin() { 77 + console.log("[weekly-calendar] initializePlugin called, CalendarService.available=" + CalendarService.available) 78 + loadEvents() 79 + } 77 80 78 81 // Fetch events 79 82 function loadEvents() { 83 + console.log("[weekly-calendar] loadEvents called, available=" + CalendarService.available + " isLoading=" + isLoading + " hasLoadedOnce=" + hasLoadedOnce) 80 84 if (!CalendarService.available || isLoading) return 81 - 85 + 82 86 isLoading = true 83 87 syncStatus = pluginApi.tr("panel.loading") 84 88 ··· 458 462 } 459 463 460 464 function goToToday() { currentDate = new Date() } 465 + 466 + // Event creation via EDS Python script 467 + property string createEventStdout: "" 468 + property string createEventStderr: "" 469 + 470 + Process { 471 + id: createEventProcess 472 + onExited: function(exitCode, exitStatus) { 473 + if (exitCode === 0) { 474 + try { 475 + var result = JSON.parse(createEventStdout) 476 + if (result.success) { 477 + console.log("Event created: " + result.uid) 478 + Qt.callLater(loadEvents) 479 + } 480 + } catch(e) { 481 + console.error("Failed to parse create-event output: " + createEventStdout) 482 + } 483 + } else { 484 + console.error("create-event.py failed: " + createEventStderr) 485 + } 486 + createEventStdout = "" 487 + createEventStderr = "" 488 + } 489 + stdout: SplitParser { 490 + onRead: data => createEventStdout += data 491 + } 492 + stderr: SplitParser { 493 + onRead: data => createEventStderr += data 494 + } 495 + } 496 + 497 + function createEvent(calendarUid, summary, startTimestamp, endTimestamp, location, description) { 498 + var scriptPath = pluginApi.pluginDir + "/scripts/create-event.py" 499 + var args = ["python3", scriptPath, 500 + "--calendar", calendarUid, 501 + "--summary", summary, 502 + "--start", String(startTimestamp), 503 + "--end", String(endTimestamp)] 504 + if (location) { args.push("--location"); args.push(location) } 505 + if (description) { args.push("--description"); args.push(description) } 506 + createEventProcess.command = args 507 + createEventProcess.running = true 508 + } 461 509 }
+176
weekly-calendar/Panel.qml
··· 20 20 readonly property bool panelAnchorVerticalCenter: mainInstance ? mainInstance.panelModeSetting === "centered" : false 21 21 anchors.fill: parent 22 22 23 + property bool showCreateDialog: false 24 + 23 25 property real hourHeight: 50 * Style.uiScaleRatio 24 26 property real timeColumnWidth: 65 * Style.uiScaleRatio 25 27 property real daySpacing: 1 * Style.uiScaleRatio ··· 61 63 } 62 64 } 63 65 66 + // Event creation dialog 67 + Rectangle { 68 + id: createEventOverlay 69 + anchors.fill: parent 70 + color: Qt.rgba(0, 0, 0, 0.5) 71 + visible: showCreateDialog 72 + z: 2000 73 + 74 + MouseArea { anchors.fill: parent; onClicked: showCreateDialog = false } 75 + 76 + Rectangle { 77 + anchors.centerIn: parent 78 + width: 400 * Style.uiScaleRatio 79 + height: createDialogColumn.implicitHeight + 2 * Style.marginM 80 + color: Color.mSurface 81 + radius: Style.radiusM 82 + 83 + MouseArea { anchors.fill: parent } // block clicks through 84 + 85 + ColumnLayout { 86 + id: createDialogColumn 87 + anchors.fill: parent 88 + anchors.margins: Style.marginM 89 + spacing: Style.marginS 90 + 91 + NText { 92 + text: pluginApi.tr("panel.add_event") 93 + font.pointSize: Style.fontSizeL; font.weight: Font.Bold 94 + color: Color.mOnSurface 95 + } 96 + 97 + NText { text: pluginApi.tr("panel.summary"); color: Color.mOnSurfaceVariant; font.pointSize: Style.fontSizeS } 98 + TextField { 99 + id: createEventSummary 100 + Layout.fillWidth: true 101 + placeholderText: pluginApi.tr("panel.summary") 102 + color: Color.mOnSurface 103 + background: Rectangle { color: Color.mSurfaceVariant; radius: Style.radiusS } 104 + } 105 + 106 + NText { text: pluginApi.tr("panel.date"); color: Color.mOnSurfaceVariant; font.pointSize: Style.fontSizeS } 107 + TextField { 108 + id: createEventDate 109 + Layout.fillWidth: true 110 + placeholderText: "YYYY-MM-DD" 111 + color: Color.mOnSurface 112 + background: Rectangle { color: Color.mSurfaceVariant; radius: Style.radiusS } 113 + } 114 + 115 + RowLayout { 116 + spacing: Style.marginS 117 + ColumnLayout { 118 + Layout.fillWidth: true 119 + NText { text: pluginApi.tr("panel.start_time"); color: Color.mOnSurfaceVariant; font.pointSize: Style.fontSizeS } 120 + TextField { 121 + id: createEventStartTime 122 + Layout.fillWidth: true 123 + placeholderText: "HH:MM" 124 + color: Color.mOnSurface 125 + background: Rectangle { color: Color.mSurfaceVariant; radius: Style.radiusS } 126 + } 127 + } 128 + ColumnLayout { 129 + Layout.fillWidth: true 130 + NText { text: pluginApi.tr("panel.end_time"); color: Color.mOnSurfaceVariant; font.pointSize: Style.fontSizeS } 131 + TextField { 132 + id: createEventEndTime 133 + Layout.fillWidth: true 134 + placeholderText: "HH:MM" 135 + color: Color.mOnSurface 136 + background: Rectangle { color: Color.mSurfaceVariant; radius: Style.radiusS } 137 + } 138 + } 139 + } 140 + 141 + NText { text: pluginApi.tr("panel.location"); color: Color.mOnSurfaceVariant; font.pointSize: Style.fontSizeS } 142 + TextField { 143 + id: createEventLocation 144 + Layout.fillWidth: true 145 + placeholderText: pluginApi.tr("panel.location") 146 + color: Color.mOnSurface 147 + background: Rectangle { color: Color.mSurfaceVariant; radius: Style.radiusS } 148 + } 149 + 150 + NText { text: pluginApi.tr("panel.description"); color: Color.mOnSurfaceVariant; font.pointSize: Style.fontSizeS } 151 + TextField { 152 + id: createEventDescription 153 + Layout.fillWidth: true 154 + placeholderText: pluginApi.tr("panel.description") 155 + color: Color.mOnSurface 156 + background: Rectangle { color: Color.mSurfaceVariant; radius: Style.radiusS } 157 + } 158 + 159 + NText { text: pluginApi.tr("panel.calendar_select"); color: Color.mOnSurfaceVariant; font.pointSize: Style.fontSizeS } 160 + ComboBox { 161 + id: calendarSelector 162 + Layout.fillWidth: true 163 + model: CalendarService.calendars || [] 164 + textRole: "name" 165 + background: Rectangle { color: Color.mSurfaceVariant; radius: Style.radiusS } 166 + } 167 + 168 + RowLayout { 169 + Layout.fillWidth: true 170 + spacing: Style.marginS 171 + 172 + Item { Layout.fillWidth: true } 173 + 174 + Rectangle { 175 + Layout.preferredWidth: cancelBtn.implicitWidth + 2 * Style.marginM 176 + Layout.preferredHeight: cancelBtn.implicitHeight + Style.marginS 177 + color: Color.mSurfaceVariant; radius: Style.radiusS 178 + NText { 179 + id: cancelBtn; anchors.centerIn: parent 180 + text: pluginApi.tr("panel.cancel"); color: Color.mOnSurfaceVariant 181 + } 182 + MouseArea { anchors.fill: parent; cursorShape: Qt.PointingHandCursor; onClicked: showCreateDialog = false } 183 + } 184 + 185 + Rectangle { 186 + Layout.preferredWidth: createBtn.implicitWidth + 2 * Style.marginM 187 + Layout.preferredHeight: createBtn.implicitHeight + Style.marginS 188 + color: Color.mPrimary; radius: Style.radiusS 189 + opacity: createEventSummary.text.trim() !== "" ? 1.0 : 0.5 190 + NText { 191 + id: createBtn; anchors.centerIn: parent 192 + text: pluginApi.tr("panel.create"); color: Color.mOnPrimary; font.weight: Font.Bold 193 + } 194 + MouseArea { 195 + anchors.fill: parent; cursorShape: Qt.PointingHandCursor 196 + onClicked: { 197 + if (createEventSummary.text.trim() === "") return 198 + var cal = CalendarService.calendars?.[calendarSelector.currentIndex] 199 + var calUid = cal?.uid || "" 200 + var dateParts = createEventDate.text.split("-") 201 + var startParts = createEventStartTime.text.split(":") 202 + var endParts = createEventEndTime.text.split(":") 203 + var startDate = new Date(parseInt(dateParts[0]), parseInt(dateParts[1])-1, parseInt(dateParts[2]), 204 + parseInt(startParts[0]), parseInt(startParts[1]), 0) 205 + var endDate = new Date(parseInt(dateParts[0]), parseInt(dateParts[1])-1, parseInt(dateParts[2]), 206 + parseInt(endParts[0]), parseInt(endParts[1]), 0) 207 + mainInstance?.createEvent(calUid, createEventSummary.text.trim(), 208 + Math.floor(startDate.getTime()/1000), Math.floor(endDate.getTime()/1000), 209 + createEventLocation.text.trim(), createEventDescription.text.trim()) 210 + showCreateDialog = false 211 + } 212 + } 213 + } 214 + } 215 + } 216 + } 217 + } 218 + 64 219 // UI 65 220 Rectangle { 66 221 id: panelContainer ··· 115 270 116 271 RowLayout { 117 272 spacing: Style.marginS 273 + NIconButton { 274 + icon: "plus"; tooltipText: pluginApi.tr("panel.add_event") 275 + onClicked: { 276 + createEventSummary.text = "" 277 + createEventLocation.text = "" 278 + createEventDescription.text = "" 279 + var now = new Date() 280 + var startH = now.getHours() + 1 281 + createEventDate.text = now.getFullYear() + "-" + String(now.getMonth()+1).padStart(2,'0') + "-" + String(now.getDate()).padStart(2,'0') 282 + createEventStartTime.text = String(startH).padStart(2,'0') + ":00" 283 + createEventEndTime.text = String(startH+1).padStart(2,'0') + ":00" 284 + showCreateDialog = true 285 + } 286 + } 118 287 NIconButton { 119 288 icon: "chevron-left" 120 289 onClicked: { mainInstance?.navigateWeek(-7); mainInstance?.loadEvents() } ··· 445 614 text: mainInstance?.formatTimeRangeForDisplay(model) || "" 446 615 color: Color.mOnPrimary 447 616 font.pointSize: Style.fontSizeXXS; opacity: 0.9 617 + elide: Text.ElideRight; width: parent.width 618 + } 619 + NText { 620 + visible: exactHeight >= 45 && model.location && model.location !== "" 621 + text: "\u26B2 " + (model.location || "") 622 + color: Color.mOnPrimary 623 + font.pointSize: Style.fontSizeXXS; opacity: 0.8 448 624 elide: Text.ElideRight; width: parent.width 449 625 } 450 626 }
+13 -1
weekly-calendar/i18n/en.json
··· 13 13 "allday": "all-day", 14 14 "no_service": "No calendar service", 15 15 "loading": "Loading...", 16 - "no_events": "No events" 16 + "no_events": "No events", 17 + "add_event": "New Event", 18 + "create": "Create", 19 + "cancel": "Cancel", 20 + "summary": "Summary", 21 + "date": "Date", 22 + "start_time": "Start Time", 23 + "end_time": "End Time", 24 + "location": "Location", 25 + "description": "Description", 26 + "calendar_select": "Calendar", 27 + "event_created": "Event created", 28 + "event_error": "Failed to create event" 17 29 }, 18 30 "settings": { 19 31 "weekStart": "First day of week",
+13 -1
weekly-calendar/i18n/zh-CN.json
··· 13 13 "allday": "场全天", 14 14 "no_service": "缺少日历服务", 15 15 "loading": "加载中…", 16 - "no_events": "没有活动" 16 + "no_events": "没有活动", 17 + "add_event": "新建活动", 18 + "create": "创建", 19 + "cancel": "取消", 20 + "summary": "标题", 21 + "date": "日期", 22 + "start_time": "开始时间", 23 + "end_time": "结束时间", 24 + "location": "地点", 25 + "description": "描述", 26 + "calendar_select": "日历", 27 + "event_created": "活动已创建", 28 + "event_error": "创建活动失败" 17 29 }, 18 30 "settings": { 19 31 "weekStart": "一周起始日",
+3 -3
weekly-calendar/manifest.json
··· 1 1 { 2 2 "id": "weekly-calendar", 3 3 "name": "Weekly Calendar", 4 - "version": "1.0.4", 4 + "version": "1.1.0", 5 5 "minNoctaliaVersion": "4.2.3", 6 6 "author": "dodaars", 7 7 "license": "MIT", 8 - "repository": "https://github.com/noctalia-dev/noctalia-plugins", 9 - "description": "A weekly calendar plugin complementing Noctalia's inbuilt calendar service.", 8 + "repository": "https://github.com/DzmingLi/noctalia-weekly-calendar", 9 + "description": "A weekly calendar plugin with location display and event creation via EDS.", 10 10 "tags": ["Bar", "Panel", "Productivity"], 11 11 "entryPoints": { 12 12 "main": "Main.qml",
+83
weekly-calendar/scripts/create-event.py
··· 1 + #!/usr/bin/env python3 2 + """Create a calendar event via Evolution Data Server (EDS).""" 3 + 4 + import argparse 5 + import json 6 + import sys 7 + from datetime import datetime, timezone 8 + 9 + import gi 10 + gi.require_version("ECal", "2.0") 11 + gi.require_version("EDataServer", "1.2") 12 + gi.require_version("ICalGLib", "3.0") 13 + from gi.repository import ECal, EDataServer, ICalGLib 14 + 15 + 16 + def find_source(registry, calendar_uid): 17 + source = registry.ref_source(calendar_uid) 18 + if source and source.has_extension(EDataServer.SOURCE_EXTENSION_CALENDAR): 19 + return source 20 + # Fallback: search by display name 21 + for src in registry.list_sources(EDataServer.SOURCE_EXTENSION_CALENDAR): 22 + if src.get_display_name() == calendar_uid or src.get_uid() == calendar_uid: 23 + return src 24 + return None 25 + 26 + 27 + def make_ical_datetime(timestamp): 28 + dt = datetime.fromtimestamp(timestamp, tz=timezone.utc).astimezone() 29 + ical_time = ICalGLib.Time.new_null_time() 30 + ical_time.set_date(dt.year, dt.month, dt.day) 31 + ical_time.set_time(dt.hour, dt.minute, dt.second) 32 + tz_id = dt.strftime("%Z") 33 + builtin_tz = ICalGLib.Timezone.get_builtin_timezone(tz_id) 34 + if builtin_tz: 35 + ical_time.set_timezone(builtin_tz) 36 + else: 37 + ical_time.set_timezone(ICalGLib.Timezone.get_utc_timezone()) 38 + ical_time.set_date(dt.year, dt.month, dt.day) 39 + ical_time.set_time(dt.hour, dt.minute, dt.second) 40 + return ical_time 41 + 42 + 43 + def main(): 44 + parser = argparse.ArgumentParser(description="Create EDS calendar event") 45 + parser.add_argument("--calendar", required=True, help="Calendar UID or display name") 46 + parser.add_argument("--summary", required=True, help="Event summary/title") 47 + parser.add_argument("--start", required=True, type=int, help="Start time (UNIX timestamp)") 48 + parser.add_argument("--end", required=True, type=int, help="End time (UNIX timestamp)") 49 + parser.add_argument("--location", default="", help="Event location") 50 + parser.add_argument("--description", default="", help="Event description") 51 + args = parser.parse_args() 52 + 53 + try: 54 + registry = EDataServer.SourceRegistry.new_sync(None) 55 + source = find_source(registry, args.calendar) 56 + if not source: 57 + print(json.dumps({"success": False, "error": f"Calendar not found: {args.calendar}"})) 58 + sys.exit(1) 59 + 60 + client = ECal.Client.connect_sync( 61 + source, ECal.ClientSourceType.EVENTS, -1, None 62 + ) 63 + 64 + comp = ICalGLib.Component.new(ICalGLib.ComponentKind.VEVENT_COMPONENT) 65 + comp.set_summary(args.summary) 66 + comp.set_dtstart(make_ical_datetime(args.start)) 67 + comp.set_dtend(make_ical_datetime(args.end)) 68 + 69 + if args.location: 70 + comp.set_location(args.location) 71 + if args.description: 72 + comp.set_description(args.description) 73 + 74 + uid = client.create_object_sync(comp, ECal.OperationFlags.NONE, None) 75 + print(json.dumps({"success": True, "uid": uid})) 76 + 77 + except Exception as e: 78 + print(json.dumps({"success": False, "error": str(e)})) 79 + sys.exit(1) 80 + 81 + 82 + if __name__ == "__main__": 83 + main()
+7
weekly-calendar/settings.json
··· 1 + { 2 + "weekStart": "1", 3 + "timeFormat": "24h", 4 + "lineColorType": "mOutline", 5 + "hourLineOpacity": 0.5, 6 + "dayLineOpacity": 1 7 + }