Local Native 2021 SoC 总结 Blog

说起来这是我的公开的第二个Rust项目,第一个还是去年大四上学期和朋友一起做的Bevy游戏项目(我们还有一个项目正在做,但是因为我最近实在是太忙了,所以没有参与进去,感兴趣的可以参与一下:https://github.com/rgripper/village-sim )。我很感谢这两次机会,让我有足够的时间和精力去深入对Rust的学习和了解。这次总结,将会从三个方面来概述。

iced和Rust

Local Native的跨平台桌面端使用的是iced来写的,iced很好用,概念抽象的很简单,如果你习惯上了iced的各种抽象,你会感受到Rust作为高级语言来写的快感。同时官方社区也很有爱,有各种问题提了issue或者去官方的群里问,很快就会有回复。

但是现阶段的iced并不完美,仍然有很多缺陷,比如没有动画支持,没有富文本支持,没有官方的多语言支持,以及各种控件太少了,这些都是官方正在竭力去补全的,特别是它还选用了wgpu作为渲染后端,我相信在不远的将来,它会是一个很好的简易跨平台应用解决方案(style还是太难写了,如果有热重载和对style进行重构,iced会更强大)。

而iced使用的语言就是Rust,说到Rust,很想分享一下自己的学习经历。2018年初的时候,我只会python,而且还是超级菜的那种。那个时候听到不少言论,说除了python以外应该再学两门编程语言,一门足够底层,一门足够工业,前者我在知乎被各种帖子的鼓吹后(特别是Rust编程之道的作者,张老师),选择了Rust,后者因为学校的课程中就包含了C#和Java,所以没有特意的去学习。

刚开始接触Rust的时候:“呀,这些概念,好严谨,好透彻,完全能够从Rust里感受到各种设计的因果关系,实在太强了!”(可能是我其他语言接触的太少的原因,只会python的我被Rust深深吸引了)。

随着深入的学习了解,开始着手各种项目练手的时候,被编译器各种教做人:“生命期怎么这么难呀,范型、trait限定的写法好吓人呀,异步状态机的什么鬼,所有权咋这么难用!”这个阶段持续时间有长有短,每一个问题都能单独拿出来说,每次将这些困惑的问题解决掉,消化掉的时候,会从中汲取极大的满足感。我的建议是,多看几家的文档,教程,找出合适的自己的,多和群友交流沟通,一定有让你满意的答案。

现在的阶段,代码写起来很顺畅,编译通过很安心,逐渐的反而会去想为啥这种错误编译器没有报错之类的事了(写这个项目的时候,有用到as,不少地方出现了溢出的问题,所以如果习惯了被Rust编译器保护,突然来这么一下,感受还是挺奇妙的)。

Local Native

这次的项目我负责的是整个跨平台的前端开发,同时负责后端依赖更新到最新版本,保证后端功能正常。项目的架构比较常见,是通过json-rpc的方式在前后端进行数据交换,前端的开发在熟悉iced之后,进展还是很快的。整个过程有充足的时间让我学习和了解iced,以及深入Rust,也因此,整个项目实际上是进行了一个较大的重构,重构之后的代码更简洁,性能上也更好了。

重构的过程中找到了比之前更好的实现方法,以及各种更优雅的写法,最熟练的还是对迭代器的使用吧,长时间的各种对迭代器的使用,已经完全被这种方式给套牢了,好用确实是真的好用。

也因为有考虑过上架苹果的AppStore和微软商店,所以做了打包,打包过程比较容易,这得多亏了tauri团队对Rust社区的贡献,再次感谢!

比较麻烦的是和浏览器扩展做初始化吧,几乎有两周的时间在弄这个,虽然这期间有其他事耽误了一下,但因为多个平台的多个浏览器不一致,这部分还是写的比较麻烦的。

另外就是后端同步过程中出现的一些问题,调试也听花时间,知道截止发稿,还有个安卓11同步崩溃的问题没解决,这周有空可以搞一下。

个人总结

今年我毕业了,同时现在也找到了一份Rust开发的工作,是做substrate开发的。最近正在看文档之类的,多亏了早年被各种Rust英文教程的轰炸,让我现在看substrate文档没多大压力。

我很感谢这次的实习机会,因为如果没有这次的机会的话,我不一定能找到编程相关的工作。我本科是学化工的,做毕设期间老师也劝我找份化工的工作,说去厂里时间很充裕,足够我去研究编程之类的东西,不过最后还是没去,最大的原因还是这份实习吧,我想着如果能把这部分工作做好的话,找份Rust工作,应该还是可以的。

在之前项目快结尾时,我们Local Native团队参加了Dweb社区举办的项目分享活动,也是那个时候认识了现在的leader,经过交流之后加入了团队。团队对我最大的诱惑是leader对开源项目的态度吧,leader很鼓励我平时多参加开源社区,如果不出意外的话,在substarte开发能稳定进行之后,bevy之类项目会再搞起来。

说点牢骚话,此前在群里看到群友发的一句话,说有些人代码出道即屎山。一不小心就把自己带入进去了。抛开我Bevy的项目不谈,那个是和朋友一起写的,那个时候确实很菜,同时当时Bevy真的资料很少,所以这个就不深究了。这次的项目,现在的版本其实重构了一次的,在之前还有个从demo写过来的版本,重构过程很美好,此前的很多写法确实可以用屎山形容,最终呈现出来的代码还算满意,但有些地方还是没有处理好,比如绘制日期过滤器,交互上还可以加强,视觉上也是;比如主题风格,对颜色把握确实不够,还需要再好好调整。最终的教程,就是在这样的情况下写出来的,所以听到这样的话的时候,心里还是蛮愧疚的,不过,这些在未来都会被尽可能的解决,所有的教程及代码,都会维护到iced出1.0版本,至少会有个三到四年时间吧,对教程有各种需要改进的都可以提issue,或者给我发邮件:cupnfish AT icloud.com

关于cupnfish,这是一个很中国的名字,杯多鱼,类似的还可以cup1egg,cup2dog如果以后我真用bevy做自己的游戏项目了,这些就当作隐藏彩蛋吧。

Local Native 2021 SoC 计划 Blog

使用iced实现LocalNative的跨平台桌面GUI,大致上要实现electron版本的基本功能,总结如下:

  • 支持搜索、查阅note
  • 支持tag显示,并可以点击tag进行查询
  • 支持tag数量显示,并且可以通过点击tag的数量进行查询
  • 支持多语言(仅需要考虑中英文)
  • 支持通过sqlite3文件进行同步
  • 支持扫描二维码进行同步
  • 支持输入目标ip地址进行同步
  • 支持note生成对应url二维码分享内容
  • 支持通过时间段过滤搜索note

除了以上electron版本已经支持的功能,可能还会支持以下功能:

  • 支持明暗主题切换
  • 支持多个渲染后端选择

目前大部分代码已经完成了,还有少部分的todo需要完成或者舍弃,除了上述todo以外,我更想和大家分享在iceddruid之间,为什么最后选择了iced,这部分没有太多涉及到技术层面的东西,更多是对使用体验上的一些考量。

druidiced是Rust社区中较为知名的GUI框架,其中iced更是以其好用的api从而俘获了大部分开发者的青睐(从Github的star数量上就可见一斑)。二者之间也有一定的关系,在介绍关系之前会大致介绍一下二者是在什么样的情况下被设计出来的。

先谈druid吧,正如druid的Github项目主页上Readme所言,目前驱动druid开发下去的主要动力是runebender,一个字体编辑工具,依托druid的跨平台能力,该编辑器在不同平台上有着较好的体验。同时如果体验一下这个字体编辑工具,能够感受到druid足以完成大部分图形界面客户端开发中的难点,也就是说druid有足够的能力去实现一个跨平台的复杂图形用户界面。目前druid的渲染后端是pietdruid的作者自己有意愿将wgpu作为druid的可选后端,但是希望wgpu能够足以胜任这份工作时才会去做出这种改变。pietwgpu的优缺点在于piet更轻量,在低性能设备上运行的时候,目前来说体验上是要比wgpu要好的,wgpu更像是一个游戏渲染后端,需要gpu有一定的支持,同时由于当前wgpu对OpenGL的支持并不是很好,从某种角度上来说Wgpu对老的设备并不是很友好(新版本的wgpu已经对OpenGL有了初步支持)。

iced的初衷就更简单了,作者本身有一个游戏引擎需要用到GUI工具,因此自己手动写了一个,谁想到游戏引擎没火,iced却火了起来,关于iced开发上限可以看看Project Showcase,其中较为出名的一定是这个:Cryptowatch Desktop,相对于druid的渲染后端pieticed则在一开始就选择了wgpu作为自己的渲染后端,当然iced自己宣称是渲染器无关的GUI工具,在后续官方确实也添加了对OpenGL的支持(直接通过glutin,一个Rust的OpenGL绑定,而不是通过wgpu)。

理解了两者开发初衷上的不同之后,你就能够感受到两者对一些理念上有着明显的不同,比如就成熟度而言,druidiced更像是一个完整的GUI方案,你能想到的大部分功能都有了足够的解决方案,虽然有些还在完成中,但是你已经能直接能用到很多简单好用的API了,相对于iced是一个游戏GUI框架的考量,你能在编译之后的程序体验上,感受到druid真的像是一个为了各个平台而设计的GUI工具,说的具体点,iced到目前还没有一个支持各个平台的菜单控件(对,你没看错,居然连菜单控件这种很常用的东西都没有),而durid已经完全对各个平台有了不同的,完全绑定平台原生的菜单控件,并且 API设计上也十分好用。druid已经有了一个可用的多语言支持(切换语言还没有实现,不过已经很快就会实现了),而iced甚至连解决在输入框里打中文,输入法文本悬浮框会飘出应用程序的PR还没有合并。

那说了这么多,全是druid的优点,那为啥最后还是选择了iced呢?

因为iced更简单,这是最重要的,这次SoC的计划除了实现那个GUI之外,其实还有一个更重要的事,就是实现一个项目实践的教程,最为教程的最佳选择,iced绝对当仁不让,你能从这次项目实践教程中体验到Rust开发如此有趣,在初步掌握了iced之后,你便能够将你的所有想象力轻易表达出来。

不仅仅是简单这么个有点,在一定程度上由于iced的渲染后端现在是wgpu,而druidpiet的原因,在一些场景下性能是iced的最大优势,你会感受到你的App是如此的丝滑(虽然iced还没有动画支持😀)。同时iced和异步框架的深度融合,在开发中会让你更为舒适。

总结下来就是以下三点,让我最后选择了iced,而不是druid

  1. iced更简单
  2. iced渲染后端是wgpu
  3. iced足够完成当前的需求

既然提到了事件处理,我还是要夸一下iced的,如果你看过iced的示例代码,会发现在iced的update逻辑里要求你返回一个Command枚举,这个Command你可以将你想要执行的异步操作直接给它调用,就能够得到一个性能还算不错的应用程序。而druid的这部分代码要怎么处理呢?如果你熟悉并发中channel的概念,你在使用druid的事件处理时会理所当然的想到,这不就是channel么,通过一个类似channel的形式,将信息传递到一个集中处理该信息的地方,使用起来实在是不太优雅。

在灵活性上,iced让你写起来完全像是在写elm(果然不愧是受到elm启发),而druidLens概念足够把很多人给劝退了,所以单单是在这些方面,就足以让我为了接下来的教程,而选择iced,而不是durid

好了既然说到教程,就把教程的整体放在这里:

  • 序,从localnative_core获取GUI需要用到的数据
  • 第一部分,实现展示一个完整的note
  • 第二部分,手动实现一个wrap控件
  • 第三部分,手动实现一个timeline控件
  • 第四部分,如何打包

大概的内容就这么多,其中在序这部分会着重讲一下开发环境的搭建,其中最为冗长的是第一部分,实现一个完成的note,这里又需要划分为三个部分来讲,最后一个打包部分只会讲到windows平台的,因为我没有mac,所以mac打包还需要各位自行尝试。大概内容就是这些,更新速度的话,其实代码写到这里,除了第三部分的timeline控件没写,基本功能都实现了,都是一些小问题需要去解决。

最后,说点我个人的感想吧,这次SoC我个人还是十分珍惜这个机会的,我很喜欢Rust,但是现在的Rust工作环境大概七成是区块链,剩下的三成还有不少是搞分布式、数据库的,所以相对于这些而言,居然有一个GUI开发的Rust实习机会,对我来说实在是太令人高兴了,再加上还是一个开源项目,又着实令人兴奋一把。从接触Rust至今,已经快两年半的时间了,但正是因为Rust十分有趣,坚持到现在已经是一种享受的姿态,这次教程的受众主要还是那些对Rust感兴趣,想要动手写点小工具之类的人,只需要知道语法是在表达什么就够了,所有权生存期这些东西交给编译器去锤炼你吧,希望大家喜欢会喜欢这个系列。

Local Native 2021 Summer of Code Team

提前完成了 Local Native 2021 Summer of Code 团队的组建。

时间线

调整和提前了主要时间线:

日期事件Note
April 3 - 24熟悉代码和框架,写计划 Blog
April 24 - June 5code() and debug() and document()June 5 Evaluation
June 5 - July 3code() and debug() and document()
July 3-17写总结 Blog 和 educative 教程文档July 17 Evaluation
TBDeducative 审核上线

成员和主要目标

  • Cupnfish

    • 实现并取代目前用 Electron 实现的 Local Native 桌面程序
    • 实现可使用的 Windows 发布版本
    • 在 localnative.app 网站 Blog 上写要在 educative.io 上加入 2021 SoC 新实现的内容的中文版
    • 写2021 SoC计划 Blog 和总结 Blog
  • hill

    • 协助实现代码和技术文档等工作
  • Conan

    • 项目管理达成目标:组织会议,在 localnative.app 写项目周报,完善文档。
    • 在 educative.io 上加入 2021 SoC 新实现的内容(翻译和完善)
    • 建立并完善 gitlab CI/CD 流程
    • 完善Browser Extension UI
    • 编写 Rust 代码

Local Native 2021 Summer of Code - Rust GUI

2021-03-20 更新

目标

推进 FLOSS 项目 https://localnative.app 的 Rust GUI 代码和相关的 educative 教程的编写, 招募代码, 文档和教程贡献同学。

  • Rust GUI 编程
    • 用druid 和/或者 iced 框架 设计, 实现并取代目前用 Electron 实现的 Local Native 桌面程序
      • 尝试用 druid 实现QR Code
    • 尝试支持 Windows 发布版本 (尝试用Rust修改注册表)
  • 给 educative.io 上相关课程加入新实现的内容
  • 写计划Blog 和 总结 Blog, 完善文档

时间线

借鉴G家2021 SoC的时间线

日期事件津贴
March 29 - April 13申请
April 13 - May 17确定申请结果
May 17 - June 7熟悉代码和框架,写计划 Blog
June 7 - July 18code() and debug() and document()July 18 First Evaluation 45%
July 18 - August 16code() and debug() and document()
August 16-31写总结 Blog 和 educative 教程文档August 31 Final Evaluation 55%

津贴

欢迎有Rust经验的同学申请!

备注 SoC 发送

  • 简历
  • Rust经验/作品
  • 期望津贴

Local Native iOS v0.4.1 发布, with SwiftUI

prelude

It has been another few months since last Local Native v0.4.1 release, which was not able to include iOS version due to crashing in TestFlight. Now iOS v0.4.1 is finally released!

the bug?

I still could not identify how the crash occurs by staring at the crash log.

the fix.

It turns out the fix is to rewrite iOS code in SwiftUI.

Fortunately thanks to existing solutions for data flow, search bar, QR code, hiding keyboard, the rewrite is very pleasant and code becomes more concise by removing storyboard and view controllers.

One thing maybe a drawback from previous iOS version is that the bookmark note text is not selectable.