logo
Published on

localsend源码学习(一) - 介绍

Authors
  • avatar
    Name
    realth000
    Twitter

介绍

localsend是一款开源的跨平台局域网文件/消息投送软件,只要在连上相同WIFI的设备上开启localsend客户端,即可方便地在设备间传送文件,具有以下特点:

  • 跨平台,支持Windows,Linux,Android等平台。
  • 支持HTTPS,端到端加密。
  • 不需要连接到互联或第三方服务器,P2P的文件/消息传送。

正好满足我的需要,而且是Flutter编写的,自然有兴趣学习一下。

实际上本来正在拿flutter写一个很类似的软件呢,写了一半发现人家的好用就直接用上了。

项目组成

按照README中的提示,克隆git repo后通过flutter pub run build_runner build -d生成代码,然后开始阅读项目。

✿ tree -d lib
lib
├── gen
├── model
│   ├── dto
│   ├── send
│   └── server
├── pages
│   ├── debug
│   └── tabs
├── provider
│   ├── network
│   └── selection
├── util
└── widget
    ├── animations
    ├── dialogs
    ├── list_tile
    └── watcher

17 directories

find lib -name "*.dart" 2>/dev/null | xargs wc -l | tail -n 1
 22971 总用量

目录数量还好,总代码量(算上生成的)不到两万三千行,flutter的行数嘛懂得都懂,不算太多。

cat pubspec.yaml
...
dependencies:
  basic_utils: 5.4.2
  collection: 1.17.0
  connectivity_plus: 3.0.3
  desktop_drop: 0.4.0
  device_info_plus: 8.1.0
  dio: 4.0.6
  file_picker: 5.2.5
  flutter:
    sdk: flutter
  flutter_localizations:
    sdk: flutter
  flutter_markdown: 0.6.13
  flutter_riverpod: 2.1.3
  freezed_annotation: 2.2.0
  image_gallery_saver: 1.7.1
  image_picker: 0.8.6
  intl: 0.17.0
  json_annotation: 4.7.0
  launch_at_startup: 0.2.1
  network_info_plus: 3.0.2
  open_filex: 4.3.2
  package_info_plus: 3.0.3
  path_provider: 2.0.11
  permission_handler: 10.2.0
  routerino: 0.3.0
  screen_retriever: 0.1.6
  share_handler: 0.0.16
  shared_preferences: 2.0.17
  shelf: 1.4.0
  shelf_router: 1.1.3
  slang: 3.12.0
  slang_flutter: 3.12.0
  tray_manager:
    # https://github.com/leanflutter/tray_manager/issues/30
    # The Linux tray manager is disabled for now
    git:
      url: https://github.com/Tienisto/tray_manager.git
      ref: b37f5e088e0f02c45a684ae41e9d2da2d5c596db
  url_launcher: 6.1.9
  uuid: 3.0.7
  wakelock: 0.6.2
  wechat_assets_picker: 8.3.2
  window_manager: 0.2.8

dev_dependencies:
  build_runner: 2.3.3
  flutter_gen_runner: 5.1.0+1
  flutter_lints: 2.0.1
  freezed: 2.3.2
  json_serializable: 6.5.4
  msix:
    # https://github.com/YehudaKremer/msix/pull/174
    git:
      url: https://github.com/Tienisto/msix.git
      ref: 207eddfe797225ab2736001cbdb8fafd04946b38
  slang_build_runner: 3.12.0
  test: 1.22.1

dependency_overrides:
  share_handler_platform_interface:
    # https://github.com/ShoutSocial/share_handler/pull/39
    # Remove this when next release is published
    git:
      url: https://github.com/ShoutSocial/share_handler.git
      path: share_handler_platform_interface
      ref: 630cf945524dfbae1bc63ed83b28559b47b25ffa

  # cannot open windows settings in 3.0.3
  url_launcher_windows: 3.0.2
...

依赖的包不少,重要的包分下类:

  • 状态管理:flutter_riverpod
  • 路由管理:routerino
  • 网络服务:dio, shelf
  • 国际化:slang
  • 代码生成:freezed, build_runner

代码生成用的两个包比较陌生,之前没用过代码生成,本系列重点学习一下。riverpod刚接触过,思想和用法还不顺手,dio之前用过,shelf之前用的时候觉得不好用,用go做了个服务器当替代方案,国际化的slang没用过,整个学下来能收获不少呀。

依赖介绍

  • riverpod:一个状态管理包,在能方便地access状态的同时保证好写测试,算provider的升级版,同一个作者开发。半个老朋友,前段时间刚从getx切到riverpod,各种概念比较迷糊,用起来也不熟练。从这个项目看来riverpod的流行度也不算低啊。比较好奇的是,竟然用的是flutter_riverpod而不是hook_riverpod,难道没有在widget之外用过state吗?虽然之前文章说了选flutter_riverpod,但是用的时候如果脱离了flutter那一套(即没有ref),那么再使用state的时候需要用ProviderContainer,留个意看看localsend如何做到的。
  • routerino:官方介绍:在声明对应关系且不适用build_runner的情况下使用命名路由。目前没看出和go_router或者getx相比有什么优势,以后仔细看看。
  • dio:http client包,同类型中使用最广泛的。之前写类似软件的时候用了,简单好用。
  • shelf:http server包,dart目前偏向客户端,像shelf这样用于服务端的包比较少,shelf是其中使用较多的。之前也考虑过直接拿dart写http服务器,后来觉得不够靠谱就拿go做了server。
  • freezed:依靠代码生成,简单地制作出“数据类”,kotlin里好像有这个概念,data class,这个类就是个数据组合,类似结构体。freezed提供了toString()==hashCode()的重载,并且提供copyWith方法,且可支持序列化/反序列化,功能挺强的。
  • build_runner:flutter官方推出的代码生成工具,很多包都依赖它。

功能介绍

localsend提供了哪些功能呢?

  • 局域网文件/消息发送。
  • 局域网内设备发现,默认每个客户端提供一个ID用于识别,也可以手动指定IP。
  • 默认状态下接收端收文件需要点确定,也提供不需要确定的快速下载模式供服务端场景使用。
  • 可以更改下载目录,有下载历史。
  • 默认开启SSL,可以关闭。
  • 有托盘图标,可以驻留后台。
  • 支持开机自启。
  • 支持更换端口。
  • 支持多种语言。

基本上和我想做的局域网流转软件一模一样,我放弃我自己做那个了,正好通过localsend学习flutter,只会getx那一套并不行,很多包使用的时候需要statefulwidget,这种场景和getx并不契合。

这篇文章稍微水了点,主要介绍一下localsend,下一期从具体角度分析下localsend的源码。

本来早就想写,这一周因为某些奇怪的无可奈何的原因没弄成,还过得很不舒坦,今天算好了一些,希望今后不再出这种问题吧。