Rust学习的关键资源

⭐️ Rust-Learning repo https://github.com/ctjhoa/rust-learning

官方教程(号称The Book)https://doc.rust-lang.org/stable/book/
中文版 https://kaisery.github.io/trpl-zh-cn/ https://rustwiki.org/zh-CN/book/

Easy Rust 用比较简单的英语写的教程,内容也较简单一些(入门)
https://dhghomon.github.io/easy_rust/Chapter_0.html

菜鸟Rust教程 https://www.runoob.com/rust/rust-tutorial.html

Rust By Example https://doc.rust-lang.org/rust-by-example/hello.html
⭐️ 中文版 https://rustwiki.org/zh-CN/rust-by-example/index.html

⭐️ Rust Cookbook https://rust-lang-nursery.github.io/rust-cookbook/

中文版:https://rustwiki.org/zh-CN/rust-cookbook

⭐️ Rust By Practice( Rust 练习实践 ) https://zh.practice.rs/why-exercise.html

⭐️ Rust圣经 https://course.rs/about-book.html

Rustc Book https://doc.rust-lang.org/rustc/index.html

Rust 🦀 and WebAssembly https://rustwasm.github.io/book/

The wasm-bindgen Guide https://rustwasm.github.io/wasm-bindgen/introduction.html

Rust参考手册:

英文 https://doc.rust-lang.org/reference/introduction.html

中文 https://rustwiki.org/zh-CN/reference/introduction.html

Rust 宏小册 https://zjp-cn.github.io/tlborm/

Rust 中的异步编程 https://huangjj27.github.io/async-book/index.html

Rust 秘典(死灵书) https://nomicon.purewhite.io/intro.html

官方API文档 https://doc.rust-lang.org/std/index.html

标准库中文版 https://rustwiki.org/zh-CN/std/

优质Rust项目 https://github.com/rust-unofficial/awesome-rust
中文版 https://github.com/PuzzledAlien/awesome-rust-cn

Rust 中文资源 https://github.com/rust-lang-cn

Effective Rust https://www.lurklurk.org/effective-rust/cover.html

⭐️ RustGYM https://rustgym.com/ leetcode题目的rust解法

⭐️ Rustlings https://github.com/rust-lang/rustlings 官方出品的rust小练习,可以有针对的练习各个语法点

Rust Atomics and Locks:Low-Level Concurrency in Practice https://marabos.nl/atomics/

The Tauri Documentation Work-in-progress https://jonaskruckenberg.github.io/tauri-docs-wip/introduction.html

Comprehensive Rust https://google.github.io/comprehensive-rust/
安卓团队编写的为期四天的 Rust 课程,从基本语法到高级主题,最后一天还会讲到 Rust 如何用于安卓开发。

视频:Rust Linz https://www.youtube.com/watch?v=OhCjnyBc448&list=PL85XCvVPmGQgL3lqQD5ivLNLfdAdxbE_u

视频:The Rust Lang Book https://www.youtube.com/watch?v=OX9HJsJUDxA&list=PLai5B987bZ9CoVR-QEIN9foz4QCJ0H2Y8&index=1

秋游圆明园

圆明园的秋天非常美丽,远远胜过其他季节,推荐九州景区,人少风景也不错,另外在很多地方都能看到松鼠,也是出乎意料。圆明园现在在我心目中的位置可以超过植物园了。

附游览路线推荐:

👣 六只脚轨迹 7436250

徒步:陈家堡-罗锅长城环穿

环穿从陈家堡龙王庙起点开始经过将军楼,鸳鸯楼,罗锅城,大黑岭,回到陈家堡结束。不建议这条路线,主要原因:

第一,碎石太多,会动的石头太多,下山的时候尤为辛苦,除去崴脚摔跤分享,大块碎石如果在下山时滚下也可能砸伤前面的人。

第二,风沙太大,整个路面尘土太多,风极大,需要掌握好平衡,否则风会在狭窄山梁上的人有影响,失去平衡则也有危险。

第三,风景确实一般,长城虽然逶迤巍峨,但整体仍然是穷山恶水。

在下山途中遇到一个如同大号苍耳的植物,果实如同狼牙棒,有鸡蛋大小,自己从未见过,便摘了一个带了回去。

后来有朋友提醒这是否曼陀罗,一搜索果然是这东西,而且还是剧毒,整个植物都有毒,这个果实干了以后会自己爆开,把种子喷出,如果放在家里确实危险,并且有时我们这里还会有小孩来玩,确实如果不明就里留下这个东西是个安全隐患。提醒的朋友居然是看金庸小说认识的曼陀罗,也是很神奇的,确实要感恩神的保护啊!

👣 六只脚轨迹 7441821

人类星光灿烂时——拜占庭的陷落背景资料

1453年5月29日,君士坦丁堡被奥斯曼帝国苏丹穆罕默德二世率军攻破,此后罗马帝国结束了1480年的历史(从公元前27年开始),君士坦丁堡的名称随后仍一直沿用,直到1930年,土耳其将其改名为伊斯坦堡。

罗马帝国分裂

东西罗马的出现始于四帝共治。

西元284年,罗马帝国内乱不断,外敌也纷纷入侵,而且军人专政,干预皇帝废立,所以新皇帝戴克里先上任后,自知一人无力应付奴隶起义及异族入侵,于是把罗马帝国西半部(即意大利、西班牙、高卢、不列颠、中欧、北非)交由其好友马克西米安管治,自己则管治罗马帝国东半部(即巴尔干半岛、东南欧、小亚细亚、巴勒斯坦、叙利亚、黎巴嫩、约旦、埃及)。两人也分别设立副职,并由四人合治国家,史称四帝共治制。

第一次四帝共治 (293-305年)

其后罗马帝国皇帝君士坦丁一世迁都君士坦丁堡并统一罗马,但在西元3世纪至西元5世纪之间东西帝国断断续续的存在。西元395年,最后一名罗马帝国统一皇帝狄奥多西一世立下遗言,把帝国照戴克里先的分法分给自己的两个儿子,东部分给长子阿卡狄乌斯,西部分给幼子霍诺里乌斯,分别治理。西罗马帝国定都梅蒂奥拉努(米兰的古称)。东罗马帝国(后称拜占庭帝国)则定都君士坦丁堡(今伊斯坦堡)。自此之后罗马帝国永久分裂。

476年,日耳曼裔将领奥多亚塞控制意大利全境。西罗马帝国灭亡。

关于“神圣罗马帝国”

800年,罗马教会为了与当时位于东方的东罗马帝国的东正教抗衡,法兰克国王查理曼被教宗利奥三世加冕为罗马人的皇帝,因此被称作查理大帝继承西罗马帝国,从此以后又多一个新的皇室,之后演变成神圣罗马帝国,因此继其之后的神圣罗马皇帝都以继承西罗马皇帝自居。但是这个“复活”的西罗马帝国不论在血统还是语言上,都已与原本的古罗马没有关联了。

东罗马帝国(拜占庭帝国)

从何时开始算东罗马帝国出现,历史学家有两种标准:一是330年君士坦丁大帝建立新罗马、罗马帝国政治中心东移,是东罗马帝国开始的标志。另一主流观点认为,395年最后一位统治整个罗马帝国的皇帝狄奥多西一世的去世,标志东罗马帝国的开始。

名称来历

东罗马帝国的正式名称是Ρωμανία(Rōmanía,“罗马人的土地”或“罗马尼亚”),或者Βασιλεία Ρωμαίων(Basileía Rōmaíōn,“罗马人的帝国”或“罗马帝国”)。这是拉丁语 Imperium Romanorum(罗马帝国)的希腊语翻译,也是其自称[4]。

尽管东罗马帝国的文化和语言大多数是希腊的,但其皇帝和臣民均认为自己的国家就是罗马帝国本身,在从330年到1453年这11个世纪的时间里,不论是“东罗马”或“拜占庭”从来没有成为过这个国家的正式或非正式名称。帝国的居民亦从未将首都新罗马称为“拜占庭城”,或将自己称为“拜占庭人或“希腊人”过,而是直接叫自己为罗马人。

为了与同样自称为罗马帝国的神圣罗马帝国区分开,因此在1453年帝国灭亡前,西欧人将其称为“东罗马帝国”(Imperium Romanum Orientale)。

“拜占庭帝国”这个称呼则是到了1557年才出现的,由神圣罗马帝国的历史学家赫罗尼姆斯·沃尔夫所发明,首次运用是在他所编纂的《历代拜占廷历史学家手稿(Corpus Historiae Byzantinae)》中,他为了区分罗马时代以前的古希腊文献与中世纪东罗马帝国的希腊文献,同时也为了在名称上割裂东罗马帝国和罗马帝国,才引入“拜占庭帝国(Imperium Byzantinum)”的叫法,以此塑造出“神圣罗马帝国”的唯一性。在18世纪之后,因为“拜占庭帝国”这个名词在运用上其实非常方便,能瞬间区分出古代的罗马帝国东部和中世纪的希腊帝国,在经过孟德斯鸠、伏尔泰等人于启蒙运动中的大量使用后,“拜占庭”广泛地被西欧和中欧历史学家所接受。

至于“拜占庭”这个名词的来源,则可追溯至东罗马帝国的首都新罗马,即君士坦丁堡的前身“拜占庭城”,这座城市是古希腊的殖民地,在地理位置上正好又和东罗马的首都重合,因此得名。

东罗马帝国疆域动态演变图

君士坦丁堡

公元330年,罗马皇帝君士坦丁一世在拜占庭建立新都,命名为新罗马(拉丁语:Nova Roma;希腊语:Νέα Ρώμη),但该城普遍被以建立者之名称作君士坦丁堡。在公元12世纪时,君士坦丁堡是全欧洲规模最大且最为繁华的城市。

建城:306-337年

军人出身的君士坦丁一世于306年在不列颠被部下拥立为帝,此后恢复了帝国的一统,并进行了大刀阔斧的改革。他认识到当时的首都罗马无法对东部的边境和军队实行有效的控制,因此决定力排众议,在帝国的东部建造一座新都城。在罗马帝国的东部,先前几位皇帝已经建立了若干座陪都,比如戴克里先皇帝,就把他的行宫设在博斯普鲁斯海峡亚洲一侧的尼科米底亚(今土耳其伊兹密特)。为了给新都选址,君士坦丁一世先后考察了特洛伊、耶路撒冷、萨尔底卡(索非亚)、帖撒罗尼迦(塞萨洛尼基)和尼科米底亚,但是最终选择了当时不甚有名的拜占廷作为新都的城址。

拜占廷位于博斯普鲁斯海峡西岸,这条狭窄的海峡将东南欧洲与亚洲分隔开来。城市本身坐落在一片小山丘上,南边是马尔马拉海,北边是金角湾,东边扼守赫勒斯滂海峡(博斯普鲁斯海峡)的入口,西边居高临下俯瞰色雷斯平原。整个城区宛如一座天造地设的要塞,易守难攻。不仅如此,拜占廷还是罗马帝国重要的军事大道埃格南地亚大道与小亚细亚地区军事公路的交汇点,是通往亚洲的必经之地,也是从黑海前往爱琴海的唯一通路。此外,城北的金角湾是一处条件极佳的自然港湾,全长约10公里,主航道宽约460米,并有多处分支水道,可供船只停泊。自古以来就是世界各地商船汇集的地方,给当地居民带来财富,因此被称为“羊角”(希腊神话中,羊角是丰收和财富的象征)。未来的新都可以凭借一面临山两面靠水的地势防御来自各方面的进攻,又可以利用便利的水陆交通发展商业。

324年,君士坦丁发布命令,兴建新都,并任命重臣着手进行建筑工程的准备工作。为了在最短的时间里完成新都的建设,他还下令建造专门学校,大量培养各类建筑人才。君士坦丁还亲自跑马勘测,圈定城市界标。

经过六年的精心建设,君士坦丁堡正式完工。330年5月11日,君士坦丁大帝宣告定都,并赐予其“新罗马”(Nova Roma)的正式名称。他仿照罗马的模式,将新城划为14个区。此时君士坦丁堡在气魄上仍然与旧都有一定的差距,于是君士坦丁大帝加快了建设公共设施的速度,吸引小亚细亚和本都的居民入住,并于332年5月18日宣布,同罗马一样,君士坦丁堡的食物将向居民免费发放。

君士坦丁堡呈三角状,两面是海,一面陆地,都有城墙保护

1204年第四次十字军东征洗劫君士坦丁堡

对君士坦丁堡最大的破坏来自于第四次十字军东征。

起因是这样:十字军为抵达耶路撒冷圣地,雇用威尼斯共和国的船队来运输部队,但因为内部分歧,使得参与人数远不如预期,许多贵族骑士纷纷求去,十字军因而付不出与威尼斯原订的费用,积欠约三万四千马克,在威尼斯总督恩里科·丹多洛的要求下,十字军将矛头指向东罗马,此时适逢流亡在外的拜占庭皇储阿历克塞四世向十字军求援,要求将皇位从其伯父阿历克塞三世手中夺回,交换条件是愿意支付十字军前往圣地的一切费用与给养,并将东正教会置于罗马教皇的权威之下,十字军因而取得出兵的藉口与正当性,成功于1203年将阿历克塞三世驱逐,被扶植上位的阿历克塞四世为兑现承诺,上台后即开始大肆搜刮,向罗马教会卑躬屈膝姿态深受虔诚东正教徒的希腊人痛恨,阿历克塞四世身旁的权臣阿历克塞·杜卡斯趁机发动政变将阿历克塞四世软禁,并自立为帝,是为阿历克塞五世。阿历克塞五世不打算履行阿历克塞四世与十字军的任何约定,在与十字军谈判破裂后,十字军开始围攻君士坦丁堡。

1204年4月12日,十字军攻陷了君士坦丁堡。

十字军在君士坦丁堡进行野蛮的洗劫,达三天之久,在此期间有许多古代和中世纪的罗马和希腊作品,不是被盗就是被毁。着名的青铜马从君士坦丁堡赛马场被送往威尼斯,装点圣马尔谷圣殿的立面,直到今天还在那里。

君士坦丁堡图书馆被十字军摧毁。十字军虽然曾经宣誓,并且有绝罚(又译破门律,俗称开除教籍、驱逐出教、逐出教会等,是一种发生在宗教内的惩罚行为)的威胁,但还是系统的亵渎这座城市的朝圣地,毁坏或偷窃所有他们能弄到手的东西,什么也没能幸免。

据说,从君士坦丁堡掠夺走的总金额约为90万银马克。威尼斯人收到的款项是15万银马克,十字军收到5万银马克。另有10万银马克为十字军和威尼斯人平分。其余的50万银马克被许多十字军骑士秘密带走。同时,君士坦丁堡的拉丁居民,对1182年的拉丁大屠杀采取报复行动。

此后君士坦丁堡再难恢复往日的繁荣规模。

2004年,罗马教宗对第四次十字军的暴行向东正教会正式道歉。

狄奥多西城墙

即这篇故事中的城墙,总长度5630米,建成时间为408年到413年。

现存遗址

狄奥多西城墙被建成双层城墙,毗邻水沟。内墙以坚固的结构组成,墙厚5米,高12米,外表是经过精心切割的石灰岩块,城墙核心则是以石灰及碎砖压成的灰泥。大约有七至十一条砖带横过结构,每条砖带厚约40厘米,这些砖带不仅是用作装饰,还透过束紧岩面与核心来增强结构的内聚力,并可增强城墙对地震的抵抗力。狄奥多西城墙共有96座城楼,主要都是方形,也有八角及六角形,高18-20米,城楼的间距是55米。每座城楼的顶部也有城垛。城楼内部分为两层,底层通往城内,用作储物,上层可经城墙走道进入,设有窗户以供暸望及投射之用,可利用斜梯登上城墙。

内墙与外墙的空隙

外墙与内墙之间的距离有15-20米,两墙之间的间隙被称为外城台。外墙底部厚2米,在连接外城台处有一些拱形的房间,上方是城垛走道,外墙高约8.5米。从城内可经主城门或内墙底层的后间到达外墙。外墙同样有96座城楼,呈方形或新月形,正好处于内墙城楼间距的中间,起著辅助内墙城楼的作用。连接外城台的房间有窗户,下方有后门,通往外台。外墙的防御力惊人,在1422年及1453年的围城战里,拜占庭帝国及其盟友的兵力不足以守护两层城墙,于是集中兵力死守外墙。

狄奥多西城墙塞律姆布里亚城门处的复原部分,外城墙及内墙都清晰可见,辅有内墙的城楼

护城河与外墙的距离约为15米,形成内城台,内城台有一条沿著城墙延伸的道路。护城河阔20米,水深10米,河内侧有一道高1.5米、有射击口的墙壁,这是君士坦丁堡的第一道防线。

西东罗马教会分裂

罗马教会的首席地位

公元70年,罗马人占领耶路撒冷,基督宗教的中心自然转移到当时罗马帝国的首都——罗马。根据《圣经》记载,罗马很早就有了基督徒,保罗曾给在罗马的基督徒写了著名的《罗马书》,并亲自在罗马居留了二年。根据教会的圣传,彼得是罗马的首位主教。这两位使徒最终都在罗马殉道。因此,罗马教会在初期教会中一直享有极高的威望。在此期间,教宗(罗马主教)亦试图在一些教会事务中扮演权威的仲裁者的角色。325年,在尼西亚召开了基督宗教有史以来的第一次普世大公会议——尼西亚大公会议,在大公会议所颁布的法令中,罗马教会列于各地方教会之首。

新罗马的兴起

330年,罗马皇帝君士坦丁一世迁都拜占庭,将该城改名为君士坦丁堡,又名新罗马。381年,召开了基督教第二次普世大公会议——君士坦丁堡大公会议,将君士坦丁堡教区提升为牧首区,而君士坦丁堡牧首的排名仅次于教宗。451年召开的第四次普世大公会议——卡尔西顿大公会议上通过的第28条法令,将君士坦丁堡牧首提升至与教宗并列的首席地位,但受到当时的教宗良一世的强烈抗议,认为该法令侵犯了教宗的首席权,声称:教宗之所以拥有首席权是因为他是使徒之首彼得的继承人的缘故,因此,拒不承认该法令。

公元4世纪,罗马帝国分裂为东、西两部份之后,罗马主教的地位在西罗马帝国继续得到巩固,但在东罗马帝国,君士坦丁堡主教的地位渐渐上升,与罗马主教常常分庭抗礼。因教义、礼仪、传统、理念不同,双方经常互相谴责。

11世纪发生东西教会大分裂后,东方教会以君士坦丁堡主教(普世牧首)为首,使用正统教会的名称,西方教会以罗马教宗为首,继续使用大公教会的名称。

奥斯曼帝国

1683年奥斯曼帝国最大疆域图。

奥斯曼帝国(奥斯曼土耳其语:دولت علیه عثمانیه‎,土耳其语:Osmanlı İmparatorluğu)是一个存在于1299年至1923年的帝国,国名来自创立者鄂图曼一世。

奥斯曼土耳其人源自于西突厥乌古斯人的游牧联盟。自中亚迁至小亚细亚,日渐兴盛。极盛时势力达亚欧非三大洲,领有南欧、巴尔干半岛、西亚及北非之大部份领土,西达直布罗陀海峡,东抵里海及波斯湾,北及今之奥地利和斯洛文尼亚,南及现今的苏丹与叶门。自消灭东罗马帝国后,定都于君士坦丁堡。所以鄂图曼帝国的君主苏丹以自封的形式,视自己为天下之主,继承了东罗马帝国的基督教文化及伊斯兰文化,因而东西文明在其得以统合。

穆罕默德二世

穆罕默德二世是穆拉德二世的第三个儿子。正如他的外号一样,穆罕默德二世是一个不折不扣的征服者。他在自己的30年统治期间亲率大军远征26次,几乎连年作战。在1453年5月29日攻克君士坦丁堡,从而灭亡了延续一千多年的东罗马帝国,穆罕默德二世把这个城市改为奥斯曼帝国的首都,使奥斯曼帝国成为一个地跨欧亚的大帝国,并且从此控制了博斯普鲁斯海峡。

穆罕默德二世在巴尔干半岛上的征服活动包括1459年吞并塞尔维亚、1460年占领摩里亚、1463年征服波斯尼亚和1479年吞并阿尔巴尼亚。使金帐汗国的分裂王朝克里米亚汗国成为奥斯曼帝国的附庸。1480年,穆罕默德二世进攻意大利,这件事在马基亚维利的《佛罗伦萨史》中有所反映。在安纳托利亚的奥特鲁克贝利战役击败白羊王朝的乌尊哈桑。但他本人却于1481年计划进攻罗德岛时突然死去(有可能是被毒死)。

穆罕默德继位(是为穆罕默德二世)时做的第一件事就是亲自去宫廷处死襁褓中的弟弟,以确保自己的安全。这个苏丹也是将“杀兄屠弟”这一习惯上升为法律的人。他制定了弑亲法:“我的任何一个儿子,由真主选为苏丹,他为了更好的世界秩序而杀死他的兄弟们,都是恰当的。大多数乌里玛已经宣告了这个许可”。这条法律记载在《穆罕默德二世的法律书》中。后世的苏丹都以此为根据为自己的杀兄屠弟行为辩护。

BST Tauri开发笔记(8)sqlite问题

将项目放到windows上试了一下问题多多,主要是sqlite编译造成的(错误代号1181),报sqlite3.lib找不到,按这篇文章解决了一下基本可行:

  1. 到sqlite官网下载源码(https://www.sqlite.org/download.html
    • Source code里的 sqlite-amalgamation-xxxx.zip
    • Precompiled Binaries for Windows的:sqlite-dll-win64-x64-xxxx.zip(我下载64bit的) 和 sqlite-tools-win32-x86-xxxx.zip
  2. 三个zip解压到同一个文件夹
  3. 开始运行里找到 Developer Command Prompt for VS 2xxx
  4. 从命令行到该目录里,运行 (64位)lib /DEF:sqlite3.def /OUT:sqlite3.lib /MACHINE:x64 或 (32位)lib /DEF:sqlite3.def /OUT:sqlite3.lib /MACHINE:x86,后生成sqlite3.lib
  5. 然后将sqlite3.lib和sqlite3.dll都复制到 src-tauri文件夹下
  6. cargo test应该可以通过了

另打包后,sqlite3.dll需要放到和exe安装目录相同的位置,或者PATH里,还不知道安装程序怎样自定义一些文件的打包。

另tauri里不能用html5的drag and drop,不知道原因是什么,这不是我说的,是tauri的管理员自己说的,并且这个问题已经很久了一直没解决。

另外tauri在mac平台上不能直接编译windows安装包,这也是我为什么要在windows上搞的原因。

还有tauri在mac平台上用safari实在是烦人,想起了以前适配ie的经历,以前是被ie折磨,现在被safari折磨。

BST Tauri 开发笔记(7)- 使用redux devtools

因为Tauri在操作系统上使用默认的系统浏览器作为webview,所以在mac系统上使用了safari,结果没法使用redux devtools,采用redux remote devtools解决。

remote-redux-devtools

安装模块

npm i remote-redux-devtools @types/remote-redux-devtools -D

修改configureStore

import { configureStore } from '@reduxjs/toolkit'
import devToolsEnhancer from 'remote-redux-devtools'
import { counterReducer } from '../features/counter/counterSlice'

export const store = configureStore({
  reducer: {
    counter: counterReducer,
  },
  devTools: false,
  enhancers: [
    devToolsEnhancer({ realtime: true, hostname: 'localhost', port: 8000 }),
  ],
})

// Infer the `RootState` and `AppDispatch` types from the store itself
export type RootState = ReturnType<typeof store.getState>
// Inferred type: {posts: PostsState, comments: CommentsState, users: UsersState}
export type AppDispatch = typeof store.dispatch

启动后发现报错,说 global 对象找不到,因为redux-remote-devtools是给React Native用的,rn里的顶级变量是global,所以打开index.html,在html的head里添加:

<script>
window.global = window
</script>

remotedev-server

安装

npm i remotedev-server -D

修改package.json

  "scripts": {
    ...,
    "remotedev": "remotedev --hostname=localhost --port=8000"
  },

启动

npm run tauri dev
npm run remotedev

打开 http://localhost:8000 应该可以看到redux store的状态了

BST Tauri 开发笔记(6)- 为Tauri接口注入全局变量

目的,想要在对JS能调用的invoke接口中提供持续的db connection对象,一开始想用比较简单粗暴的方式每次都重新连接一次本地的sqlite数据库,后来发现Tauri可以注入的功能,就有了以下的使用方法:

main.rs

use rusqlite::Connection;
use tauri::State;
use std::sync::Mutex;

struct DbConnection {
    db: Mutex<Option<Connection>>,
}

// 注入的state会自动匹配声明的变量
#[tauri::command]
fn query(some_param: i32, connection: State<DbConnection>) -> Vec<String> {
    println!("some_param={}", some_param);

    let db = connection.db.lock();
    let conn = db.as_ref().unwrap().as_ref().unwrap();
    let mut stmt = conn.prepare("SELECT name_en FROM books").unwrap();
    let rows = stmt.query_map([], |row| row.get(0)).unwrap();

    let mut names = Vec::new();
    for name_result in rows {
        names.push(name_result.unwrap());
    }
    names
}

fn main() {
    tauri::Builder::default()
        // 注入state
        .manage(DbConnection {
            db: Mutex::new(Some(
                Connection::open("./resources/db.sqlite").unwrap(),
            )),
        })
        .invoke_handler(tauri::generate_handler![query])
        .run(tauri::generate_context!())
        .expect("error while running tauri application");
}

在React中使用接口:

App.tsx

import { invoke } from '@tauri-apps/api'
import { FunctionComponent } from 'react'

interface AppProps {}

const App: FunctionComponent<AppProps> = () => {
  return (
    <div className="tw-w-screen tw-h-screen">
      <button
        onClick={async () => {
          const names = await invoke('query', { someParam: 123 })
          console.log(names)
        }}
      >
        query3
      </button>
    </div>
  )
}

export default App

这样就能在所有的tauri接口中使用同一个db 的connection对象了!

文档:https://docs.rs/tauri/1.2.4/tauri/trait.Manager.html#method.manage

如何阻止浏览器超出滚动的弹跳效果

最近做Tauri,发现Tauri虽然少了Chromium大大缩小了安装包的大小,但是用操作系统内本地的浏览器做WebView实在是太不靠谱了,Mac电脑上的Safari简直就是一个大毒瘤,为了搞这个适配问题,感觉回到了兼容IE时代,Tauri的开发者拜托至少给个Chromium的选项别一刀切,比起适配如此痛苦,我真不在乎那几十兆的浏览器。

原文:https://www.bram.us/2016/05/02/prevent-overscroll-bounce-in-ios-mobilesafari-pure-css/

目的:禁止浏览器超出部分滚动的弹跳效果

除Safari以外的浏览器:

html, body {
  overscroll-behavior-y: none;
}

Safari:

html,
body {
  position: fixed;
  overflow: hidden;
}

body > .mainwrapper {
  width: 100vw;
  height: 100vh;
  overflow-y: scroll;
  -webkit-overflow-scrolling: touch; /* enables “momentum” (smooth) scrolling */
}
<html>
…
<body>
  <div class="mainwrapper">
    …
  </div>
</body>
</html>

据该博客的2021年补充说,因为bug上面的方法在ios12里也不支持,我没有测试,但至少在Tauri的浏览器里可以,而且无需加上 mainwrapper等。

flex-shrink 的使用

flex-shrink 根据容器大小和自己原先的尺寸 (flex-basis) ,当空间不足时适当适当缩小,看示例:

<p>The width of content is 460px; the flex-basis of the flex items is 120px.</p>
<p>A, B, C have flex-shrink:1 set. D and E have flex-shrink:2 set</p>
<p>The width of D and E is less than the others.</p>
<div id="content">
  <div class="box" style="background-color:red;">A</div>
  <div class="box" style="background-color:lightblue;">B</div>
  <div class="box" style="background-color:yellow;">C</div>
  <div class="box1" style="background-color:brown;">D</div>
  <div class="box1" style="background-color:lightgreen;">E</div>
</div>
#content {
  display: flex;
  width: 460px;
}

#content div {
  flex-basis: 120px;
}

.box {
  flex-shrink: 1;
}

.box1 {
  flex-shrink: 2;
}

A, B, C, D, E 五个 div 都是 content 容器的子元素,它们的 flex-basis 都是 120px,所以原本它们的宽度和应该是 600px,现在 content 容器宽 460px,超出 140px 由5个子元素分担缩减,ABC 减少1份,DE减少 2 份,总共是 7 份(1+1+1+2+2),所以每份是 20,ABC 减少 20px 最终宽度是 100px,DE 减少 40px 最终宽度80。

演示:

BST Tauri 开发笔记(5)- 自定义窗口标题栏

参考:

https://tauri.app/v1/guides/features/window-customization/

https://tauri.app/v1/api/config#windowconfig

创建css(测试可以写在index.html里)

      .titlebar {
        height: 30px;
        background: #329ea3;
        user-select: none;
        display: flex;
        justify-content: flex-end;
        position: fixed;
        top: 0;
        left: 0;
        right: 0;
      }
      .titlebar-button {
        display: inline-flex;
        justify-content: center;
        align-items: center;
        width: 30px;
        height: 30px;
      }
      .titlebar-button:hover {
        background: #5bbec3;
      }

添加标题栏的html结构(index.html)

    <div data-tauri-drag-region class="titlebar">
      <div class="titlebar-button" id="titlebar-minimize">
        <img
          src="https://api.iconify.design/mdi:window-minimize.svg"
          alt="minimize"
        />
      </div>
      <div class="titlebar-button" id="titlebar-maximize">
        <img
          src="https://api.iconify.design/mdi:window-maximize.svg"
          alt="maximize"
        />
      </div>
      <div class="titlebar-button" id="titlebar-close">
        <img src="https://api.iconify.design/mdi:close.svg" alt="close" />
      </div>
    </div>

绑定事件(main.tsx)

import { appWindow } from '@tauri-apps/api/window'
document
  .getElementById('titlebar-minimize')
  ?.addEventListener('click', () => appWindow.minimize())
document
  .getElementById('titlebar-maximize')
  ?.addEventListener('click', () => appWindow.toggleMaximize())
document
  .getElementById('titlebar-close')
  ?.addEventListener('click', () => appWindow.close())

tauri.conf.json

    "allowlist": {
      ...
      "window": {
        "all": false,
        "close": true,
        "hide": true,
        "show": true,
        "maximize": true,
        "minimize": true,
        "unmaximize": true,
        "unminimize": true,
        "startDragging": true
      }
    },
    "windows": [
      {
        "fullscreen": false,
        "resizable": true,
        "title": "bible-study-tool-app",
        "width": 800,
        "height": 600,
        "decorations": false
      }
    ]

透明背景(如果使用圆角窗口)

tauri.conf.json 编辑 windows 下的 transparent 设为 true,macOS要把 tauri 下的 macOSPrivateApi 设置成 true

    "windows": [
      {
        ...
        "transparent": true
      }
    ],
    "macOSPrivateApi": true

并且把 html 元素设置为透明

<html lang="en" data-theme="light" style="background-color: rgba(0, 0, 0, 0)">

BST Tauri 开发笔记(4)- Tailwind CSS / DaisyUI

安装Tailwindcss

npm install -D tailwindcss postcss autoprefixer 

生成 tailwind.conf.cjs

npx tailwindcss init -p  

安装daisyui和daisyui react

npm i daisyui react-daisyui    

taiwind.config.cjs

/** @type {import('tailwindcss').Config} */
module.exports = {
  content: ['./index.html', './src/**/*.{js,ts,jsx,tsx}'],
  theme: {
    extend: {},
  },
  plugins: [require('daisyui')],
}

设置主题 index.html

<!DOCTYPE html>
<html lang="en" data-theme="light">
...