Skip to content

Add date separators to the message reader#51

Merged
keyang556 merged 5 commits intomainfrom
codex/dev
Apr 10, 2026
Merged

Add date separators to the message reader#51
keyang556 merged 5 commits intomainfrom
codex/dev

Conversation

@keyang556
Copy link
Copy Markdown
Owner

@keyang556 keyang556 commented Apr 10, 2026

Summary

  • preserve exported chat date rows in the parsed message list instead of dropping them
  • render date separator rows in the message reader without changing existing message formatting
  • guard continuation-line parsing so extra lines attach only to real messages, not date rows
  • add parser and formatting tests covering date preservation and multiline message behavior

Testing

  • uv run --with pytest python -m pytest tests\test_message_reader_parser.py

Greptile Summary

此 PR 為訊息閱讀器新增日期分隔列的支援:_chatParser.py 改為將日期列以 type: 'date' 的形式保留於輸出列表,而非丟棄;_messageReader.py 則對應調整格式化邏輯、進度標籤計算(僅計算真實訊息數量)、以及多行訊息的附加守衛。所有核心行為均有測試覆蓋。

  • _chatParser.py:日期列以 {'type': 'date', 'content': line} 形式保留;所有訊息加上 type: 'message';continuation line 的附加守衛從 if messages 改為 if messages and messages[-1].get('type') != 'date',避免孤立文字附加至日期列
  • _messageReader.py_formatMessage 直接回傳日期列內容;新增 _getProgressLabel 方法,以 _messageIndexMap 精確計算進度(排除日期列);邊界提示文字從「第一則訊息/最後一則訊息」改為「第一項/最後一項」
  • tests/test_message_reader_parser.py:新增 5 個測試,涵蓋日期保留、continuation line 守衛、日期格式化、進度標籤計算,以及邊界提示文字
  • .claude/worktrees/:兩個 git submodule 指標意外被提交至倉庫,應在合併前清除

Confidence Score: 4/5

核心功能邏輯正確、測試完整,僅需在合併前移除意外提交的 .claude/worktrees/ submodule 指標

解析器與閱讀器的修改邏輯清晰正確,_messageIndexMap 建構方式與 _getProgressLabel 計算在前導、中間、尾端日期等各種情境下均驗證無誤,測試覆蓋充分。唯一需要處理的問題是意外提交的兩個 Claude Code 工作樹 gitlink,這不影響 addon 功能,但會汙染倉庫歷史並可能對 clone 造成困擾,應在合併前清除。

.claude/worktrees/gracious-wright 與 .claude/worktrees/hopeful-northcutt 需要移除

Important Files Changed

Filename Overview
addon/appModules/_chatParser.py 新增日期列保留邏輯(type: 'date')、為所有訊息加上 type 欄位、修正 continuation line 守衛以避免附加到日期列,邏輯正確
addon/appModules/_messageReader.py 新增 _messageIndexMap 進度計算、_getProgressLabel 方法及日期列格式化,覆蓋前導/中間/尾端日期各種情境,邏輯正確
tests/test_message_reader_parser.py 新增 5 個測試函數,以 object.new 繞過 wx 依賴,充分覆蓋日期保留、continuation 守衛、格式化、進度標籤及邊界提示各情境
.claude/worktrees/gracious-wright 意外提交的 Claude Code 工作樹 git submodule 指標,不應出現在版本倉庫中
.claude/worktrees/hopeful-northcutt 意外提交的 Claude Code 工作樹 git submodule 指標,不應出現在版本倉庫中
addonTemplate.egg-info/SOURCES.txt 僅補上檔案尾端換行符,無功能影響

Flowchart

%%{init: {'theme': 'neutral'}}%%
flowchart TD
    A["parseChatFile(filePath)"] --> B{逐行讀取}
    B --> C{空行?}
    C -- 是 --> B
    C -- 否 --> D{符合 _DATE_RE?}
    D -- 是 --> E["append {type:'date', content:line}"]
    E --> B
    D -- 否 --> F{符合 _RECALL_RE?}
    F -- 是 --> G["append {type:'message', ...}"]
    G --> B
    F -- 否 --> H{符合 _MSG_RE?}
    H -- 是 --> I["append {type:'message', ...}"]
    I --> B
    H -- 否 --> J{messages 非空 且 最後一項 != 'date'?}
    J -- 是 --> K["最後一則訊息 content += line"]
    K --> B
    J -- 否 --> B

    L["MessageReaderDialog.__init__"] --> M["建立 _messageIndexMap"]
    M --> N["_messageCount = 真實訊息總數"]
    N --> O["_updateDisplay()"]
    O --> P["_formatMessage(msg)"]
    P --> Q{type == 'date'?}
    Q -- 是 --> R["回傳 content 原文"]
    Q -- 否 --> S["回傳 name content time"]
    O --> T["_getProgressLabel()"]
    T --> U{messageCount <= 0?}
    U -- 是 --> V["回傳空字串"]
    U -- 否 --> W{目前為日期列?}
    W -- 否 --> X["回傳 index / total"]
    W -- 是 --> Y{index < messageCount?}
    Y -- 是 --> Z["回傳 index+1 / total"]
    Y -- 否 --> V
Loading

Comments Outside Diff (1)

  1. addon/appModules/_messageReader.py, line 67 (link)

    P2 導覽計數器將日期項目計入總數

    len(self._messages) 現在包含日期分隔符號項目,因此計數器(例如 2 / 5)會把日期列也算進去,對使用者來說可能不直覺——他們通常期望看到的是「第幾則訊息 / 共幾則訊息」,而非「第幾個項目 / 共幾個項目」。

    若要只計算真正的訊息數量,可考慮在 __init__ 中預先計算訊息總數供顯示用:

    self._messageCount = sum(1 for m in messages if m.get('type') != 'date')

    這僅為使用體驗建議,若設計上刻意將日期視為獨立的可導覽項目,則現行行為亦屬合理。

    Prompt To Fix With AI
    This is a comment left during a code review.
    Path: addon/appModules/_messageReader.py
    Line: 67
    
    Comment:
    **導覽計數器將日期項目計入總數**
    
    `len(self._messages)` 現在包含日期分隔符號項目,因此計數器(例如 `2 / 5`)會把日期列也算進去,對使用者來說可能不直覺——他們通常期望看到的是「第幾則訊息 / 共幾則訊息」,而非「第幾個項目 / 共幾個項目」。
    
    若要只計算真正的訊息數量,可考慮在 `__init__` 中預先計算訊息總數供顯示用:
    
    ```python
    self._messageCount = sum(1 for m in messages if m.get('type') != 'date')
    ```
    
    這僅為使用體驗建議,若設計上刻意將日期視為獨立的可導覽項目,則現行行為亦屬合理。
    
    How can I resolve this? If you propose a fix, please make it concise.

    Fix in Claude Code Fix in Codex

Fix All in Claude Code Fix All in Codex

Prompt To Fix All With AI
This is a comment left during a code review.
Path: .claude/worktrees/gracious-wright
Line: 1

Comment:
**意外提交的 Claude Code 工作樹 submodule 指標**

`.claude/worktrees/gracious-wright``.claude/worktrees/hopeful-northcutt` 是 Claude Code 開發工具在本機建立的暫時工作樹(worktree)所留下的 git submodule 指標,不應被納入版本控制。

這兩個 gitlink(`160000` 模式)指向外部 commit,任何 clone 此倉庫的人若執行 `git submodule update --init`,將因這些 commit 不公開可用而失敗;即使不使用 submodule,它們也會汙染 `git status``git log` 的輸出。

建議在合併前執行以下步驟移除:

```bash
git rm --cached .claude/worktrees/gracious-wright
git rm --cached .claude/worktrees/hopeful-northcutt
```

並確認 `.claude/` 目錄已加入 `.gitignore`,以防日後再次發生:

```
# .gitignore
.claude/worktrees/
```

How can I resolve this? If you propose a fix, please make it concise.

Reviews (5): Last reviewed commit: "Optimize message reader progress indexin..." | Re-trigger Greptile

@keyang556
Copy link
Copy Markdown
Owner Author

@greptileai 要怎麼修正

@greptile-apps
Copy link
Copy Markdown
Contributor

greptile-apps bot commented Apr 10, 2026

我看到了需要修正的兩個問題。讓我為您提供具體的修復方案:

問題 1:移除多餘的防禦性條件(第 67-68 行)

_getProgressLabel 方法中,第 67-68 行的檢查永遠不會執行到,因為 currentMessageIndex 在邏輯上不可能 ≤ 0。

修復方式(第 67-68 行):

		return f"{currentMessageIndex} / {self._messageCount}"

這樣直接返回結果,移除了無法觸及的檢查。

問題 2:更新邊界訊息措辭(第 113 行和第 121 行)

由於現在清單中包含日期項目,邊界提示應該使用更通用的措辭。

修復方式(第 113 行):

			self._speakMessage(_("已經是第一項"))

修復方式(第 121 行):

			self._speakMessage(_("已經是最後一項"))

這樣無論是停在日期列還是訊息上,提示都是準確的。

@keyang556
Copy link
Copy Markdown
Owner Author

@greptileai 要怎麼修正

@greptile-apps
Copy link
Copy Markdown
Contributor

greptile-apps bot commented Apr 10, 2026

__init__ 中預先建立索引對應表,避免每次導航都重新計算:

	def __init__(self, messages, title=None, cleanupPath=None):
		if title is None:
			title = _("訊息閱讀器")
		super().__init__(
			gui.mainFrame,
			title=title,
			style=wx.DEFAULT_DIALOG_STYLE | wx.RESIZE_BORDER,
		)
		self._messages = messages
		self._messageCount = sum(1 for msg in messages if msg.get('type') != 'date')
		# Pre-compute position → message index map for O(1) lookup
		self._messageIndexMap = {}
		real_count = 0
		for i, msg in enumerate(messages):
			if msg.get('type') != 'date':
				real_count += 1
			self._messageIndexMap[i] = real_count
		self._pos = 0 if messages else -1
		self._cleanupPath = cleanupPath

然後簡化 _getProgressLabel

	def _getProgressLabel(self):
		if self._messageCount <= 0 or self._pos < 0:
			return ""
		currentMessageIndex = self._messageIndexMap[self._pos]
		if self._messages[self._pos].get('type') == 'date' and currentMessageIndex < self._messageCount:
			currentMessageIndex += 1
		return f"{currentMessageIndex} / {self._messageCount}"

這樣每次導航只需查表,不用重新遍歷清單。

@keyang556
Copy link
Copy Markdown
Owner Author

@greptileai 要怎麼修正

@greptile-apps
Copy link
Copy Markdown
Contributor

greptile-apps bot commented Apr 10, 2026

看到了,目前第67-69行的進度標籤計算方式包含了所有項目(訊息+日期)。需要改成只計算真正的訊息。

這是修正方案:

	def __init__(self, messages, title=None, cleanupPath=None):
		if title is None:
			title = _("訊息閱讀器")
		super().__init__(
			gui.mainFrame,
			title=title,
			style=wx.DEFAULT_DIALOG_STYLE | wx.RESIZE_BORDER,
		)
		self._messages = messages
		self._pos = 0 if messages else -1
		self._cleanupPath = cleanupPath
		# 只計算實際訊息數量(排除日期列)
		self._messageCount = sum(1 for m in messages if m.get('type') != 'date')
		# 建立位置到訊息編號的映射
		self._messageIndexMap = []
		messageIndex = 0
		for msg in messages:
			if msg.get('type') != 'date':
				messageIndex += 1
			self._messageIndexMap.append(messageIndex)

		panel = wx.Panel(self)
		sizer = wx.BoxSizer(wx.VERTICAL)

		self._totalLabel = wx.StaticText(panel, label="")
		sizer.Add(self._totalLabel, 0, wx.ALL, 5)

		self._textCtrl = wx.TextCtrl(
			panel,
			style=wx.TE_MULTILINE | wx.TE_READONLY | wx.TE_RICH2,
			size=(500, 100),
		)
		sizer.Add(self._textCtrl, 1, wx.EXPAND | wx.ALL, 5)

		closeBtn = wx.Button(panel, wx.ID_CLOSE, _("關閉(&C)"))
		sizer.Add(closeBtn, 0, wx.ALIGN_CENTER | wx.ALL, 5)

		panel.SetSizer(sizer)
		sizer.Fit(self)

		self._textCtrl.Bind(wx.EVT_KEY_DOWN, self._onKeyDown)
		closeBtn.Bind(wx.EVT_BUTTON, self._onClose)
		self.Bind(wx.EVT_CLOSE, self._onClose)
		self.Bind(wx.EVT_CHAR_HOOK, self._onCharHook)

		self._updateDisplay()
		self._textCtrl.SetFocus()

	def _formatMessage(self, msg):
		if msg.get('type') == 'date':
			return msg.get('content', '')
		return f"{msg['name']} {msg['content']} {msg['time']}"

	def _getProgressLabel(self):
		"""返回進度標籤,只計算實際訊息"""
		if self._messageCount <= 0 or self._pos < 0:
			return ""
		currentMessageIndex = self._messageIndexMap[self._pos]
		if self._messages[self._pos].get('type') == 'date':
			# 在日期列上:顯示下一則訊息編號
			if currentMessageIndex < self._messageCount:
				currentMessageIndex += 1
			else:
				# 末尾日期列:不顯示進度
				return ""
		return f"{currentMessageIndex} / {self._messageCount}"

	def _updateDisplay(self):
		if not self._messages or self._pos < 0:
			self._textCtrl.SetValue(_("沒有訊息"))
			self._totalLabel.SetLabel("")
			return
		msg = self._messages[self._pos]
		text = self._formatMessage(msg)
		self._textCtrl.SetValue(text)
		self._totalLabel.SetLabel(self._getProgressLabel())
		self._speakMessage(text)

主要變更:

  1. __init__建立_messageCount只計算訊息(排除日期)
  2. 建立_messageIndexMap映射每個位置對應的訊息編號
  3. 新增_getProgressLabel()處理日期列的進度顯示
  4. _updateDisplay()改用_getProgressLabel()

這樣進度會顯示「第幾則訊息 / 共幾則訊息」,而非「第幾個項目 / 共幾個項目」。

@keyang556
Copy link
Copy Markdown
Owner Author

@greptileai 移除了

@greptile-apps
Copy link
Copy Markdown
Contributor

greptile-apps bot commented Apr 10, 2026

好的!記得確認 .gitignore 中已加入 .claude/.claude/worktrees/,避免日後再次提交。

@keyang556 keyang556 merged commit 8e4f4f2 into main Apr 10, 2026
2 of 3 checks passed
@keyang556 keyang556 deleted the codex/dev branch April 10, 2026 07:58
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.

1 participant