Skip to content

Commit

Permalink
Add documentation and improve formatting (#4)
Browse files Browse the repository at this point in the history
* Add documentation to all utilities

* Add explanatory comments to certain lines in the utils package

* Document ui/activity and ui/components

* Add docs to the screens

* Clean up theming

* Document viewmodels

* Document viewmodels

* Document attachment widgets

* Document InstancePreview

* Document all the post widgets

* Add links to api models

* Document rest package

* Document domain package

* Finish documentation
  • Loading branch information
wingio committed Dec 8, 2023
1 parent 50a5a87 commit 42d5053
Show file tree
Hide file tree
Showing 74 changed files with 870 additions and 220 deletions.
2 changes: 1 addition & 1 deletion app/src/main/java/xyz/wingio/dimett/Dimett.kt
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@ class Dimett : Application() {
override fun onCreate() {
super.onCreate()

// Add gif support (https://coil-kt.github.io/coil/gifs/)
val imageLoader = ImageLoader.Builder(this)
.components {
if (Build.VERSION.SDK_INT >= 28) {
Expand All @@ -46,7 +47,6 @@ class Dimett : Application() {
loggerModule
)
}

}

}
22 changes: 22 additions & 0 deletions app/src/main/java/xyz/wingio/dimett/ast/Renderer.kt
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,14 @@ import xyz.wingio.syntakts.compose.rememberAsyncRendered
import xyz.wingio.syntakts.markdown.addBasicMarkdownRules
import xyz.wingio.syntakts.syntakts

/**
* Renders a formatted version of [text]
*
* @param text Text to parse and format
* @param emojiMap Used to insert custom emoji into the text
* @param mentionMap All the users mentioned in the post
* @param actionHandler Callback that is passed the actions name
*/
@Composable
fun Syntakts<DefaultRenderContext>.render(
text: String,
Expand All @@ -21,6 +29,11 @@ fun Syntakts<DefaultRenderContext>.render(
context = rememberRenderContext(emojiMap, mentionMap, actionHandler)
)

/**
* Creates a remembered version of [DefaultRenderContext]
*
* @see DefaultRenderContext
*/
@Composable
fun rememberRenderContext(
emojiMap: Map<String, String>,
Expand All @@ -35,6 +48,9 @@ fun rememberRenderContext(
}
}

/**
* Contains all the rules for rendering post content
*/
val DefaultSyntakts = syntakts {
addHashtagRule()
addMentionRule()
Expand All @@ -43,13 +59,19 @@ val DefaultSyntakts = syntakts {
addUnicodeEmojiRule()
}

/**
* Contains the rules for rendering styled string resources
*/
val StringSyntakts = syntakts {
addUrlRule()
addClickableRule()
addBasicMarkdownRules()
addUnicodeEmojiRule()
}

/**
* Only contains rules necessary for emotes and Twemoji
*/
val EmojiSyntakts = syntakts {
addEmojiRule()
addUnicodeEmojiRule()
Expand Down
12 changes: 6 additions & 6 deletions app/src/main/java/xyz/wingio/dimett/ast/Rules.kt
Original file line number Diff line number Diff line change
Expand Up @@ -8,22 +8,22 @@ import xyz.wingio.syntakts.compose.style.toSyntaktsColor
import xyz.wingio.syntakts.style.Style

const val urlRegex =
"https?:\\/\\/([\\w+?]+\\.[\\w+]+)([a-zA-Z0-9\\~\\!\\@\\#\\\$\\%\\^\\&\\*\\(\\)_\\-\\=\\+\\\\\\/\\?\\.\\:\\;\\'\\,]*)?"
"https?:\\/\\/([\\w+?]+\\.[\\w+]+)([a-zA-Z0-9\\~\\!\\@\\#\\\$\\%\\^\\&\\*\\(\\)_\\-\\=\\+\\\\\\/\\?\\.\\:\\;\\'\\,]*)?" // https://example.com

const val hyperlinkRegex =
"\\[(.+?)\\]\\(($urlRegex)\\)"
"\\[(.+?)\\]\\(($urlRegex)\\)" // [link](https://example.com)

const val clickableRegex =
"\\[(.+?)\\]\\{(.+?)\\}"
"\\[(.+?)\\]\\{(.+?)\\}" // [some text]{onSomeAction}

const val emojiRegex =
":(.+?):"
":(.+?):" // :shortcode:

const val mentionRegex =
"@(\\S+?)\\b(@(\\S+)\\b)?"
"@(\\S+?)\\b(@(\\S+)\\b)?" // @user or @[email protected]

const val hashtagRegex =
"#(.+?)\\b"
"#(.+?)\\b" // #sometext

fun Syntakts.Builder<DefaultRenderContext>.addUrlRule() {
rule(urlRegex) { result, context ->
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,9 +4,9 @@ import androidx.compose.ui.graphics.Color
import androidx.compose.ui.platform.UriHandler

data class DefaultRenderContext(
val emojiMap: Map<String, String>,
val mentionMap: Map<String, String>,
val emojiMap: Map<String, String>, // shortcode: url
val mentionMap: Map<String, String>, // username to id
val linkColor: Color,
val uriHandler: UriHandler,
val clickActionHandler: (String) -> Unit
val clickActionHandler: (String) -> Unit // Is passed the action name (Ex. onUserClick)
)
2 changes: 1 addition & 1 deletion app/src/main/java/xyz/wingio/dimett/di/HttpModule.kt
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@ val httpModule = module {
defaultRequest {
header(
HttpHeaders.UserAgent,
"Dimett/${BuildConfig.APPLICATION_ID} v${BuildConfig.VERSION_NAME} (${BuildConfig.VERSION_CODE})${if (BuildConfig.DEBUG) " - Debug" else ""}"
"Dimett/${BuildConfig.APPLICATION_ID} v${BuildConfig.VERSION_NAME} (${BuildConfig.VERSION_CODE})" // Dimett/xyz.wingio.dimett v1.0.0 (1)
)
}
install(Logging) {
Expand Down
3 changes: 3 additions & 0 deletions app/src/main/java/xyz/wingio/dimett/domain/db/AccountsDao.kt
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,9 @@ import androidx.room.Query
import androidx.room.Update
import xyz.wingio.dimett.domain.db.entities.Account

/**
* Used to manage saved [Account]s
*/
@Dao
interface AccountsDao {

Expand Down
3 changes: 3 additions & 0 deletions app/src/main/java/xyz/wingio/dimett/domain/db/AppDatabase.kt
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,9 @@ import androidx.room.TypeConverters
import xyz.wingio.dimett.domain.db.entities.Account
import xyz.wingio.dimett.domain.db.entities.Instance

/**
* Manages complex persistent data (Such as accounts and instances)
*/
@Database(
entities = [Account::class, Instance::class],
version = 1
Expand Down
3 changes: 3 additions & 0 deletions app/src/main/java/xyz/wingio/dimett/domain/db/Converters.kt
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,9 @@ import kotlinx.serialization.json.Json
import xyz.wingio.dimett.rest.dto.CustomEmoji
import xyz.wingio.dimett.rest.dto.user.Field

/**
* Contains methods to convert any non-primitive data types
*/
@ProvidedTypeConverter
class Converters(
private val json: Json
Expand Down
4 changes: 4 additions & 0 deletions app/src/main/java/xyz/wingio/dimett/domain/db/InstancesDao.kt
Original file line number Diff line number Diff line change
Expand Up @@ -5,8 +5,12 @@ import androidx.room.Delete
import androidx.room.Insert
import androidx.room.Query
import androidx.room.Update
import xyz.wingio.dimett.domain.db.entities.Account
import xyz.wingio.dimett.domain.db.entities.Instance

/**
* Used to manage saved [Instance]s
*/
@Dao
interface InstancesDao {

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,11 @@ import androidx.room.PrimaryKey
import xyz.wingio.dimett.rest.dto.CustomEmoji
import xyz.wingio.dimett.rest.dto.user.Field

/**
* Represents an account that can be logged into
*
* @see xyz.wingio.dimett.rest.dto.user.CredentialUser
*/
@Entity(
foreignKeys = [ForeignKey(
entity = Instance::class,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,9 @@ import androidx.room.ColumnInfo
import androidx.room.Entity
import androidx.room.PrimaryKey

/**
* Represents a Mastodon compatible instance with an existing OAuth application
*/
@Entity
data class Instance(
@PrimaryKey val url: String,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -12,33 +12,55 @@ import xyz.wingio.dimett.domain.db.entities.Account
import xyz.wingio.dimett.rest.dto.user.CredentialUser
import xyz.wingio.dimett.utils.mainThread

/**
* Manage all stored accounts (adding, switching, deleting)
*
* @param preferenceManager Used for obtaining the logged in id
*/
class AccountManager(
db: AppDatabase,
private val preferenceManager: PreferenceManager
) {

// All db accesses need to be done on another thread
private val managerScope = CoroutineScope(Dispatchers.IO)
private val dao = db.accountsDao()

/**
* Whether or not all accounts have been loaded yet
*/
var isInitialized by mutableStateOf(false)
private set

/**
* Cached version of the accounts table for fast synchronous account fetching
*/
var accounts: MutableList<Account> = mutableStateListOf()
private set

/**
* Currently logged on account, null when not logged in to any account
*/
val current: Account?
get() = get(preferenceManager.currentAccount)

init {
managerScope.launch {
val accs = dao.listAccounts()
mainThread {
accounts += accs
isInitialized = true
val accs = dao.listAccounts() // Fetch all accounts from the database
mainThread { // Compose state needs to be altered on the main thread
accounts += accs // Cache them all in memory
isInitialized = true // Mark us as ready
}
}
}

/**
* Adds an account using a [CredentialUser]
*
* @param user User to add as an account
* @param token The token for the [user]
* @param instance Instance the [user] is on
*/
fun addAccount(user: CredentialUser, token: String, instance: String) {
managerScope.launch {
val acct = with(user) {
Expand Down Expand Up @@ -77,6 +99,9 @@ class AccountManager(
}
}

/**
* Updates an account
*/
fun updateAccount(account: Account) {
managerScope.launch {
if (account.id.isNotBlank()) {
Expand All @@ -85,12 +110,18 @@ class AccountManager(
}
}

/**
* Switches to another account
*/
fun switchAccount(id: String) {
val otherAccount = accounts.find { it.id == id } ?: return

preferenceManager.currentAccount = otherAccount.id
}

/**
* Retrieves an account by its id or null if one doesn't exist
*/
operator fun get(id: String): Account? {
return accounts.find { it.id == id }
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,14 +5,29 @@ import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.launch
import xyz.wingio.dimett.domain.db.AppDatabase
import xyz.wingio.dimett.domain.db.entities.Instance
import xyz.wingio.dimett.utils.mainThread

class InstanceManager(database: AppDatabase, val accountManager: AccountManager) {
private val dao = database.instancesDao()
/**
* Managed saved instances and associated OAuth apps
*/
class InstanceManager(
database: AppDatabase,
val accountManager: AccountManager
) {

// All db accesses need to be done on another thread
private val managerScope = CoroutineScope(Dispatchers.IO)
private val dao = database.instancesDao()

/**
* Cached version of the instances table for fast synchronous instance fetching
*/
var instances: MutableList<Instance> = mutableListOf()
private set

/**
* Gets the instance for the currently logged on account
*/
val current: Instance?
get() {
val account = accountManager.current ?: return null
Expand All @@ -22,10 +37,21 @@ class InstanceManager(database: AppDatabase, val accountManager: AccountManager)

init {
managerScope.launch {
instances = dao.listInstances().toMutableList()
val _instances = dao.listInstances() // Fetch all accounts from the database
mainThread { // Compose state needs to be altered on the main thread
instances += _instances // Cache them all in memory
}
}
}

/**
* Stores an [Instance]
*
* @param url Base url for the instance
* @param clientId Client id for the associated OAuth app
* @param clientSecret Client secret for the associated OAuth app
* @param features Supported features that this instance has (Ex. reactions)
*/
fun addInstance(
url: String,
clientId: String,
Expand All @@ -40,10 +66,16 @@ class InstanceManager(database: AppDatabase, val accountManager: AccountManager)
return i
}

/**
* Checks if the instance with the given [url] already has an OAuth app we could use
*/
fun exists(url: String): Boolean {
return instances.find { it.url == url } != null
}

/**
* Obtains the instance with the given [url]
*/
operator fun get(url: String) = instances.find { it.url == url }

}
Original file line number Diff line number Diff line change
Expand Up @@ -3,9 +3,15 @@ package xyz.wingio.dimett.domain.manager
import android.content.Context
import xyz.wingio.dimett.domain.manager.base.BasePreferenceManager

/**
* Manage general app preferences
*/
class PreferenceManager(context: Context) :
BasePreferenceManager(context.getSharedPreferences("prefs", Context.MODE_PRIVATE)) {

/**
* Id for the currently logged in account
*/
var currentAccount by stringPreference("current_account")

}
Loading

0 comments on commit 42d5053

Please sign in to comment.