Răsfoiți Sursa

r1: one time-format util — src/Format.vala's format_stamp owns the '%Y-%m-%d %H:%M' display shape; the four per-entrypoint format_stamp/format_time copies and the saddles/rules/projects inline formats collapse onto it (StatePulse keeps its second-precision pulse stamp); the clock domain is uniform now_local (PushService's VAPID exp was the lone now_utc, and to_unix is timezone-independent anyway).

clanker 1 lună în urmă
părinte
comite
375d0957f9

+ 1 - 0
meson.build

@@ -121,6 +121,7 @@ app_sources = files(
     # spry:sources-begin
     'src/main.vala',
     'src/Json.vala',
+    'src/Format.vala',
     'src/Data/Entities.vala',
     'src/Data/Migrations/M0001_Initial.vala',
     'src/Services/ProjectService.vala',

+ 14 - 0
src/Format.vala

@@ -0,0 +1,14 @@
+namespace ClankerSaddle {
+
+    /**
+     * The one display timestamp shape ("%Y-%m-%d %H:%M", "" when
+     * null) every page stamp uses — created/started/completed
+     * displays, session labels, activity rows. Clock domain: the
+     * app stamps rows with now_local (uniform — epoch math is
+     * timezone-independent anyway), and ISO parses read the
+     * daemon's UTC domain (EntryJson.parse_iso).
+     */
+    public string format_stamp(DateTime? stamp) {
+        return stamp != null ? ((!)stamp).format("%Y-%m-%d %H:%M") : "";
+    }
+}

+ 1 - 1
src/Services/PushService.vala

@@ -580,7 +580,7 @@ namespace ClankerSaddle.Services {
                 ?? "mailto:clanker-saddle@localhost";
             string header = "{\"typ\":\"JWT\",\"alg\":\"ES256\"}";
             string claims = "{\"aud\":\"" + origin + "\",\"exp\":"
-                + (new DateTime.now_utc().to_unix() + 43200).to_string()
+                + (new DateTime.now_local().to_unix() + 43200).to_string()
                 + ",\"sub\":\"" + subject + "\"}";
             string header_b64 = base64url_encode(header.data);
             string claims_b64 = base64url_encode(claims.data);

+ 0 - 4
src/entrypoints/GoalDetailEntrypoint.vala

@@ -785,10 +785,6 @@ private static async Dictionary<string, GoalTaskDisplay> task_display_map(
             return map;
         }
 
-        private static string format_stamp(DateTime? stamp) {
-            return stamp != null ? ((!)stamp).format("%Y-%m-%d %H:%M") : "";
-        }
-
         /** A flattened, clipped activity line (the current-activity display). */
         private static string clip_line(string text, int limit) {
             string flat = text.replace("\n", " ⏎ ").strip();

+ 3 - 7
src/entrypoints/HomeEntrypoint.vala

@@ -217,7 +217,7 @@ namespace ClankerSaddle {
                     var progress = yield tasks.list_progress(task.id);
                     if (progress.length > 0) {
                         row.latest_progress = progress.first().summary;
-                        row.progress_display = format_time(progress.first().created_at);
+                        row.progress_display = format_stamp(progress.first().created_at);
                     }
                     active.add(row);
                 }
@@ -250,7 +250,7 @@ namespace ClankerSaddle {
                         goal_title = block_goal_title,
                         block_type = block.block_type,
                         question = block.question,
-                        created_display = format_time(block.created_at)
+                        created_display = format_stamp(block.created_at)
                     };
                     if (block.created_at != null) {
                         view.at_epoch = ((!)block.created_at).to_unix();
@@ -287,8 +287,7 @@ namespace ClankerSaddle {
                 activity.add(new DashboardActivityView() {
                     kind = item.kind,
                     at_epoch = item.at_epoch,
-                    when_display = new DateTime.from_unix_local(item.at_epoch)
-                        .format("%Y-%m-%d %H:%M"),
+                    when_display = format_stamp(new DateTime.from_unix_local(item.at_epoch)),
                     task_id = item.task_id,
                     task_title = item.task_title,
                     goal_id = item.goal_id,
@@ -311,9 +310,6 @@ namespace ClankerSaddle {
             });
         }
 
-        private static string format_time(DateTime? time) {
-            return time != null ? ((!)time).format("%Y-%m-%d %H:%M") : "";
-        }
     }
 
     /**

+ 2 - 4
src/entrypoints/ProjectsEntrypoint.vala

@@ -180,8 +180,7 @@ namespace ClankerSaddle {
                 git_url = ((!)project).git_url,
                 default_branch = ((!)project).default_branch,
                 summary = ((!)project).summary ?? "",
-                created_display = ((!)project).created_at != null
-                    ? ((!)((!)project).created_at).format("%Y-%m-%d %H:%M") : "",
+                created_display = format_stamp(((!)project).created_at),
                 update = action_registry.author_private<UpdateProjectAction, ProjectActionPrivate>(sealed),
                 add_link = action_registry.author_private<AddProjectLinkAction, ProjectActionPrivate>(sealed),
                 attach_rule = action_registry.author_private<AttachProjectRuleAction, ProjectActionPrivate>(sealed)
@@ -278,8 +277,7 @@ namespace ClankerSaddle {
                     project_name = ((!)project).name,
                     source_task_id = note.source_task_id,
                     body = note.body,
-                    created_display = note.created_at != null
-                        ? ((!)note.created_at).format("%Y-%m-%d %H:%M") : "",
+                    created_display = format_stamp(note.created_at),
                     delete = action_registry.author_private<DeleteProjectNoteAction, ProjectNoteActionPrivate>(note_private)
                 });
             }

+ 1 - 2
src/entrypoints/RulesEntrypoint.vala

@@ -47,8 +47,7 @@ namespace ClankerSaddle {
                     id = rule.id,
                     name = rule.name,
                     body = rule.body,
-                    created_display = rule.created_at != null
-                        ? ((!)rule.created_at).format("%Y-%m-%d %H:%M") : "",
+                    created_display = format_stamp(rule.created_at),
                     update = action_registry.author_private<UpdateRuleAction, RuleActionPrivate>(sealed),
                     delete = action_registry.author_private<DeleteRuleAction, RuleActionPrivate>(sealed)
                 });

+ 1 - 2
src/entrypoints/SaddlesEntrypoint.vala

@@ -170,8 +170,7 @@ namespace ClankerSaddle {
                     ssh_public_key = saddle.ssh_public_key ?? "",
                     update_identity = action_registry.author_private<UpdateSaddleIdentityAction, SaddleActionPrivate>(sealed),
                     current_task_id = saddle.current_task_id,
-                    allocated_display = saddle.allocated_at != null
-                        ? ((!)saddle.allocated_at).format("%Y-%m-%d %H:%M") : "",
+                    allocated_display = format_stamp(saddle.allocated_at),
                     unregister = action_registry.author_private<UnregisterSaddleAction, SaddleActionPrivate>(sealed),
                     refresh = action_registry.author_private<RefreshSaddleStatusAction, SaddleActionPrivate>(sealed),
                     attach_capability = action_registry.author_private<AttachSaddleCapabilityAction, SaddleActionPrivate>(sealed)

+ 10 - 13
src/entrypoints/TaskDetailEntrypoint.vala

@@ -224,9 +224,9 @@ namespace ClankerSaddle {
                 creator = task.creator,
                 is_goal_run = task.kind == TASK_KIND_GOAL_RUN,
                 enqueue_after_task_id = task.enqueue_after_task_id,
-                created_display = format_time(task.created_at),
-                started_display = format_time(task.started_at),
-                completed_display = format_time(task.completed_at)
+                created_display = format_stamp(task.created_at),
+                started_display = format_stamp(task.started_at),
+                completed_display = format_stamp(task.completed_at)
             };
 
             var display = TaskService.display_of_detail(((!)detail));
@@ -287,7 +287,7 @@ namespace ClankerSaddle {
                     author = comment.author,
                     body = comment.body,
                     quote = comment.quote ?? "",
-                    when_display = format_time(comment.created_at),
+                    when_display = format_stamp(comment.created_at),
                     from_agent = comment.author == "agent",
                     is_system = comment.author == COMMENT_AUTHOR_SYSTEM
                 });
@@ -298,7 +298,7 @@ namespace ClankerSaddle {
                 progress.add(new ProgressView() {
                     id = row.id,
                     summary = row.summary,
-                    when_display = format_time(row.created_at)
+                    when_display = format_stamp(row.created_at)
                 });
             }
 
@@ -313,7 +313,7 @@ namespace ClankerSaddle {
             foreach (var row in yeehaw_feed.latest) {
                 yeehaws.add(new YeehawView() {
                     message = row.message,
-                    when_display = format_time(row.at)
+                    when_display = format_stamp(row.at)
                 });
             }
 
@@ -335,8 +335,8 @@ namespace ClankerSaddle {
                     answered = block.answer != null,
                     answered_by = block.answered_by ?? "",
                     is_plan_review = block.block_type == BLOCK_PLAN,
-                    created_display = format_time(block.created_at),
-                    answered_display = format_time(block.answered_at),
+                    created_display = format_stamp(block.created_at),
+                    answered_display = format_stamp(block.answered_at),
                     answer_action = actions.author_private<AnswerBlockAction, BlockAnswerPrivate>(block_private)
                 };
                 if (!view.answered && view.block_type == BLOCK_REVIEW) {
@@ -458,8 +458,8 @@ namespace ClankerSaddle {
                 sessions.add(new SessionView() {
                     id = session.id,
                     saddle_name = saddle != null ? ((!)saddle).name : @"saddle #$(session.saddle_id)",
-                    started_display = format_time(session.started_at),
-                    ended_display = format_time(session.ended_at),
+                    started_display = format_stamp(session.started_at),
+                    ended_display = format_stamp(session.ended_at),
                     outcome = session.outcome ?? "",
                     open = session.ended_at == null
                 });
@@ -520,9 +520,6 @@ namespace ClankerSaddle {
             });
         }
 
-        private static string format_time(DateTime? time) {
-            return time != null ? ((!)time).format("%Y-%m-%d %H:%M") : "";
-        }
     }
 
     /**

+ 1 - 4
src/entrypoints/TaskTerminalEntrypoint.vala

@@ -151,7 +151,7 @@ namespace ClankerSaddle {
                     ? opening_notice : (session.resume_notice ?? "");
                 session_rows.add(new TerminalSessionView() {
                     id = session.id,
-                    label = @"Session #$(session.id) — started $(format_time(session.started_at))"
+                    label = @"Session #$(session.id) — started $(format_stamp(session.started_at))"
                         + (resumed ? " [resumed]" : ""),
                     selected = session.id == selected,
                     raw = yield task_service.has_raw_log(session.id),
@@ -171,9 +171,6 @@ namespace ClankerSaddle {
             return directives().set(slot);
         }
 
-        private static string format_time(DateTime? time) {
-            return time != null ? ((!)time).format("%Y-%m-%d %H:%M") : "";
-        }
 
         /**
          * The opening-brief framing for a task's FIRST session (plan