• Stars
    star
    464
  • Rank 91,559 (Top 2 %)
  • Language
    Rust
  • License
    GNU General Publi...
  • Created 12 months ago
  • Updated 7 months ago

Reviews

There are no reviews yet. Be the first to send feedback to the community and the maintainers!

Repository Details

A cross platform Mastodon Client written in Rust

Ebou

Ebou is a cross platform Mastodon (and Pleroma, untested) client written in Rust using the Dioxus UI library. It currently runs on macOS [stable], Windows [beta], and theoretically on Linux [untested].

Ebou is a different take on the Microblogging / Mastodon experience. It groups new Toots by author and displays them in a UI not unlike modern messengers like Telegram, iMessage or WhatsApp.

This makes it easy to see your friends' updates at once.

It also has a Conversation view which helps seeing replies in the originating context.

Ebou is currently an experiment and therefore missing some features which you might expect from a full Mastodon client. They will be implemented over time.

You can download the current release for macOS Testflight or in the GitHub releases

Note: I worked on Ebou in my spare time. Please judge the code not as a professional project but more like a small side project where the outcome (a working desktop client) had higher priority than beautiful, well architected, well abstracted code.

Screenshots

Full Screenshot with Conversation Tree:

List of Followers:

Classic Timeline:

Windows Beta:

Linux Beta:

State

Ebou is currently in a beta state. There're bugs, and there're missing features. Here's a list of currently supported Mastodon features:

  • Timelines
  • Super Minimal Notifications (only Mentions and Ebou doesnโ€™t remember which ones you already saw)
  • Posting (including Video / Image attachments via Dragging and Dropping images onto window)
  • Conversations in a nice nested tree view
  • Boost, favorite, reply, bookmark
  • Lists
  • Your favourites / bookmarks
  • Profiles
  • Settings
  • Minimal Search
  • Followers / Follows
  • Some settings

Dioxus

Ebou uses Dioxus as the UI library. Dioxus makes it easy to build functional cross platform apps, but it is also currently unfinished and lacking features. Some of the limitations of Ebou are related to missing features in Dioxus.

One particular issue I have with Dioxus is that it uses a lot of abstractions and patterns from the React world. This leads to a lot of mixing of logic, model and ui domains.

Navicula

Therfore, I wrote an additional abstraction on top of Dioxus which implements a reducer model where each view is split up into the view, the state, the action / message and the reducer. It is a bit of a mix between the Elm architecture and the Swift Composable Architecture. It is called Navicula and a separate crate which can be found here.

Forks

Due to the way things work, many of the dependencies that Ebou uses had the one or other issue which made it difficult to use in Ebou. Therefore (if you look at the dependencies in Cargo.toml) there're several forks of different crates. I plan to get these changes merged over time.

Model Layer

One tricky issue about apps servicing microblogging services such as Twitter or Mastodon is that the data model needs to support the use case of sharing and mutating each Status (or Toot, or Tweet, or Message, I'll use the word Status now).

You could have the same Status multiple times on the screen. As a Status, and then as a boost and then in another column as one of your liked items, and then maybe in the conversation view as well. If you star one of them, the following needs to happen:

  1. The state is temporarily changed
  2. The mastodon star api is called
  3. If successful the star should be made permanent
  4. Find all the places where this particular Status is currently displayed
  5. Update it in all these places
  6. Redraw the related UI in these places
  7. All this on different threads (because the api call will probably happen on tokio and should not block the UI)

This particular problem is a bit hard in Rust because shared mutable cross thread state can only be achived with a Arc<Mutex<...>> which is hard to use because everytime you'd want to read any property of it you'd need to watch out for a poisoned lock, etc.

Ebou currently doesn't have a really good solution to this problem. It has something called RefPublisher which keeps all the Status data in a variety of structures. Reducers can subscribe to this RefPublisher. Then, whenever something in the storage changes, the view will be notified that it needs to re-render. Mutation then happens with a specific with_mutation function which makes sure to update all subscribers. This is not a particularly good solution because of multiple reasons:

  1. It is not fine-grained enough. It should be possible to subscribe on a per Status level
  2. Statuses are currently not stored as references. Instead, multiple instances can exist in memory. Something aking to a ECS might be a useful idea here
  3. The with_mutation way is cumbersome to use.

Replacing this system with something better would go a long way towards improving the performance and reliability of Ebou.

Javascript

There're some places where Dioxus didn't support the required functionality yet, so Ebou uses ugly javascript injection hacks to achieve some sort of effect. I can't say that I'm particularly happy about this.

Building

cargo run
# or
cargo run --release

Signing & Releasing

macOS

In order to create a macOS release build, we first generate a universal binary in Rust and then let Xcode sign it. It is possible to use command line utilities to sign the binary, but this is quite the hassle. Instead, there is an included Xcode project in the Xcode-Container folder:

  1. Open up the Xcode Project
  2. Build an Archive
  3. Open the Archive in Finder to get the path to the archive on disk
  4. Call the make.sh script with a version number and the path, e.g. `./make.sh 700 "/Users/ben/Library/Developer/Xcode/Archives/2023-05-05/Ebou 23.05.23.xcarchive"
  5. This will build Ebou and replace the binary in the Xcode archive with the actual Ebou binary
  6. Go to Xcode, selected the archive in the Organizer and sign & submit it from there

Linux

Linux requires a couple of additional dependencies.

Debian

sudo apt-get install pkg-config libssl-dev libgtk-3-dev xdotool libwebkit2gtk-4.1-dev libgtk-3-0 libgtk-3-dev libxdo-dev

Arch

There's a AUR package for Arch Linux:

https://aur.archlinux.org/packages/ebou-git

Thanks to https://github.com/StandingPadAnimations

Fedora

# Untested
dnf install pkg-config openssl-devel gtk3 gtk3-devel webkit2gtk4.1-devel xdotool xdotool-devel

License

Ebou is licensed under the GPL License

More Repositories

1

SourceKittenDaemon

Swift Auto Completions for any Text Editor
Swift
529
star
2

CoreValue

Lightweight Framework for using Core Data with Value Types
Swift
457
star
3

postsack

Visually cluster your emails by sender, domain, and more to identify waste
Rust
347
star
4

twitvault

Easily Archive and Search Your Twitter Data with our Syncable Desktop App
Rust
143
star
5

appventure-blog

My Clojure/Static-Based Blog.
CSS
82
star
6

OceanBar

A fancy Digital Ocean API client for Mac OS X 10.9+
Objective-C
70
star
7

gitsi

Git Status Interactive
C
36
star
8

bevy_quickmenu

A simple-to-use menu system for Bevy which supports gamepad, keyboard or mouse navigation
Rust
23
star
9

Swijito

An Apple iCloud Photostream Client written in Swift
Swift
21
star
10

TextMateSwiftCompletion

Swift Completions for Textmate
Swift
19
star
11

SwiftWadReader

Example of how to use Swift 3 in order to read a Doom WAD file
Swift
18
star
12

rust-catalyst-example

Example Project to show how to build a Catalyst static library with Rust
Swift
17
star
13

navicula

Rust
14
star
14

rust-ios-android-example

Rust
13
star
15

VimConfiguration

My new, personal, vim configuration. Based on Vundle.
Vim Script
13
star
16

CX11.swift

Swift Package for X11
Swift
13
star
17

swift-x11-example

A simple example that shows how to write a X11 app on Linux in Swift using the new package manager
Swift
12
star
18

NSSpain2020Code

The code for my NSSpain 2020 Talk: GeometryReader, View Preferences and Anchors - SwiftUI tales from the Hyperdeck
Swift
9
star
19

Parsepaper

Link Taskpaper files with Git commit so that commit messages automatically include the @done tasks from the task paper file.
Ruby
9
star
20

Difflocal

Compare Localizable.strings files for changes
Python
8
star
21

pragma2017-example-code

Unidirectional Data Flow Examples
Swift
6
star
22

tryswift-macos-workshop

Swift
6
star
23

watchout

Automatically run scripts and reload images
Rust
6
star
24

SpacemacsConfig

My personal Spacemacs config.
Emacs Lisp
5
star
25

belum

A lightweight, experimental, type-safe dependency injection container (cough) for Swift
Swift
5
star
26

cljs-animated-wwdc2014

Animated WWDC 2014 Logo in ClojureScript
JavaScript
4
star
27

luapsql

A high speed C binding to PostgreSQL's libpq for quick access to databases. Includes support for array columns and json columns. Forked from Luis Carvalho.
C
3
star
28

Cederic

Agents for Swift: Non-blocking, thread-safe, asynchrounous access & modification of shared data/state
Swift
3
star
29

SwiftHeroesCatalystAppKit

Swift
3
star
30

nsspain18-cocoa-bindings-workshop

Swift
3
star
31

timezone-abbreviations

Translate non-standardized abbreviations such as 'GMT' to timezone information on a best guess basis.
Rust
3
star
32

senor-pacbomber

The unholy combination of PacMan and Bomberman: El Seรฑor Pacbomber. For the Bevy Jam #2
Rust
2
star
33

tted

Render rich text and emoji on the GPU or CPU using Forma
Rust
2
star
34

django-spoutcore

a Django application that auto-generates a SproutCore datastore framework [done] and admin application [in progress] for your Django project
Python
2
star
35

cryptsy-python-api

A Python implementation of the Cryptsy-API (https://www.cryptsy.com/)
Python
2
star
36

appventure.me-codebase

The Jekyll Code that powers appventure.me + The git that has all the posts
Ruby
2
star
37

Google-Web-History-Downloader

Google Web History Downloader
Ruby
2
star
38

uniffi-swift-async-example

Quick example showing how to use uniffi with swift and async
Swift
2
star
39

nsspain2023workshop

Rust
2
star
40

aargh

No Chrome Fullscreen Mac OS X Browser for HTML5 Slideshows/Presentations
Objective-C
1
star
41

CatalystMaterial

Swift
1
star
42

appventure

Appventure Codebase
HTML
1
star
43

techou

Custom Rust static site engine. Terrible code, probably full of bugs. Works for my use cases.
Rust
1
star
44

appbuilders2022

Shell
1
star
45

PhotoSetManager

Group loads of pictures based on metadata
Objective-C
1
star
46

lempel

Gzip for Swift as a Carthage-Compatible framework
Swift
1
star
47

EmacsConfiguration

My private Emacs configuration utilizing Evil to feel almost like vim
Emacs Lisp
1
star
48

emlx

Parse Apple Mail.app `Emlx` Files.
Rust
1
star
49

Vim---Bash-Configuration

My Vim Configuration, based on http://github.com/evilchelu/braid, and my Bash Config
Python
1
star
50

GameAssetOrganizer

A Mac tool that helps in sorting game assets into a level pack / level structure so that these can be transformed into sprite sheets.
Objective-C
1
star
51

stripe_bug_cocoa_example

There's an issue on Mac OS X 10.8 and 10.9 where CSS/JS Animation heavy contents in a Layer-Backed WebView do not draw correctly. This affects the Stripe Checkout form which does not display at all on those older operating systems. The bug seems to be fixed in 10.10 Yosemite.
Objective-C
1
star
52

parse_most_visited_websites

A Simple collection for scripts to generate a list of frequently visited websites and analyze it in order to find out which is the best partitioning scheme for a PostgreSQL database partitioning. Also includes code to generate the necessary SQL.
Clojure
1
star