DevLog:2025年9月9日

1、继续昨天的修改,昨天为了实现对表格较好的渲染效果,拆分出了UnifiedMarkdownView,用于渲染普通文本,表格和代码块都已有专用的文件来渲染,但UnifiedMarkdownView使用了简单的Text组件,丢失了Markdown渲染效果,还是需要换成NSTextView,以实现良好的Markdown渲染效果、文字选择、右键菜单等功能
2、为了实现除表格和代码块之外的文本内容的渲染效果,Cursor创建了新的文件MarkdownTextView,至此明确了组件的职责,MarkdownTextView专门渲染普通文本,TableView专门渲染表格内容,CodeBlockView专门渲染代码块内容,UnifiedMarkdownView统一协调各个组件
3、接下来又是漫长的添加调试信息、定位问题的过程,在此过程中出现了应用卡死、文本不显示等问题,一直没能实现用NSTextView来渲染AI问答的文本内容,目前还是用的Text,可以正常显示文本、选择并复制文本,但没能搞定用AttributedString来解析Markdown,暂时搁置
4、先修改表格的样式,发现目前的表格第二行显示了一堆分隔符,而非正常的表格内容,而且Cursor给表格增加了最大高度限制和滚动功能,我也用不到,让Cursor修改下,Cursor创建了MarkdownTableCell组件来渲染表格单元格,但导致了应用卡死,在恢复到简单的Text组件后暂时不会卡死了,但表格里还是混合了Markdown语法标记,尤其是加粗标记
5、先保存粗体处理试试看,目前测试过的两个表格,都是粗体字比较常见,没想到只想使用这一个功能,也会导致应用卡死,只能先撤销了这一步修改,接下来准备试试Cursor建议的第三方Markdown库,比如SwiftUI-Markdown或MarkdownUI,如果可以的话,应该可以搞定AI对话中的文本、表格,以及备忘录的Markdown渲染

DevLog:2025年9月8日

1、上周在修改NoteWith时,通过调试信息发现目前AI对话并不是真正的流式输出,而是在完整回答后模拟流式输出,Cursor建议使用真正的流式API,实现增量渲染(只渲染新增部分),并且缓存已渲染的组件,避免重复解析,今天先修改这个问题
2、在修改过程中,遇到了AI回答内容不完整显示(但调试信息里是完整的)、问题只有一行时下方有一行空白、流式输出内容的汉字显示为乱码等问题,最终实现了真正的流式API调用,通过修改AIService,新增streamAIModel方法,实现了流式响应和实时解析数据,AI一开始生成内容就立即显示,用户能更快看到回答开始,使用起来更流畅了,并且测试发现思考过程也可流式输出
3、至于汉字显示为乱码,是因为之前的逐字节处理流式数据,但UTF-8编码的中文字符,一个字符能占用2-4个字节,这就会导致中文字符被截断,从而显示为乱码
4、有意思的是Cursor竟然从我发送的全是乱码的AI回答内容中看出了我真实的问题,并在修改代码后问我“关于您提到的OpenRouter vs Anthropic官方API的对比,这是一个很好的技术选择问题。如果您需要进一步的建议或想要实现特定的API集成,请告诉我!”
5、用百度云千帆的DeepSeek-R1-250528写了一个斜体字Markdown语法正则表达式,试试看能否解决备忘录预览界面斜体字无法正常渲染的问题,测试发现没能解决,斜体字依然无法显示为斜体
6、AI回答内容中的表格一直无法正常渲染,特别像是仅仅把表格中的文字复制出来,根本不像个表格,于是询问Cursor能否用类似CodeBlocksView的形式,创建一个单独的文件来渲染AI回答内容中的表格?Cursor创建表格渲染组件,包含表格解析器TableParser、表格视图TableView、表格渲染视图MarkdownWithTablesView
7、创建新文件之后,经历了多次测试和修改,仍然无法正常渲染,包括看不见我提出的问题,看不见AI回答中的文本内容(基本上除了表格之外,其它的对话内容都看不到,但深度思考内容和参考链接区域没有受影响)等等,多次添加调试信息、反馈调试信息后仍然无果,决定发起一个新的Cursor对话再试试
8、看了一眼Cursor网站的DashBoard,出现了“Analytics are currently degraded and showing incomplete data. We’re working on resolving this issue. You can subscribe to updates here.”这样的提示,看来Cursor终于发现了数据统计功能的问题
9、询问Cursor发现当前AI问答内容全都是在使用新创建的MarkdownWithTablesView来渲染,和我理解的不一样,我希望的是在AI回答中有表格时使用MarkdownWithTablesView来渲染表格,在AI回答中有代码块时,使用MarkdownWithCodeBlocksView来渲染代码块,于是让Cursor创建了一个新的组件UnifiedMarkdownView来统一处理文本内容,并修改MessageView来使用分离的渲染逻辑,这样避免了功能冲突,可以看到AI问答中表格以外的其它内容了
10、但UnifiedMarkdownView对普通文本的渲染使用了简单的Text组件,丢失了Markdown渲染效果,后续还是要换成NSTextView,以实现良好的Markdown渲染效果、文字选择、右键菜单等功能,明天再完善UnifiedMarkdownView

DevLog:2025年9月5日

1、继续测试和优化体验,前两天盘了下各个API平台的余额,发现百度云千帆和硅基流动上还各有五六十块钱,先用硅基流动的API来测试NoteWith的AI对话功能了
2、首先就是在添加模型时,硅基流动官方文档里提到base url是https://api.siliconflow.cn/v1,但我直接填写这个url之后,在测试时仍然提示404错误,去掉后面的v1就好了,可能是因为之前我让Cursor添加了base url自动补全功能,所以现在只需要填写AI服务的根地址就行了
3、然后是在AI对话中切换模型时,选择AI模型的界面,每个模型都显示了模型的名称和“自定义模型”两行文字,我不需要“自定义模型”,我需要在这个页面看到每个模型的备注和模型名称两个字段的信息,Cursor删除了AIModelSelectorView中“硬编码”的“自定义模型”文字,并且完成了修改
4、接下来优化一下流式输出,发现AI回答内容像是在一段一段地输出,并且在AI回答内容输出之前就会有一条白色的区域,然后“AI正在思考中”前面的加载图标也比较大
5、Cursor表示目前的流式输出回答内容的分块是160字符,减少到了50字符,同时将思考过程的分块从80字符减少到了40字符,输出间隔时间也有缩减,至于在AI回答内容输出之前的白色区域,通过修改MessageView,只有当消息内容不为空时才显示消息内容区域,只有消息有内容时才会显示操作按钮(收藏、复制、删除),避免了空消息占位符显示白色背景区域的问题,然后缩小了“AI正在思考中”前面的加载图标
6、流式输出回答内容的分块还是有点大,还可以再缩小一些,另外由于目前AI回答中的文本内容渲染采用了NSTextView,虽然可以看到渲染后的结果,但语法标记所占的位置都显示成了空格,效果不是很好,这样做的原因是之前想要复制部分回答内容
7、尝试继续完善文本的渲染效果,将语法标记完全移除而不是设置为透明,这次竟然真的搞定了!真是万万没想到
8、然后调整下AI对话的标题,之前已经修改了AIChatView,目前它只负责AI对话详情页,也就是AI对话模块的第三栏,这页左上角的标题目前固定显示为“AI对话”,决定将其改为显示当前AI对话的标题,如果我没有打开任何对话,则显示为“AI对话”,如果我打开了某个对话,就显示当前对话的标题
9、发现AI对话内容(无论是提问还是回答)的底部都有一小条空白,Cursor表示这是因为消息容器的边距和内容区域的边距叠加导致的,稍微缩减了一下,目前显示效果还行
10、在测试时我发现调试信息里很早就已经出现了API返回的回答内容,但迟迟不见AI对话界面显示回答内容,猜测可能是API返回回答内容之后,先用MarkdownWithCodeBlocksView完成渲染,再流式输出到AI对话界面,实际上是API返回完整回答(AIService),然后分块流式输出(AIViewModel),再实时渲染(MessageView+MarkdownWithCodeBlocksView)
11、这不是真正的流式API,而是完整回答后模拟流式输出,由于这种方式每次内容更新都会重新渲染整个Markdown内容,可能会在长回答时造成性能开销,导致渲染闪烁(特别是复杂格式),Cursor建议使用真正的流式API,实现增量渲染(只渲染新增部分),并且缓存已渲染的组件,避免重复解析

DevLog:2025年9月3日

1、参考Xcode的建议和Cursor的解释,对项目进行了死代码剥离(Dead Code Stripping),Cursor称这是一个编译优化功能,可以移除未使用的代码和数据,减小最终应用程序的大小,提高应用程序的加载性能,并且这是一个安全的优化
2、继续调整细节,比如将备忘录中的“笔记”替换为“备忘录”,和应用中备忘录模块名字保持一致,搜索界面按钮的顺序调整和文字修改,删除NotesListView也就是备忘录列表中未被使用的搜索功能,等等,让代码更干净一些
3、继续想办法解决从NoteWith还是手机应用时就一直存在的老大难问题:备忘录,询问了Cursor,有没有一些比较好用的Markdown编辑器,可以替换掉目前正在使用的NSTextView,Cursor给我推荐了SwiftUI Markdown、MarkdownUI、AttributedString+Markdown解析、以及MarkdownEditor、RichTextEditor两个第三方开源组件、和WebView+JavaScript方案
4、选择了第一个方案,但Cursor建议将现有的单视图编辑器改为双视图模式,即将编辑和预览分开,在编辑时可以实时更新预览,再具体一些,它推荐内联预览模式,可以同时看到编辑和预览,上面是编辑区域,下面是预览区域,可以展开/收起、可以拖拽调整高度,先试试看
5、修改过程中发现编辑区域已经显示了渲染效果,但预览区域显示的是未渲染的效果,这是因为之前创建的WYSIWYGMarkdownEditor是一个所见即所得编辑器,在编辑时就已经渲染了Markdown,按照Cursor的建议替换成了TextEditor
6、测试发现预览界面依然存在一些Markdown语法标记,可能是因为MarkdownRenderer不够完善,于是让Cursor修改,之后又是漫长的修正MarkdownRenderer的过程,因为Cursor在修改过程中认为之前的MarkdownRender太过复杂,于是删掉、重新创建了一个
7、目前应用内包含了两个Markdown渲染器,一个是AI对话使用的MarkdownWithCodeBlocksView,一个是备忘录使用的MarkdownRenderer

DevLog:2025年9月1日

1、今天继续完善应用细节,先从拆分待办事项列表为单独文件开始,将待办事项分组拆分为单独的文件,并且参考备忘录界面的布局,使用HSplitView,可调节宽度,最小宽度200,理想宽度300,最大宽度400,这样NoteWith的三大模块布局就一致了,并且更便于后续维护
2、Cursor陆续创建了TodoGroupListView(分组列表视图)、TodoItemListView(待办事项列表视图),之后重构TodoListView以使用HSplitView,删除其中重复的组件定义,这样TodoListView就成了主视图,并使用HSplitView组合两个子视图
3、多次调整细节后,三个列表的样式基本一致了,同样的列表宽度(最小、理想、最大、默认宽度)、同样的标题位置、同样的分割线、同样的右侧界面顶栏高度、同样的新建按钮,这样在细节上更加统一了
4、今天Cursor的响应速度变得好慢,频繁出现We‘re having trouble connecting to the model provider.的提示,需要反复点击Try again,等待几分钟之后虽然理解了我的意图,执行起来也非常慢,但再重启一次之后好像速度快了很多,看来可能是我两天时间没有使用,但又一直没关导致的
5、Views/Common目录下的ErrorWrapper文件不知道是干啥用的,让Cursor确认了下,这是一个未使用的错误包装器类型,可能是上次对项目架构进行重构时创建的文件,但现在没有使用,于是让Cursor删掉了ErrorWrapper,同时也删掉了重构指南文档REFACTORING_GUIDE.md
6、还得让Cursor记住在创建新文件之后要将其添加到项目中,只创建文件、不添加到项目就开始构建测试的问题,已经出现过多次了,于是在Cursor的设置中添加这条Rule,看样子以后遇到类似的频繁出现的问题,还是要明确提出,才有机会被识别成Memory,就会更容易添加

DevLog:2025年8月29日

1、首先让Cursor把深度思考内容的底色换成浅灰色,目前的颜色在AI对话界面中略显突兀,因为提问和回答内容都改成了白色
2、需要继续优化AI回答内容的Markdown渲染效果,渲染后的内容能否不以空格替代语法占的位置?比如加粗的文字前后都有两个空格,Cursor表示在Markdown样式应用的过程中,代码使用了NSColor.clear来隐藏语法标记,但这只是让语法标记变透明,并未真正移除它们占用的空间,需要用字符串替换来真正移除语法标记
3、但测试发现使用字符串替换的效果不好,回答内容被截断,且原本使用了同一个Markdown语法的内容,部分文字有渲染效果,部分没有,尝试用属性应用而不是字符串替换,一顿操作之后,又回到了之前的效果,渲染后的内容还是以空格替代了语法标记占的位置,又是一个悬而未决的问题
4、如果改用SwiftUI的Text来渲染AI对话内容,会失去文本选择功能、失去右键菜单、文本搜索等高级文本交互功能,Markdown渲染也会有限制,还是继续保持目前的NSTextView吧
5、发现在AI对话列表中点击右键修改标题时会弹出弹窗,可以在弹窗里输入新标题,但弹窗上方一直有一个空的icon,之前也修改过多次,但删不掉,于是要求改成点击右键修改标题,直接在对话标题位置修改、回车确认,修改过程中发现AIChatSessionListView和AIChatView在功能上有一些重叠,Cursor分析后发现AIChatSessionListView没有被使用,AIChatView中包含了了会话列表和聊天功能,于是决定把会话列表相关功能从AIChatView中迁移到AIChatSessionListView里,这样更便于后续对聊天功能和列表功能进行分别管理,然后修正了导航栏消失、部分界面变成四栏布局等问题
6、接下来需要统一一下AI对话列表和AI对话之间、备忘录列表和备忘录详情之间的分割线样式、底色样式,选中样式,以及拖动调整比例的功能,在实现这一需求的过程中,将ContentView中有关AI对话列表功能完全移动到了AIChatSessionListView中,这下ContentView就只专注于导航和界面切换了,减少了跨组件的状态传递,符合单一职责原则
7、然后统一了两个列表的默认宽度(最小200、理想300、默认300、最大400)和样式(首次打开和切换时不选中任何一条内容、每个条目都不需要用圆角,翻译一下,正确的说法应该是移除自动选中和圆角设计)
8、发现在Views/Notes/Components文件夹下有两个文件,SearchBarView和EmptyStateView,但不知道这两个文件现在还有没有用,这是之前使用UserDefaults来存储数据时,Cursor拆分的组件,现在NotesListView里已经有了重复的组件,SearchBarView用于在备忘录中搜索内容,EmptyStateView是空状态显示组件,Cursor建议删掉这两个文件,我觉得目前这俩文件好像也没啥用了,甚至这两个文件都没有被项目文件引用,删完之后项目结构更加整洁了
9、AI对话和备忘录列表修改告一段落之后,我又开始看待办事项分组列表,询问Cursor后发现这个列表不是单独的文件,是TodoListView文件的中的一个组件,并且备忘录界面使用了HSplitView,可调节宽度,待办事项界面使用了HStack,固定布局,虽然备忘录分组管理的功能完整,但界面布局和AI对话、备忘录列表不一致,还是决定以后要改成一致的

DevLog:2025年8月28日

1、本周着实有点忙,这两天一行未改,先继续修正AI对话内容显示不全的问题,现在只显示一行或者几行,需要滑动才能看到全文,Cursor认为这是一些文本显示组件没有正确设置高度约束导致的
2、还没测试,有点纠结为什么每次新打开一个Cursor对话,就会在修改后尝试直接启动应用,每次都需要我跟它强调下不要直接打开应用,构建下看看有没有编译错误就行,然后在Cursor设置的Rules&Memories中发现了它可以根据过往对话内容学习我的偏好,并且列出了我的这项要求“The user prefers that the assistant not open the application automatically”,果断同意
3、查看已保存的记忆时,发现其中还有一条“用户要求每次构建时,默认使用iPhone 16模拟器,除非用户单独指定其它机型”,稍微修改了下,增加了“在构建iOS应用时”
4、继续测试,发现仍未解决,Cursor继续修改了文本容器的配置、文本视图的垂直调整大小设置等等, 但未解决问题,Cursor再次提出要用Swift的Text组件来替换NSTextView,在确认不会影响备忘录(只修改MarkdownWithCodeBlocksView,不修改备忘录使用的渲染组件)之后,我同意了替换
5、现在AI问答的内容可以完整显示了,但无法选择回答的内容了,且有部分Markdown语法的渲染效果不太好,比如链接不能点击直接打开、同时应用加粗和标题语法的内容仍然会看到语法标记等等,于是让Cursor检查一下还有没有其它的语法渲染效果可以优化一下
6、Swift的Text无法实现文本选择,还是回到了NSTextView,然后AI问答内容又不正常显示了,所有的AI问答内容都只能看到一行,继续修改,多次修改后终于可以同时实现问答内容全部显示、文本选择和Markdown渲染了,发现在和Cursor对话时,问题描述要尽量详细,并且每次修改后有什么变化都要一起告诉它,便于它判断上一步的修改方法是否正确,让下一步的修改更有针对性
7、虽然达成了上述目标,但用户消息和AI消息的一直有白色的底色,多次修改也去不了,于是换个思路,将用户消息和AI消息的浅绿、浅蓝底色统一为NSTextView的默认底色,再调整了间距等细节
8、今天到此为止了,明天继续优化Markdown渲染效果,看能否去掉隐藏的Markdown语法占据的位置,现在回答内容里的空格有点多,然后把默认行间距调整为1.2倍,现在排版有些太紧巴了
9、另外吐槽一下,最近遇到Connection Failed提示的次数有点多

DevLog:2025年8月25日

1、接下来优化文字选择相关功能,我的目标是可以选择AI对话内容中的部分文字,测试发现目前的NoteWith在选择AI对话内容的部分文字时,无法同时选择掺杂了了不同Markdown语法的内容,比如同一行文字里如果既有加粗的文字也有普通文本,就无法选择,如果这一行文字只有H3或者普通文本,就可以选择
2、Cursor理解了我的需求,但没完全理解,它还在延续上周对备忘录功能的修改,表示当前的WYSIWYG Markdown编辑器通过隐藏Markdown语法标记(将颜色设置为透明)来实现视觉效果,这回导致文本选择问题,因为不同的Markdown语法被分割成了不同的文本片段,于是Cursor主要修改了NoteEditView文件,改进了文本视图配置、添加文本存储代理、实现NSTextStorageDelegate、改进选择范围处理,测试发现备忘录中的内容的确可以跨行、跨语法选择了
3、但其实我是想让Cursor处理AI对话中文字内容无法跨Markdown语法选择的问题,在和Cursor明确后,它修改了MarkdownWithCodeBlocksView(其中使用NSTextViewWrapper来渲染各种Markdown元素),创建了新的ImprovedMarkdownTextView(实际名字是OptimizedMarkdownTextView),使用单个NSTextView来渲染整个文本内容,并删除旧的MarkdownLineView结构,修改过程中甚至还直接删掉了整个MarkdownWithCodeBlocksView,因为Cursor觉得它太复杂了?
4、Cursor重新创建了MarkdownWithCodeBlocksView,让整个Markdown内容在一个NSTextView中,但实测发现AI对话内容无法正常渲染,且应用非常卡顿,在不同对话间切换时甚至会卡死,原因可能是过多的调试输出、复杂的正则表达式处理、频繁的文本存储更新、重复的样式应用等,之后测试时发现AI回答内容无法正常渲染,有的看不到任何回答,有的会显示在一个小框里,没有展开显示,不过现在已经可以跨语法选择了,还是有成果的
5、截了多张AI回答以小框显示的图给Cursor之后,它判断可能是NSTextView的高度没有正确设置,需要让NSTextView能够根据内容自动调整高度,修改一轮之后问题依然存在,甚至还差一点就给我替换成SwiftUI的Text视图,赶紧拦住,后面重开一个对话再修改这个问题吧

DevLog:2025年8月22日

1、从7月23日首次付费到昨天,已使用Cursor编辑了90511行代码,马上突破10万行
2、我发现在修改待办事项和编辑AI模型时有一个共性的问题:选一条AI模型或待办事项,点编辑时,会出现一个小的空白弹窗,选另一条AI模型或待办事项点击“编辑”时才会出现编辑窗口,之后就能正常编辑所有的AI模型和待办事项了,看看是不是AIModelSettingsView、AIModelManangementView、TodoDetailView这几个文件的问题,另外AIModelSettingsView里面为何还有针对gpt-4、gpt-3.5-turbo、deepseek-r1、claude-3的图标和颜色设置?我不需要这些预置的设置,模型由用户自行添加就可以了
3、Cursor表示根本原因在于Sheet逻辑显示不正确,可能是这三个文件使用了isPresented和if let的组合,当第一次点击编辑时,状态变量可能还没有正确设置,导致显示空白弹窗,同时也删除了预置的模型设置,问题顺利解决
4、从代码来看,AIModelSettingsView、AIModelManangementView,这两个文件的功能好像有些重合,询问Cursor后发现前者未被使用,且是一个独立的弹窗界面(可能是在AI对话界面选择模型-管理模型时的弹窗,但之前已经去掉了这里的“管理”按钮),后者正在SettingsDetailView中被调用,即设置-模型管理,于是让Cursor删除了冗余的AIModelSettingsAView文件
5、接下来让Cursor给AI模型管理界面添加一个测试功能,点击测试按钮可以测试能否正常响应,这样可以避免信息填错但一时未发现影响使用的情况,Cursor直接在AI模型管理界面每个模型的右侧增加了测试按钮,并且用颜色来区分测试状态,橙色为测试中,绿色为连接成功,并且显示响应时间,红色为失败,测试了下目前我添加的四个模型,deepseek V3响应时间最长,1373ms,火山方舟平台的deepseek r1响应时间最短,244ms,来自OpenRouter的claude 3.7 sonnet响应时间竟然仅有253ms,还是很让我惊讶的
6、改完上面的几个小问题之后,继续测试和完善待办事项相关功能,我发现“编辑待办事项”界面的优先级设置有八个按钮(包含文字和图标),但是不是只有四个分级?比如我点击文字“普通”,对应的优先级是紧急,我点击文字“低”,对应的优先级是普通,另外,我需要去掉“事项标题”、第二行“优先级”、“选择分组”这些文字,有点多余了,Cursor表示之前使用的是segmented样式的Picker,可能导致显示8个按钮且对应关系混乱,改成了自定义按钮样式,确保只有四个优先级,并且简化了界面上的说明文字,这样界面就更简洁了
7、接下来是截止日期设置的优化、添加重复频率功能,目前截止日期并非强制要求填写,但我需要必须填写截止日期,并且需要重复频率功能,也添加到这个页面,和选择日期的功能放在同一行,重复频率包含每天、每周、每月、每年,只要选择了重复频率,就要在待办事项列表中体现重复频率
8、发现新建待办事项和编辑待办事项两个视图好像界面不一样,但功能是一样的,实际上新建待办事项对应的文件是AddTodoView,编辑待办事项对应的文件是TodoDetailView,于是要求Cursor也修改了另一个文件的优先级选择按钮样式,并打开两个文件,手动对齐了下界面上的文字显示效果,但感觉还是略显杂乱
9、还有一个问题,即使只有一条截止日期是今天的Todo条目,也会在待办事项页面右上角显示1逾期、1今日,我需要的是真正过期的Todo条目,比如截止日期是昨天的Todo条目,才被判定为逾期条目,Cursor表示问题在于overdueItems的计算逻辑,同时还修正了overdueTodoCount的计算逻辑、isOverdue方法
10、然后调整分组相关逻辑,要求每次创建新的待办事项时,都默认选择“默认”分组,编辑待办事项时,显示当前这条待办所在的分组
11、剩余其它功能规划:1.可以选择AI对话内容中的部分文字并进行复制等操作 2.完善设置中的导入/导出功能,支持将外部内容导入到备忘录,支持将备忘录导出成txt或md,下周再说