Implement most of the API (#23)

Add Kotlin representations (data classes) of the Types of the Mastodon API. 
Create helper function to make API from the interface.
Test the deserialization.
This commit is contained in:
Wv5twkFEKh54vo4tta9yu7dHa3 2020-03-04 18:04:55 +01:00 committed by GitHub
parent 5ec65cdad2
commit aa788f9720
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
19 changed files with 387 additions and 179 deletions

View File

@ -25,5 +25,5 @@ script:
after_script:
# Report test coverage to Code Climate
- export JACOCO_SOURCE_PATH=app/src/main/java/
- ./cc-test-reporter format-coverage ./app/build/reports/coverage/debug/report.xml --input-type jacoco
- ./cc-test-reporter format-coverage ./app/build/reports/jacoco/jacocoTestReport/jacocoTestReport.xml --input-type jacoco
- ./cc-test-reporter upload-coverage

View File

@ -6,7 +6,10 @@ apply plugin: 'jacoco'
android {
compileSdkVersion 29
buildToolsVersion "29.0.3"
compileOptions {
sourceCompatibility JavaVersion.VERSION_1_8
targetCompatibility JavaVersion.VERSION_1_8
}
defaultConfig {
applicationId "com.h.pixeldroid"
minSdkVersion 23
@ -35,6 +38,15 @@ dependencies {
implementation 'androidx.appcompat:appcompat:1.1.0'
implementation 'androidx.core:core-ktx:1.2.0'
implementation 'androidx.constraintlayout:constraintlayout:1.1.3'
implementation "com.squareup.okhttp3:okhttp:4.4.0"
implementation 'com.squareup.retrofit2:retrofit:2.7.1'
implementation 'com.squareup.retrofit2:converter-gson:2.7.1'
implementation 'com.squareup.retrofit2:adapter-rxjava2:2.7.1'
implementation 'io.reactivex.rxjava2:rxjava:2.2.16'
implementation 'io.reactivex.rxjava2:rxandroid:2.1.1'
testImplementation "com.github.tomakehurst:wiremock-jre8:2.26.2"
testImplementation "com.nhaarman.mockitokotlin2:mockito-kotlin:2.2.0"
testImplementation 'junit:junit:4.13'
androidTestImplementation 'androidx.test.ext:junit:1.1.1'
androidTestImplementation 'androidx.test.espresso:espresso-core:3.2.0'
@ -54,13 +66,11 @@ task jacocoTestReport(type: JacocoReport, dependsOn: ['testDebugUnitTest', 'crea
}
def fileFilter = ['**/R.class', '**/R$*.class', '**/BuildConfig.*', '**/Manifest*.*', '**/*Test*.*', 'android/**/*.*']
def debugTree = fileTree(dir: "$project.buildDir/intermediates/classes/debug", excludes: fileFilter)
def kotlinDebugTree = fileTree(dir: "$project.buildDir/tmp/kotlin-classes/debug", excludes: fileFilter)
def javaMainSrc = "$project.projectDir/src/main/java"
def kotlinMainSrc = "$project.projectDir/src/main/kotlin"
sourceDirectories = files([javaMainSrc, kotlinMainSrc])
classDirectories = files([debugTree, kotlinDebugTree])
def mainSrc = "$project.projectDir/src/main/java"
sourceDirectories = files([mainSrc])
classDirectories = files([kotlinDebugTree])
executionData = fileTree(dir: project.buildDir, includes: [
'jacoco/testDebugUnitTest.exec', 'outputs/code-coverage/connected/*coverage.ec'
'jacoco/testDebugUnitTest.exec', 'outputs/code-coverage/debugAndroidTest/connected/*coverage.ec'
])
}

View File

@ -1,7 +1,7 @@
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.h.pixeldroid">
<uses-permission android:name="android.permission.INTERNET"/>
<application
android:allowBackup="true"
android:icon="@mipmap/ic_launcher"

View File

@ -2,6 +2,15 @@ package com.h.pixeldroid
import androidx.appcompat.app.AppCompatActivity
import android.os.Bundle
import android.util.Log
import com.h.pixeldroid.api.PixelfedAPI
import com.h.pixeldroid.objects.Status
import retrofit2.Call
import retrofit2.Callback
import retrofit2.Response
import retrofit2.Retrofit
import retrofit2.adapter.rxjava2.RxJava2CallAdapterFactory
import retrofit2.converter.gson.GsonConverterFactory
class MainActivity : AppCompatActivity() {
@ -9,4 +18,5 @@ class MainActivity : AppCompatActivity() {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)
}
}

View File

@ -0,0 +1,42 @@
package com.h.pixeldroid.api
import android.util.Log
import com.h.pixeldroid.objects.*
import retrofit2.Call
import retrofit2.Callback
import retrofit2.Response
import retrofit2.Retrofit
import retrofit2.adapter.rxjava2.RxJava2CallAdapterFactory
import retrofit2.converter.gson.GsonConverterFactory
import retrofit2.http.GET
import retrofit2.http.Query
/*
Implements the Pixelfed API
https://docs.pixelfed.org/technical-documentation/api-v1.html
However, since this is mostly based on the Mastodon API, the documentation there
will be more useful: https://docs.joinmastodon.org/
*/
interface PixelfedAPI {
@GET("/api/v1/timelines/public")
fun timelinePublic(
@Query("local") local: Boolean?,
@Query("max_id") max_id: String?,
@Query("since_id") since_id: String?,
@Query("min_id") min_id: String?,
@Query("limit") limit: Int?
): Call<List<Status>>
companion object {
fun create(baseUrl: String): PixelfedAPI {
return Retrofit.Builder()
.baseUrl(baseUrl)
.addConverterFactory(GsonConverterFactory.create())
.addCallAdapterFactory(RxJava2CallAdapterFactory.create())
.build().create(PixelfedAPI::class.java)
}
}
}

View File

@ -0,0 +1,35 @@
package com.h.pixeldroid.objects
/*
Represents a user and their associated profile.
https://docs.joinmastodon.org/entities/account/
*/
data class Account(
//Base attributes
val id: String,
val username: String,
val acct: String,
val url: String, //HTTPS URL
//Display attributes
val display_name: String,
val note: String, //HTML
val avatar: String, //URL
val avatar_static: String, //URL
val header: String, //URL
val header_static: String, //URL
val locked: Boolean,
val emojis: List<Emoji>,
val discoverable: Boolean,
//Statistical attributes
val created_at: String, //ISO 8601 Datetime (maybe can use a date type)
val statuses_count: Int,
val followers_count: Int,
val following_count: Int,
//Optional attributes
val moved: Account? = null,
val fields: List<Field>? = emptyList(),
val bot: Boolean = false,
val source: Source? = null
)

View File

@ -0,0 +1,9 @@
package com.h.pixeldroid.objects
data class Application (
//Required attributes
val name: String,
//Optional attributes
val website: String? = null,
val vapid_key: String? = null
)

View File

@ -0,0 +1,19 @@
package com.h.pixeldroid.objects
data class Attachment(
//Required attributes
val id: String,
val type: AttachmentType,
val url: String, //URL
val preview_url: String, //URL
//Optional attributes
val remote_url: String? = null, //URL
val text_url: String? = null, //URL
//TODO meta
val description: String? = null,
val blurhash: String? = null
) {
enum class AttachmentType {
unknown, image, gifv, video, audio
}
}

View File

@ -0,0 +1,23 @@
package com.h.pixeldroid.objects
data class Card(
//Required attributes
val url: String, //URL
val title: String,
val description: String,
val type: CardType,
//Optional attributes
val author_name: String? = null,
val author_url: String? = null, //URL
val provider_name: String? = null,
val provider_url: String? = null, //URL
val html: String? = null, //HTML
val width: Int? = null,
val height: Int? = null,
val image: String? = null, //URL
val embed_url: String? = null //URL
) {
enum class CardType {
link, photo, video, rich
}
}

View File

@ -0,0 +1,11 @@
package com.h.pixeldroid.objects
data class Emoji(
//Required attributes
val shortcode: String,
val url: String, //URL
val static_url: String, //URL
val visible_in_picker: Boolean,
//Optional attributes
val category: String? = null
)

View File

@ -0,0 +1,5 @@
package com.h.pixeldroid.objects
class Field {
}

View File

@ -0,0 +1,8 @@
package com.h.pixeldroid.objects
data class History(
//Required attributes
val day: String,
val uses: String,
val accounts: String
)

View File

@ -0,0 +1,4 @@
package com.h.pixeldroid.objects
class Mention {
}

View File

@ -0,0 +1,5 @@
package com.h.pixeldroid.objects
class Poll {
}

View File

@ -0,0 +1,5 @@
package com.h.pixeldroid.objects
class Source {
}

View File

@ -0,0 +1,48 @@
package com.h.pixeldroid.objects
/*
Represents a status posted by an account.
https://docs.joinmastodon.org/entities/status/
*/
data class Status(
//Base attributes
val id: String,
val uri: String,
val created_at: String, //ISO 8601 Datetime (maybe can use a date type)
val account: Account,
val content: String, //HTML
val visibility: Visibility,
val sensitive: Boolean,
val spoiler_text: String,
val media_attachments: List<Attachment>,
val application: Application,
//Rendering attributes
val mentions: List<Mention>,
val tags: List<Tag>,
val emojis: List<Emoji>,
//Informational attributes
val reblogs_count: Int,
val favourites_count: Int,
val replies_count: Int,
//Nullable attributes
val url: String?, //URL
val in_reply_to_id: String?,
val in_reply_to_account: String?,
val reblog: Status?,
val poll: Poll?,
val card: Card?,
val language: String?, //ISO 639 Part 1 two-letter language code
val text: String?,
//Authorized user attributes
val favourited: Boolean,
val reblogged: Boolean,
val muted: Boolean,
val bookmarked: Boolean,
val pinned: Boolean
)
{
enum class Visibility {
public, unlisted, private, direct
}
}

View File

@ -0,0 +1,9 @@
package com.h.pixeldroid.objects
data class Tag(
//Base attributes
val name: String,
val url: String,
//Optional attributes
val history: List<History>? = emptyList()
)

View File

@ -1,170 +0,0 @@
<?xml version="1.0" encoding="utf-8"?>
<vector xmlns:android="http://schemas.android.com/apk/res/android"
android:width="108dp"
android:height="108dp"
android:viewportWidth="108"
android:viewportHeight="108">
<path
android:fillColor="#3DDC84"
android:pathData="M0,0h108v108h-108z" />
<path
android:fillColor="#00000000"
android:pathData="M9,0L9,108"
android:strokeWidth="0.8"
android:strokeColor="#33FFFFFF" />
<path
android:fillColor="#00000000"
android:pathData="M19,0L19,108"
android:strokeWidth="0.8"
android:strokeColor="#33FFFFFF" />
<path
android:fillColor="#00000000"
android:pathData="M29,0L29,108"
android:strokeWidth="0.8"
android:strokeColor="#33FFFFFF" />
<path
android:fillColor="#00000000"
android:pathData="M39,0L39,108"
android:strokeWidth="0.8"
android:strokeColor="#33FFFFFF" />
<path
android:fillColor="#00000000"
android:pathData="M49,0L49,108"
android:strokeWidth="0.8"
android:strokeColor="#33FFFFFF" />
<path
android:fillColor="#00000000"
android:pathData="M59,0L59,108"
android:strokeWidth="0.8"
android:strokeColor="#33FFFFFF" />
<path
android:fillColor="#00000000"
android:pathData="M69,0L69,108"
android:strokeWidth="0.8"
android:strokeColor="#33FFFFFF" />
<path
android:fillColor="#00000000"
android:pathData="M79,0L79,108"
android:strokeWidth="0.8"
android:strokeColor="#33FFFFFF" />
<path
android:fillColor="#00000000"
android:pathData="M89,0L89,108"
android:strokeWidth="0.8"
android:strokeColor="#33FFFFFF" />
<path
android:fillColor="#00000000"
android:pathData="M99,0L99,108"
android:strokeWidth="0.8"
android:strokeColor="#33FFFFFF" />
<path
android:fillColor="#00000000"
android:pathData="M0,9L108,9"
android:strokeWidth="0.8"
android:strokeColor="#33FFFFFF" />
<path
android:fillColor="#00000000"
android:pathData="M0,19L108,19"
android:strokeWidth="0.8"
android:strokeColor="#33FFFFFF" />
<path
android:fillColor="#00000000"
android:pathData="M0,29L108,29"
android:strokeWidth="0.8"
android:strokeColor="#33FFFFFF" />
<path
android:fillColor="#00000000"
android:pathData="M0,39L108,39"
android:strokeWidth="0.8"
android:strokeColor="#33FFFFFF" />
<path
android:fillColor="#00000000"
android:pathData="M0,49L108,49"
android:strokeWidth="0.8"
android:strokeColor="#33FFFFFF" />
<path
android:fillColor="#00000000"
android:pathData="M0,59L108,59"
android:strokeWidth="0.8"
android:strokeColor="#33FFFFFF" />
<path
android:fillColor="#00000000"
android:pathData="M0,69L108,69"
android:strokeWidth="0.8"
android:strokeColor="#33FFFFFF" />
<path
android:fillColor="#00000000"
android:pathData="M0,79L108,79"
android:strokeWidth="0.8"
android:strokeColor="#33FFFFFF" />
<path
android:fillColor="#00000000"
android:pathData="M0,89L108,89"
android:strokeWidth="0.8"
android:strokeColor="#33FFFFFF" />
<path
android:fillColor="#00000000"
android:pathData="M0,99L108,99"
android:strokeWidth="0.8"
android:strokeColor="#33FFFFFF" />
<path
android:fillColor="#00000000"
android:pathData="M19,29L89,29"
android:strokeWidth="0.8"
android:strokeColor="#33FFFFFF" />
<path
android:fillColor="#00000000"
android:pathData="M19,39L89,39"
android:strokeWidth="0.8"
android:strokeColor="#33FFFFFF" />
<path
android:fillColor="#00000000"
android:pathData="M19,49L89,49"
android:strokeWidth="0.8"
android:strokeColor="#33FFFFFF" />
<path
android:fillColor="#00000000"
android:pathData="M19,59L89,59"
android:strokeWidth="0.8"
android:strokeColor="#33FFFFFF" />
<path
android:fillColor="#00000000"
android:pathData="M19,69L89,69"
android:strokeWidth="0.8"
android:strokeColor="#33FFFFFF" />
<path
android:fillColor="#00000000"
android:pathData="M19,79L89,79"
android:strokeWidth="0.8"
android:strokeColor="#33FFFFFF" />
<path
android:fillColor="#00000000"
android:pathData="M29,19L29,89"
android:strokeWidth="0.8"
android:strokeColor="#33FFFFFF" />
<path
android:fillColor="#00000000"
android:pathData="M39,19L39,89"
android:strokeWidth="0.8"
android:strokeColor="#33FFFFFF" />
<path
android:fillColor="#00000000"
android:pathData="M49,19L49,89"
android:strokeWidth="0.8"
android:strokeColor="#33FFFFFF" />
<path
android:fillColor="#00000000"
android:pathData="M59,19L59,89"
android:strokeWidth="0.8"
android:strokeColor="#33FFFFFF" />
<path
android:fillColor="#00000000"
android:pathData="M69,19L69,89"
android:strokeWidth="0.8"
android:strokeColor="#33FFFFFF" />
<path
android:fillColor="#00000000"
android:pathData="M79,19L79,89"
android:strokeWidth="0.8"
android:strokeColor="#33FFFFFF" />
</vector>

File diff suppressed because one or more lines are too long