Skip to content


Contributions are highly encouraged!

To see what you can do, you can look at open issues, or contact me directly!

When contributing code to Pattle, your code will be licensed under the AGPLv3.

General contribution steps

  1. Fork the project.
  2. Create a feature/bug branch named, for example: logout.
  3. Make your changes.
  4. Add copyright notices
    1. If you have edited an existing file, add your copyright notice under the existing ones last, in the format of: Copyright (C) YEAR Full Name <> Note the double space between YEAR and Full Name.
    2. If you created a file, add the license file header with your name and email. (See File headers)
  5. Commit your changes and create a merge request.

Note that if you're creating a new feature, you probably also need to implement an API call in Trace.

File headers

Every file has a license header with copyright notices. Every copyright notice is in the format of:

Copyright (C) YEAR  Full Name <>

Note the double space between the year and full name.

The creator of the file is on top, and every contributor afterwards is listed below in chronological order. An example file header would be:

 * Copyright (C) 2018  Wilko Manger <>
 * Copyright (C) 2018  Nathan van Beelen <>
 * This file is part of Pattle.
 * Pattle is free software: you can redistribute it and/or modify
 * it under the terms of the GNU Affero General Public License as published by
 * the Free Software Foundation, either version 3 of the License, or
 * (at your option) any later version.
 * Pattle is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * GNU Affero General Public License for more details.
 * You should have received a copy of the GNU Affero General Public License
 * along with Pattle.  If not, see <>.

Here, Wilko Manger is the file creator, and Nathan van Beelen contributed later on.


Pattle is structured and designed along the principles of MVVM. It's recommend that you read up on this before contributing.



There are two top level packages: data and ui, representing the data and UI layer respectively.


├── chat
│   ├── event
│   │   └── model
│   ├── message
│   └── overview
├── media
├── sync
└── user

The data package contains a package for each type of resource, for example: media, user, and chat, where the latter is again divided into specific resource packages like message and overview.

An odd one out is the user resource, it does not simply fetch User's, but also handles other user management related tasks like logging in, registering, checking if a username is available, etc.


These 'resource packages' can contain a RemoteSource and LocalSource, for example MediaRemoteSource and MediaLocalSource. They will also include model data classes representing the resource.

As the name implies, the RemoteSource fetches from a remote source, often times using Trace's MatrixClient.

The LocalSource handles data that has been saved locally, these sources are mostly used for caching.


Every resource has a Repository, which combines the two Remote and Local sources. The Repository handles when to cache and when to fetch from a remote source.

ViewModels should only depend on the Repository, not on individual Sources.


Every resource has a Koin module for dependency injection, containing the Repository and Sources.


The sync package is not a resource, but manages syncing data between the client and homeserver.

All RemoteSources should subscribe to the Flowable provided by the SyncManager for new data.


├── base
├── main
│   ├── chat
│   ├── chatoverview
├── start
│   ├── phase
│   │   ├── identity
│   │   ├── info
│   │   ├── key
│   │   └── verify
└── util

The ui package represents the UI layer of the app.


The base package contains a BaseFragment and BaseViewModel, which all fragments and viewmodels inherit from, respectively.


The main package covers the core part of application: messaging, chat overview, creating chats, etc.

The package is divided in packages representing a main part of the application. For example, the chatoverview package contains the ChatOverviewFragment, which a user will see when they launch the app and are logged in.


The start package covers all UI and logic when the user opens the app for the first time, when they're not logged in or registered.

It also contains a phase package, which is again divided into packages representing a different phase of authentication:

  1. identity: Phone, email or username input
  2. key: For now only password, later on also token based (see #21.
  3. verify*: Verify that the user is human
  4. info*: Avatar and display name input

* Only used for registration.

Note that these phases are reused for both logging in and registering, see the authentication documentation for details.


The util package contains classes that are reused accross the ui package.