Skip to content

Update Server API #31

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 1 commit into from
Jun 21, 2025
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 2 additions & 1 deletion app/build.gradle.kts
Original file line number Diff line number Diff line change
Expand Up @@ -70,14 +70,15 @@ dependencies {
implementation(libs.firebase.crashlytics)
implementation(libs.okhttp)
implementation(libs.retrofit)
implementation(libs.retrofit.gson)
implementation(libs.converter.moshi)
implementation(libs.glide)
implementation(libs.media3.exoplayer)
implementation(libs.media3.exoplayer.dash)
implementation(libs.media3.ui)
implementation(libs.media3.ui.compose)
implementation(libs.taptargetview)
ksp(libs.androidx.room.compiler)
ksp(libs.moshi.kotlin.codegen)
testImplementation(libs.junit)
androidTestImplementation(libs.androidx.junit)
androidTestImplementation(libs.androidx.espresso.core)
Expand Down
4 changes: 0 additions & 4 deletions app/proguard-rules.pro
Original file line number Diff line number Diff line change
Expand Up @@ -44,10 +44,6 @@
-keep class org.cssnr.zipline.api.ZiplineApi$* { *; }
-keep class org.cssnr.zipline.api.FeedbackApi$* { *; }

-keepclassmembers class * {
@com.google.gson.annotations.SerializedName <fields>;
}


## https://github.com/square/retrofit/blob/trunk/retrofit/src/main/resources/META-INF/proguard/retrofit2.pro
# Retrofit does reflection on generic parameters. InnerClasses is required to use Signature and
Expand Down
15 changes: 10 additions & 5 deletions app/src/main/java/org/cssnr/zipline/api/FeedbackApi.kt
Original file line number Diff line number Diff line change
@@ -1,15 +1,18 @@
package org.cssnr.zipline.api

import android.content.Context
import android.os.Build
import android.util.Log
import com.google.gson.GsonBuilder
import com.squareup.moshi.Json
import com.squareup.moshi.JsonClass
import com.squareup.moshi.Moshi
import okhttp3.MediaType.Companion.toMediaTypeOrNull
import okhttp3.OkHttpClient
import okhttp3.ResponseBody.Companion.toResponseBody
import org.cssnr.zipline.R
import retrofit2.Response
import retrofit2.Retrofit
import retrofit2.converter.gson.GsonConverterFactory
import retrofit2.converter.moshi.MoshiConverterFactory
import retrofit2.http.Body
import retrofit2.http.POST

Expand All @@ -30,7 +33,7 @@ class FeedbackApi(val context: Context) {
suspend fun sendFeedback(messageText: String): Response<Unit> {
Log.d("sendFeedback", "messageText: $messageText")
val feedbackText =
"**${context.getString(R.string.app_name)}** `v${versionName}`\n```\n${messageText}\n```"
"**${context.getString(R.string.app_name)}** `v${versionName}` API **${Build.VERSION.SDK_INT}**\n```\n${messageText}\n```"
Log.d("sendFeedback", "feedbackText: $feedbackText")
val message = Message(content = feedbackText)
Log.d("sendFeedback", "message: $message")
Expand All @@ -42,7 +45,9 @@ class FeedbackApi(val context: Context) {
}
}

@JsonClass(generateAdapter = true)
data class Message(
@Json(name = "content")
val content: String
)

Expand All @@ -62,10 +67,10 @@ class FeedbackApi(val context: Context) {
chain.proceed(request)
}
.build()
val gson = GsonBuilder().create()
val moshi = Moshi.Builder().build()
return Retrofit.Builder()
.baseUrl(RELAY_URL)
.addConverterFactory(GsonConverterFactory.create(gson))
.addConverterFactory(MoshiConverterFactory.create(moshi))
.client(client)
.build()
}
Expand Down
76 changes: 32 additions & 44 deletions app/src/main/java/org/cssnr/zipline/api/ZiplineApi.kt
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,9 @@ import android.util.Log
import android.webkit.CookieManager
import androidx.core.content.edit
import androidx.preference.PreferenceManager
import com.google.gson.annotations.SerializedName
import com.squareup.moshi.Json
import com.squareup.moshi.JsonClass
import com.squareup.moshi.Moshi
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.withContext
import okhttp3.Cookie
Expand All @@ -20,7 +22,7 @@ import okhttp3.RequestBody.Companion.toRequestBody
import org.cssnr.zipline.R
import retrofit2.Response
import retrofit2.Retrofit
import retrofit2.converter.gson.GsonConverterFactory
import retrofit2.converter.moshi.MoshiConverterFactory
import retrofit2.http.Body
import retrofit2.http.GET
import retrofit2.http.Header
Expand All @@ -31,14 +33,14 @@ import java.io.InputStream
import java.net.URLConnection

class ZiplineApi(private val context: Context, url: String? = null) {

val api: ApiService
private var ziplineUrl: String
private var ziplineToken: String

private val preferences by lazy { PreferenceManager.getDefaultSharedPreferences(context) }

private lateinit var cookieJar: SimpleCookieJar
private lateinit var client: OkHttpClient

private val preferences by lazy { PreferenceManager.getDefaultSharedPreferences(context) }

init {
ziplineUrl = url ?: preferences.getString("ziplineUrl", null) ?: ""
Expand Down Expand Up @@ -164,7 +166,7 @@ class ZiplineApi(private val context: Context, url: String? = null) {
val userAgent = "${context.getString(R.string.app_name)}/${versionName}"
Log.d("createRetrofit", "versionName: $versionName")
cookieJar = SimpleCookieJar()
client = OkHttpClient.Builder()
val client = OkHttpClient.Builder()
.cookieJar(cookieJar)
.addInterceptor { chain ->
val request = chain.request().newBuilder()
Expand All @@ -174,16 +176,19 @@ class ZiplineApi(private val context: Context, url: String? = null) {
chain.proceed(request)
}
.build()
val moshi = Moshi.Builder().build()
return Retrofit.Builder()
.baseUrl(baseUrl)
.addConverterFactory(GsonConverterFactory.create())
.addConverterFactory(MoshiConverterFactory.create(moshi))
.client(client)
.build()
}

interface ApiService {
@POST("auth/login")
suspend fun postLogin(@Body request: LoginRequest): Response<Unit>
suspend fun postLogin(
@Body request: LoginRequest,
): Response<Unit>

@GET("user/token")
suspend fun getToken(): TokenResponse
Expand All @@ -204,54 +209,61 @@ class ZiplineApi(private val context: Context, url: String? = null) {
): Response<ShortResponse>
}

@JsonClass(generateAdapter = true)
data class LoginRequest(
val username: String,
val password: String,
)

@JsonClass(generateAdapter = true)
data class TokenResponse(
val token: String
val token: String,
)

@JsonClass(generateAdapter = true)
data class FileResponse(
val files: List<UploadedFile>
val files: List<UploadedFile>,
)

@JsonClass(generateAdapter = true)
data class UploadedFile(
val id: String,
val type: String,
val url: String,
)

@JsonClass(generateAdapter = true)
data class ShortRequest(
val destination: String,
val vanity: String?,
val enabled: Boolean,
)

@JsonClass(generateAdapter = true)
data class ShortResponse(
val id: String,
val createdAt: String,
val updatedAt: String,
val code: String,
val vanity: String,
val vanity: String?,
val destination: String,
val views: Int,
val maxViews: Int?,
val enabled: Boolean,
val userId: String,
val url: String
val url: String,
)

@JsonClass(generateAdapter = true)
data class StatsResponse(
@SerializedName("filesUploaded") val filesUploaded: Int,
@SerializedName("favoriteFiles") val favoriteFiles: Int,
@SerializedName("views") val views: Int,
@SerializedName("avgViews") val avgViews: Double,
@SerializedName("storageUsed") val storageUsed: Long,
@SerializedName("avgStorageUsed") val avgStorageUsed: Double,
@SerializedName("urlsCreated") val urlsCreated: Int,
@SerializedName("urlViews") val urlViews: Int,
@Json(name = "filesUploaded") val filesUploaded: Int,
@Json(name = "favoriteFiles") val favoriteFiles: Int,
@Json(name = "views") val views: Int,
@Json(name = "avgViews") val avgViews: Double,
@Json(name = "storageUsed") val storageUsed: Long,
@Json(name = "avgStorageUsed") val avgStorageUsed: Double,
@Json(name = "urlsCreated") val urlsCreated: Int,
@Json(name = "urlViews") val urlViews: Int,
)


Expand All @@ -276,27 +288,3 @@ class ZiplineApi(private val context: Context, url: String? = null) {
//}
}
}


//data class LoginResponse(
// val user: TokenUser
//)

//data class TokenUser(
// val id: String,
// val username: String,
// val token: String,
//)

//fun getFileNameFromUri(context: Context, uri: Uri): String? {
// var fileName: String? = null
// context.contentResolver.query(uri, null, null, null, null).use { cursor ->
// if (cursor != null && cursor.moveToFirst()) {
// val nameIndex = cursor.getColumnIndex(OpenableColumns.DISPLAY_NAME)
// if (nameIndex != -1) {
// fileName = cursor.getString(nameIndex)
// }
// }
// }
// return fileName
//}
4 changes: 3 additions & 1 deletion gradle/libs.versions.toml
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@ crashlyticsPlugin = "3.0.4"

okhttp = "4.12.0"
retrofit = "3.0.0"
moshiKotlinCodegen = "1.15.2"
glide = "5.0.0-rc01"
media3 = "1.7.1"
taptargetview = "1.15.0"
Expand Down Expand Up @@ -53,7 +54,8 @@ firebase-crashlytics = { group = "com.google.firebase", name = "firebase-crashly

okhttp = { module = "com.squareup.okhttp3:okhttp", version.ref = "okhttp" }
retrofit = { module = "com.squareup.retrofit2:retrofit", version.ref = "retrofit" }
retrofit-gson = { module = "com.squareup.retrofit2:converter-gson", version.ref = "retrofit" }
converter-moshi = { group = "com.squareup.retrofit2", name = "converter-moshi", version.ref = "retrofit" }
moshi-kotlin-codegen = { group = "com.squareup.moshi", name = "moshi-kotlin-codegen", version.ref = "moshiKotlinCodegen" }
glide = { group = "com.github.bumptech.glide", name = "glide", version.ref = "glide" }
#okhttp3-integration = { group = "com.github.bumptech.glide", name = "okhttp3-integration", version.ref = "glide" }
media3-exoplayer = { group = "androidx.media3", name = "media3-exoplayer", version.ref = "media3" }
Expand Down
Loading