Skip to content

terhechte/hyperdeck-app

Repository files navigation

Hyperdeck

Setup

In order to work on Hyperdeck, you need to install Rust and compile the parseval package.

The first requirement is to install Rust via the offocial Rustup tool.

Next, you need to install the required architectures for Catalyst

# iOS device support
rustup target add aarch64-apple-ios
# iOS simulator support
rustup target add aarch64-apple-ios-sim
# Catalyst on intel macs
rustup target add x86_64-apple-ios-macabi
# Catalyst on apple silicon macs
rustup target add aarch64-apple-ios-macabi

With that out of the way, the parseval package can be compiled:

cd parseval-rs
make apple BUILD_TYPE=release

Xcode

Once the Rust package has been compiled, the project can be opened in Xcode. Note that I stopped integrating parseval into the Xcode build process as that led to more issues than it solved.

Architecture

There're two blog posts that explain the architecture of Hyperdeck:

Here's additional information about the architecture not covered in those posts:

Basic Setup

  • Hyperdeck still uses Frameworks instead of Swift Packages, mostly because that worked much better in 2020 and I didn't want to change this setup yet.
  • There's method swizzling and other hacks in order to improve Catalyst support.
  • Switching to a all SwiftUI flow is probably difficult because there're so many UIKit based views and controllers that would need to be rewritten or moved below a shared CrossPlatformController class that is either UIViewController or NSViewController and handles UIKit / Cocoa differences such as colors, fonts or method names.

Frameworks

HyperDeck

The app target. Which also includes containers for the visible UI, e.g.

  • New Document Flow
  • Scene Delegates
  • Presenter / Moderator
  • Editor
  • Assistant

containers in this regard means that while the HyperDeck target contains the actual, say, editor view controller, most of the logic is in a separate framework.

Effectively, the HyperDeck targets puts all the components together (and adds a lot of mess)

AppState

Basically a UIDocument like class that stores the state of the current document. I ran into issues with UIDocument and Catalyst which is why this is based on LSDocument. I had nothing but trouble with UIDocument and Catalyst. This is the entry point into the Rust parseval-rs package to parse markdown and modify markdown.

SlideKit

SwiftUI code responsible for rendering parsed slides. This code was written in 2019 with a target of 2016 iPad Pro. Hence, there're many performance optimizations (e.g. using EquatableView everywhere and custom Equatable implementations). I don't think these are needed anymore with modern Macs.

In addition, this was written for SwiftUI 1.0 and contains a ton of hacks to make the layout somehow work within the limitations of SwiftUI 1.0.

PlayerKit

Basic facilities for full screen presenting presentations. Includes code for animated backgrounds.

EditorKit

A huge amount of code to have a working NSTextView based editor with syntax highliting and keyboard shortcut support. Once again, many Catalyst issues forced the code into implementing some weird hacks. It would probably be better to use a TextKit2 based editor, such as [https://github.com/krzyzanowskim/STTextView]https://github.com/krzyzanowskim/STTextView

SlideModel

Re-Exports all the Model-Layer types from parseval-rs and adds additional extensions. Also has a couple of other types required.

InspectorKit

The inspectors that appear when editing a slide or a block level element (e.g. a paragraph or a list item). This is abhorrent SwiftUI code and I think it would be beneficial to redo it with current SwiftUI and Swift Macros (to automatically have inspector fields based on datatypes)

ThemeKit

parseval-rs also contains a CSS parser into CSS rules. ThemeKit takes a CSS stylesheet and gives it to parseval to return a list of CSS rules. These are then converted into SwiftUI styles and cached. SlideKit then queries these styles based on the selector of the element, e.g.

This selector slide title1 right quote italic

This is just an example, the actual selector names are slightly different

Would get the style for a slide with the master set to title1 and the layout set to right and a quote element which contains italic text.

Here's a concrete example

title2 li1,
title2 li2,
title2 li3,
title2 li4,
title2 li5,
title2 li6 {
  -hyper-list-style-bulletcolor: var(--color2-dark);
  color: var(--color1);
  -hyper-list-bullet-font: var(--list-text-size) var(--heavy);
}

HyperDeck only supports a subset of CSS (2.1) with additional hacks and some custom properties. There's a _Docs.md in the theme folder that explains this.

Apart from that, ThemeKit style types (e.g. Border, Shadow), editor theming code, images, colors, fonts.

ExtensionKit

Just a bunch of type extension (e.g. UIColor+Hex.swift) to make life easier.

ComponentKit

This was meant to be a shared place for SwiftUI Views and UIViews that were needed in multiple places. However, right now its mostly a unsorted list of UI things.

AnimationKit

Includes UIView transitions for animated backgrounds and transitions. The whole transition system is based on transitioning between two UIViews and not in the realm of SwiftUI which - again - worked way better in 2019.

AppKitGlue & AppKitUIKitSharedTypes

Since Catalyst was so limited, this contains hacks to inject into AppKit in order to make the app look and feel like an AppKit app and not a Catalyst UIKit Frankenstein.

AppKitUIKitSharedTypes are types that are written in Such a way that they can compile in UIKit and AppKit. They're being used across the bridge when communicating between the AppKit and UIKit sides.

Other Notes

  • Text Ranges are a complicated thing. Cocoa uses NSRange (UTF16 based), Swift uses Range<String.Index> (UTF8 based), and Rust uses Range<usize> (byte based). There're facilities to convert back and forth between these types. In particular the conversion from Rust's bytes to Swift's Range<String.Index> is expensive which is why Rust precalculates NSRange values.
  • Implementing Undo / Redo was really difficult and I don't think its working very well.
  • When cleaning up HyperDeck I only tested the macOS build. I haven't tried
  • It builds for iPad, but there's currently a Document error that I haven't investigated further.

About

Markdown presentation slides for iPad and macOS

Resources

License

Stars

Watchers

Forks

Releases

No releases published

Packages

 
 
 

Contributors