| Sources/Fedicat | ||
| Tests/TootSDKTests | ||
| .gitignore | ||
| .swift-format | ||
| LICENSE | ||
| Makefile | ||
| Package.swift | ||
| README.md | ||
| RELEASE.md | ||
Fedicat
This repo provides the issue tracker for the Fedicat fediverse app (available on Testflight) and a Swift package that currently comprises the lower layers, mostly non-UI code, although pretty much anything that is not a SwiftUI View is migrating here, while there is some app-specific support (SwiftSys contains code that I reuse or theoretically could reuse in other apps, which is currently just Talk Dim Sum). Apple/Xcode/SPM doesn't like local packages depending on local packages, so heavily customized package dependencies (namely HTML2Markdown and TootSDK) are merged in.
This package is open source and theoretically reusable but it is highly fluid and unstable with daily commits, undocumented, and tailored to Fedicat, so if you're looking to build an app, I recommend starting with the official TootSDK first and then feel free to use ideas from this code (and patch back to TootSDK if that makes sense). I got started by modifying one of their sample apps, but TootSDK-based TootyGraph is open source, and other open source apps are listed in awesome-mastodon ranging from fairly compact (Bubble is around 15k lines) to the aptly named Mammoth (over 100k and looking for a new caretaker).
Components
Session
This is the top and user-interface facing layer. A Session encapsulates an instance login, including a TootClient for communicating with the instance, and Platform/Instance/NodeInfo identifying the instance platform description and capabilities. An app that handles multiple active instances will have a Session for each login. It is essentially a generalization of TootManager in the TootSDK sample app, although maybe it should be flattened into TootClient.
HTMLMarkdown
A fork of HTML2Markdown with formatting support for Fedicat, e.g. bold tags and mentions.
Most rich text is received as HTML and, as in the TootSDK sample renderer, converted to Markdown before rendering in SwiftUI. Fedicat displays that with EmojiText (by the same author), which is also used in the TootSDK sample app, Bubble, and Ice Cubes.
The conversion is invoked by the UI but probably should be performed at decoding time and thus stay internal to this package.
TootSDK
A fork of TootSDK (from a couple years ago, so it's diverged quite a bit), tailored for Fedicat. It omits code for features and endpoints not used by Fedicat (streaming feeds, web push…), and is intended to be used within Fedicat, so everything is internal except data types used by the UI, and the line between TootClient and Session is getting fuzzy.
Models are mostly structs (Swift treats classes like the bad sheep of the family), but classes are used when there is a circular definition (Post can contain a quoted or reblogged Post, and Account can reference a moved-to Account) or if there is an opportunity for substantial code sharing (Post and PostEdit subclass PostContent). They are generally immutable (let properties), and mostly only instantiated from decoders (so no plans to use these server-side). Decoders and initializers do much of the work in packaging data for the UI (trimming whitespace in strings, returning URLs and OrderedSet instead of strings and arrays). I like to see which specific cases fail, so I handle those on a case-by-case basis, but see original TootSDK for safer handling of enums. The fields correspond to those in the API specs, but can diverge for convenience (treat nil as empty string or empty set) or to accomodate multiple platforms (mastodon has different post quote structure than other platforms so use different fields for each).
TootFeature is removed, platform/feature checks are performed at the Session level and by the UI, so TootClient is more a union of platform APIs than a unified API.
Enums in the same form as Timeline are used to describe most endpoints, in the general direction of other apps like Feditext. They are generally grouped by feature.
Platform
A set of Platform descriptors that replaces the TootSDK feature/flavour tests, but it is outside TootSDK so theoretically TootSDK could be used with any platform/feature detection or none. Each platform is a Platform subclass and the hierarchy mirrors the forking relationship, e.g. Glitch is a subclass of Mastodon which is a subclass of MastoAPI which is a subclass of Platform, GotoSocial and Mitra subclasses of MastoAPI and so on. Within a platform, feature availability can be dependent on the Mastodon API and/or platform build.
The feature tests supplied by Platform is somewhat arbitrary (see Feditext for an endpoint-based feature/flavor test), but it is convenient to add a new platform simply by subclassing, and a new feature test usually requires modifying just a few files, the base Platform class and enabling it in the platform that provides it.
The target platform is anything with pretty good Mastodon API compatibility but I'll try to support whatever is available, even if it's just the InstanceV1 info (like bookwyrm). A current requirement is that the platform identifies itself through a nodeinfo, which includes most of the major fediverse platforms.
An initial platform is derived from the nodeinfo, and then if it's a platform that supports the mastodon instance (v1 or v2) endpoint, more information is potentially derived from that, typically the build number but sometimes a more specific platform (the nodeinfo might indicate the platform is mastodon but the instance info may say it's actually some other mastodon-compatible platform).
Platform is mostly wrapped by Session wrappers (e.g. session.isMitra, session.supportsLists...) but is public so the UI can instantiate platforms to list in the instance browser.
Common
Some functions are shared among modules, e.g. trimming whitespace.
Lists
Assorted hardcoded lists used by the UI, such as instances and hashtags.
Localizations
Also for the UI, localization keywords in the form of enums. The translations are exported to fedicat-localization.
Translations
Translator interfaces (conforming to the Translated protocol along with the Mastodon instance translation), really anything that can transform the content of a post, e.g. there is an Apple Translate implementation and one for deleted posts.
Draft
Observable classes representing sets of defaults and drafts, such as DraftPost for composing posts and DraftProfile for editing your account profile.
Style
Try to follow the Swift API Design Guidelines and DocC documentation
Formatted and checked with swift-format using default rules, except AlwaysUseLowerCamelCase turned off because we have some upper camelcase enums corresponding to JSON fields.
Credits
Open source and graphics credits are listed on the fedicat site
License
MIT License. The original HTML2Markdown and TootSDK licenses are in the respective directories.