ProgressDemo.vala 4.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106
  1. using Spry;
  2. using Inversion;
  3. /**
  4. * ProgressDemo - A progress bar demo for the Continuations documentation
  5. *
  6. * Demonstrates:
  7. * - spry-continuation attribute for SSE
  8. * - spry-dynamic for updatable sections
  9. * - continuation() method for real-time updates
  10. * - ContinuationContext API
  11. */
  12. public class ProgressDemo : Component {
  13. public int percent { get; set; default = 0; }
  14. public string status { get; set; default = "Ready"; }
  15. public bool is_running { get; set; default = false; }
  16. public override string markup { get {
  17. return """
  18. <div sid="progress" spry-continuation class="demo-progress" style="padding: 20px; background: #f8f9fa; border-radius: 8px; border: 1px solid #e9ecef;">
  19. <div spry-dynamic="progress-bar" class="progress-bar-container" style="background: #e0e0e0; border-radius: 8px; overflow: hidden; margin: 15px 0; height: 24px;">
  20. <div sid="progress-bar" class="progress-bar"
  21. style-width-expr='format("%i%%", this.percent)'
  22. style="height: 100%; background: linear-gradient(90deg, #4CAF50, #8BC34A); transition: width 0.3s ease; display: flex; align-items: center; justify-content: center; color: white; font-weight: bold; font-size: 12px; min-width: 40px;">
  23. </div>
  24. </div>
  25. <div spry-dynamic="status" class="progress-info" style="display: flex; justify-content: space-between; align-items: center; margin: 15px 0;">
  26. <span sid="percent-text" class="progress-percent" spry-unique content-expr='format("%i%%", this.percent)' style="font-weight: bold; color: #333; font-size: 18px;">0%</span>
  27. <span sid="status-text" class="progress-status" spry-unique content-expr="this.status" style="color: #666; font-size: 14px; padding: 6px 12px; background: #e9ecef; border-radius: 4px; border-left: 3px solid #2196F3;">Ready</span>
  28. </div>
  29. <div class="progress-controls" style="display: flex; gap: 10px; margin-top: 15px;">
  30. <button sid="start-btn" spry-action=":Start" spry-target="progress"
  31. class="progress-btn" style="padding: 10px 20px; background: #4CAF50; color: white; border: none; border-radius: 4px; cursor: pointer; font-weight: 500; transition: background 0.2s;">Start Task</button>
  32. <button sid="reset-btn" spry-action=":Reset" spry-target="progress"
  33. class="progress-btn secondary" style="padding: 10px 20px; background: #6c757d; color: white; border: none; border-radius: 4px; cursor: pointer; font-weight: 500; transition: background 0.2s;">Reset</button>
  34. </div>
  35. </div>
  36. """;
  37. }}
  38. public override async void prepare() throws Error {
  39. this["status-text"].text_content = status;
  40. this["percent-text"].text_content = @"$percent%";
  41. if (is_running) {
  42. this["start-btn"].set_attribute("disabled", "disabled");
  43. this["start-btn"].text_content = "Running...";
  44. } else {
  45. this["start-btn"].remove_attribute("disabled");
  46. this["start-btn"].text_content = percent >= 100 ? "Complete!" : "Start Task";
  47. }
  48. }
  49. public async override void handle_action(string action) throws Error {
  50. switch (action) {
  51. case "Start":
  52. if (!is_running && percent < 100) {
  53. is_running = true;
  54. status = "Starting...";
  55. }
  56. break;
  57. case "Reset":
  58. percent = 0;
  59. status = "Ready";
  60. is_running = false;
  61. break;
  62. }
  63. }
  64. public async override void continuation(ContinuationContext ctx) throws Error {
  65. if (!is_running) return;
  66. for (int i = percent; i <= 100; i += 5) {
  67. percent = i;
  68. if (i < 30) {
  69. status = @"Processing... $i%";
  70. } else if (i < 60) {
  71. status = @"Building... $i%";
  72. } else if (i < 90) {
  73. status = @"Finalizing... $i%";
  74. } else {
  75. status = @"Almost done... $i%";
  76. }
  77. // Send updates via SSE to the dynamic sections
  78. yield ctx.send_dynamic("progress-bar");
  79. yield ctx.send_dynamic("status");
  80. // Simulate work
  81. Timeout.add(200, () => {
  82. continuation.callback();
  83. return false;
  84. });
  85. yield;
  86. }
  87. percent = 100;
  88. status = "Complete!";
  89. is_running = false;
  90. yield ctx.send_dynamic("progress-bar");
  91. yield ctx.send_dynamic("status");
  92. }
  93. }