跳转到内容
Skip
3.2k

贡献指南

Skip 欢迎各种形式的社区贡献。你可以通过多种方式参与贡献:

  • 帮助改进文档。每个文档页面底部都有一个”编辑页面”链接,点击后会跳转到 github.com/skiptools/skip.dev/ 文档站点,你可以在那里 fork 页面、进行改进并提交 pull request。
  • 改进 Skip 核心框架,即 Skip 为 Skip Lite 重新实现的基础 Swift 框架(如 Foundation)。每个库的 README 都包含背景信息,例如当前状态、所采用的重要实现策略等。请在贡献前查阅 README。准备好提交更新时,创建一个标准的 GitHub pull request。Skip 的开发团队会尽快处理 PR。
  • SkipUISkipFuseUI 做出贡献,帮助扩展和改进 Android 上的 SwiftUI 支持。与其他 Skip 模块一样,请查阅 README 并提交标准 pull request。SkipFuseSkipFuseUI 库在贡献时有特殊注意事项
  • 向第三方 Swift 库提交 pull request,使其能够在 Android 上构建,并在 Swift Package Index 上显示为 Android 兼容。请参阅移植指南获取有用的提示。

如果你想在开发应用时对 Skip 的库进行本地修改——例如改进 SkipUISkipFuseUI,并通过其 Showcase 应用来验证修改效果——你需要配置 Xcode 使用本地库版本,而不是当前的 Skip 发行版。使用 Xcode Workspace 可以轻松实现这一点。

  1. 克隆你想要修改的仓库。我们发现最方便的做法是将克隆目录作为应用目录的同级目录。

    Terminal window
    > ls
    hello-skip/ skip-ui/ skip-fuse-ui/
  2. 使用 Xcode 在同一目录下创建一个新的 Workspace。

  3. 将你的应用的 .xcodeproj 文件添加到 Workspace。

  4. 将本地模块目录添加到 Workspace。添加这些本地包会覆盖 Package.swift 中指定的发行版,使本地包的更改在你的应用构建中生效。

  5. 使用 Workspace 同时迭代你的应用和库。

现在你已经配置好了 Skip 库的开发环境!这是修复影响你的应用的任何问题或添加缺失功能的好方法,同时还能帮助整个 Skip 社区。

从 Android Studio 启动应用时,默认不会使用 Workspace 中的本地库。如果你想在 Android Studio 中工作,请编辑你的应用的 Android/settings.gradle.kts 文件,将 Android Studio 指向 Xcode 的构建输出,如跨平台主题中所述。

如果你正在开发一个转译库,涉及大量使用 Kotlin API,你可能会发现在 Android Studio 中打开模块并在那里迭代更快,即使你希望最终代码是 Swift。其思路是先在 Android Studio 中使用 Kotlin 进行原型开发,然后将解决方案移植回 Swift 代码库。我们发现在 Compose 之上实现 SwiftUI 功能时,这种方式特别有用。Android Studio 提供了强大的自动补全、内联文档,以及对众多 Compose 包的自动 imports。它的构建和运行速度也非常快,在实验阶段帮助很大。我们在实现主要的 SkipUI 模块功能时的一般策略是:

  1. 确保你已配置好本地库开发环境。别忘了将 Android Studio 指向你的本地库。
  2. 在 Swift 和 Xcode 中编写功能的存根代码。
  3. 构建你的应用(对于 SkipUI 的工作,我们使用 Showcase 应用),使你的 Swift 存根被转译。
  4. 在 Android Studio 中打开应用
  5. 在 Android Studio 中使用纯 Kotlin/Compose 迭代实现。是的,这涉及编辑包含你存根的转译文件,你甚至可能需要覆盖文件的只读标志才能编辑。在此阶段注意不要运行 Xcode 构建,因为它会用自身的转译结果覆盖该文件。
  6. 确定了 Android 实现方案后,用它来填充你的 Swift 存根。你可以将其分离为一个被包含的 Kotlin 文件,从 Swift 中调用其 API,或者将你编写的 Kotlin 代码移植为内联 Swift。

同样,我们只建议在实现需要大量使用 Kotlin API 并且需要大量迭代和实验时才使用此流程。在这种情况下,使用 Android 原生 IDE 来确定可行方案的速度,完全弥补了最终清理解决方案所需的额外几分钟。

对这些库的大多数贡献,无论是核心框架还是集成框架,都只需要为单个包和仓库提交 pull request。但 SkipUI 不同:由于 SwiftUI 实现的复杂性,Skip 对它的支持被分到了两个独立的仓库:

  1. SkipUI 用于转译的 Skip Lite 将 SwiftUI 概念映射到对应的 Jetpack Compose 等价物
  2. SkipFuseUI 用于在原生 Skip Fuse 应用中使用 SKipUI 所需的额外适配

SkipUI 的一些改进,例如修复 Compose 实现的 bug,可以仅在 skip-ui 仓库中完成。但如果改进涉及新增可用的 API 或对 SwiftUI 接口的任何其他更改,则 PR 需要与 skip-fuse-ui 仓库的 PR 配对提交。

此外,在添加新功能或以其他方式更改行为时,最好始终在 skipapp-showcase 应用中进行测试,它可以在 Skip Lite 或 Skip Fuse 模式下运行。这既可以测试你的新功能,确保不会破坏其他内容,又能为其他开发者提供你的改进如何工作的演示。

因此,一个贡献的示例工作流程如下:

  1. Fork SkipUI:https://github.com/skiptools/skip-ui/fork
  2. Fork SkipFuseUI:https://github.com/skiptools/skip-fuse-ui/fork
  3. Fork Showcase:https://github.com/skiptools/skipapp-showcase/fork
  4. 将每个 fork 的仓库克隆到本地文件夹
  5. 创建一个 Xcode workspace,包含 skip-uiskip-fuse-ui 包以及 skipapp-showcase/Darwin/Showcase.xcodeproj 项目
  6. 运行 ShowcaseLite AppShowcaseFuse App 两个 target 以确保它们正常工作
  7. 开始实现对 SkipUI 的更改,通过启动 ShowcaseLite App target 进行测试
  8. 当你对更改满意后,开始在 SkipFuseUI 模块中实现等效功能,并通过启动 ShowcaseFuse App target 进行测试
  9. 一切正常后,将更改推送到你的本地 fork,并向每个上游仓库提交 PR。

以下一系列 pull request 展示了向 SkipUI 添加新功能的工作流示例:

  1. 添加 View.contextMenu 修饰符:https://github.com/skiptools/skip-ui/pull/356
  2. 支持 View.contextMenu 修饰符:https://github.com/skiptools/skip-fuse-ui/pull/93
  3. 添加 ContextMenuPlayground 来演示 View.contextMenuhttps://github.com/skiptools/skipapp-showcase/pull/74

集成框架是 Skip 的核心:它们是可选模块,为 Android 和 Darwin 平台提供统一的 API 来访问等效功能。模块索引中提供了部分现有集成框架,但在 Skip GitHub 组织仓库下还有更多。其中许多框架是多年来由用户贡献的。

实现集成框架有两种不同的策略:“直通式”和”定制式”。

当目标是模仿现有的 Darwin(iOS 或 macOS)API 接口时,可以设计 Android API 来匹配 Darwin API。

直通式 API 的一些示例:

直通式策略有以下优势:

  1. API 已经为你设计好了。你只需要为你想暴露的功能子集”填空” Android 实现。
  2. 当模仿现有的 Darwin API 接口时,通常你只需要实现 Android 端(通常在 #if SKIP 块中)。iOS/macOS API 会按原样使用,你的 Android 实现只需要设计为与 Darwin 端的工作方式相同。

与直通式策略不同,定制式 API 是一个全新的 API 接口,分别适配底层的 Darwin 和 Android API。

定制式 API 的一些示例:

定制式 API 策略的一些优势:

  1. 直通式 API 会将设计限制在(通常是遗留的)现有 Darwin API 上,而设计自定义 API 来抽象 Darwin 和 Android 平台上的功能,则可以使用现代约定,如 async/awaitAsyncStream
  2. 自定义 API 可以只构建受支持 API 的子集,而不必为 Android 上不支持的 API 部分提供抛出错误指示其不受支持的 shim。
  3. 定制式 API 可以跨越多个独立依赖,而不是仅限于它所模仿的框架。

无论集成框架是直通式还是定制式,都有一些有用的设计和实现策略。

  1. 最小化新颖性:集成框架通常旨在为 Android 和 Darwin 上的等效功能或特性提供抽象。通常建议实现尽可能精简,将重要逻辑委托给底层实现,这可能是平台的内置功能或外部库依赖。
  2. 寻找先例:许多常见的集成需求已在其他跨平台开发工具中实现。在 Flutter 的 pub.dev 或 React Native 的 expo.dev 上搜索,可以找到现有的免费开源 Swift(或 Objective-C)和 Kotlin(或 Java)实现,展示如何完成集成。这些可以适配到 Skip,或作为新 API 设计和实现的灵感。

你没有义务将框架贡献给 Skip 组织,但这样做有助于社区,并使框架可以在 skip.dev 模块页面上被文档化,还能鼓励社区贡献和持续维护。

要提出新的集成框架想法,请在想法论坛上发布消息,描述它将启用的新特性和功能。通常,我们会创建一个新的 Skip 仓库,包含一个空白的 Skip 项目,然后你可以 fork 它、迭代开发,并通过提交 pull request 来改进。

Skip Fuse 应用可以使用纯 Swift 库,无需它们”Skip 感知”。这要求包能在 Android 和 Darwin 平台上构建。

Swift Package Index 追踪数千个可原生编译到 Android 的 Swift 包。将你支持 Linux 和 Android 的包提交到 Swift Package Index,即可自动收录和文档化。

Skip 用户除了原生包外,还可以使用转译包。转译包对完整的 Skip Lite 应用很有用,并且在应用桥接时,对想与 Kotlin 库交互的 Skip Fuse 应用也有用。如果你创建了一个转译库,并认为它可能对其他 Skip 用户有用,请考虑将其开放给 Skip 社区。