Replace old API wrapper

This commit is contained in:
Jan-Lukas Else 2018-02-04 22:49:32 +01:00
parent 835300c11e
commit b304de3dbb
5 changed files with 78 additions and 206 deletions

View File

@ -36,8 +36,4 @@ dependencies {
implementation 'com.afollestad.material-dialogs:commons:0.9.6.0'
implementation 'pub.devrel:easypermissions:1.1.3'
implementation 'com.github.kittinunf.fuel:fuel-android:1.12.0'
implementation('com.afollestad:bridge:5.1.2') {
exclude group: 'org.json', module: 'json'
exclude group: 'com.intellij', module: 'annotations'
}
}

View File

@ -1,155 +0,0 @@
package telegra.ph
import com.afollestad.bridge.Bridge
import com.afollestad.bridge.MultipartForm
import org.json.JSONArray
import org.json.JSONObject
import java.io.File
object Api {
private val ApiBase = "https://api.telegra.ph/"
fun getPage(path: String?, accessToken: String?, callback: (success: Boolean, page: Page?) -> Unit) {
try {
Bridge.get("${ApiBase}getPage/$path?access_token=%s&return_content=true", accessToken).asString { response, _, _ ->
if (response?.isSuccess == true) callback(true, response.asAsonObject()?.toStockJson()?.parsePageResponse())
else callback(false, null)
}
} catch (e: Exception) {
callback(false, null)
}
}
fun createPage(accessToken: String?, content: String?, title: String?, name: String?, callback: (success: Boolean, Page?) -> Unit) {
try {
Bridge.get("${ApiBase}createPage?access_token=%s&title=%s&author_name=%s&content=%s&return_content=true", accessToken, title, name, content).asString { response, _, _ ->
if (response?.isSuccess == true) callback(true, response.asAsonObject()?.toStockJson()?.parsePageResponse())
else callback(false, null)
}
} catch (e: Exception) {
callback(false, null)
}
}
fun editPage(accessToken: String?, path: String?, content: String?, title: String?, name: String?, callback: (success: Boolean, Page?) -> Unit) {
try {
Bridge.get("${ApiBase}editPage/$path?access_token=%s&title=%s&author_name=%s&content=%s&return_content=true", accessToken, title, name, content).asString { response, _, _ ->
if (response?.isSuccess == true) callback(true, response.asAsonObject()?.toStockJson()?.parsePageResponse())
else callback(false, null)
}
} catch (e: Exception) {
callback(false, null)
}
}
fun createAccount(callback: (accessToken: String?) -> Unit) {
try {
Bridge.get("${ApiBase}createAccount?short_name=teleposter").asString { response, _, _ ->
if (response?.isSuccess == true) callback(response.asAsonObject()?.toStockJson()?.optJSONObject("result")?.optString("access_token"))
else callback(null)
}
} catch (e: Exception) {
callback(null)
}
}
fun getPageList(accessToken: String?, offset: Int = 0, callback: (success: Boolean, MutableList<Page>?) -> Unit) {
try {
Bridge.get("${ApiBase}getPageList?access_token=%s&limit=200&offset=$offset", accessToken).asString { response, _, _ ->
if (response?.isSuccess == true)
response.asAsonObject()?.toStockJson()?.optJSONObject("result")?.let {
val totalCount = it.optInt("total_count")
var currentCount = 200 + offset
val result = mutableListOf<Page>()
it.optJSONArray("pages")?.let {
for (i in 0 until it.length()) {
val page = it.optJSONObject(i)?.parsePage()
if (page != null) result.add(page)
}
}
if (currentCount < totalCount) {
getPageList(accessToken, currentCount) { success, pages ->
if (success && pages != null) {
result.addAll(pages)
callback(true, result)
}
if (!success) callback(false, null)
}
currentCount += 200
} else callback(true, result)
} ?: callback(false, null)
else callback(false, null)
}
} catch (e: Exception) {
callback(false, null)
}
}
private fun JSONObject.parsePageResponse(): Page? {
if (optBoolean("ok", false)) optJSONObject("result")?.let { return it.parsePage() }
return null
}
private fun JSONObject.parsePage(): Page? {
val result = Page()
result.path = optString("path", "")
result.url = optString("url", "")
result.title = optString("title", "")
result.description = optString("description", "")
result.author_name = optString("author_name", "")
result.author_url = optString("author_url", "")
result.image_url = optString("image_url", "")
optJSONArray("content")?.parseContent(result)
result.views = optInt("views", 0)
result.can_edit = optBoolean("can_edit", false)
return result
}
private fun JSONArray.parseContent(result: Page) {
for (i in 0 until length()) {
optJSONObject(i)?.let {
result.content += "<${it.optString("tag", "")}"
it.optJSONObject("attrs")?.let {
for (key in it.keys()) {
result.content += " $key=\"${it.optString(key, "")}\""
}
}
result.content += ">"
it.optJSONArray("children")?.parseContent(result)
result.content += "</${it.optString("tag", "")}>"
}
if (optJSONObject(i) == null) optString(i)?.let {
result.content += it
}
}
}
fun uploadImage(file: File, callback: (url: String?) -> Unit) {
try {
Bridge.post("http://telegra.ph/upload")
.body(MultipartForm().add("FileUpload", file))
.asJsonArray { _, jsonArray, _ ->
val src = jsonArray?.optJSONObject(0)?.optString("src", null)
callback(src)
}
} catch (e: Exception) {
callback(null)
}
}
}
class Page(
var path: String = "",
var url: String = "",
var title: String = "",
var description: String = "",
var author_name: String = "",
var author_url: String = "",
var image_url: String = "",
var content: String = "",
var views: Int = 0,
var can_edit: Boolean = false
)

View File

@ -19,7 +19,7 @@ class MainActivity : AppCompatActivity(), AdvancedWebView.Listener, FileChooserD
private val editor: Editor? by lazy { findViewById<Editor?>(R.id.editor) }
private var currentUrl = ""
private var currentPage: Page? = null
private var currentPage: TelegraphApi.Page? = null
private var editorMode = true
private var canEdit = false
private var isEdit = false
@ -37,8 +37,12 @@ class MainActivity : AppCompatActivity(), AdvancedWebView.Listener, FileChooserD
isVerticalScrollBarEnabled = false
overScrollMode = View.OVER_SCROLL_NEVER
}
if (accessToken().isNullOrBlank()) Api.createAccount { accessToken ->
if (accessToken != null) saveAccessToken(accessToken)
if (accessToken().isBlank()) TelegraphApi.createAccount(shortName = "teleposter") { success, account, error ->
if (success && account != null && account.accessToken != null) {
saveAccessToken(account.accessToken)
} else {
showError(error)
}
}
if (intent.action == Intent.ACTION_VIEW && intent.dataString.contains("telegra.ph")) loadPage(intent.dataString.split("/").last())
else loadEditor()
@ -54,13 +58,14 @@ class MainActivity : AppCompatActivity(), AdvancedWebView.Listener, FileChooserD
webView?.visibility = View.GONE
currentPage = null
// Load
if (path != null) Api.getPage(path, accessToken()) { success, page ->
if (success) runOnUiThread {
if (path != null) TelegraphApi.getPage(accessToken(), path, true) { success, page, error ->
if (success && page != null) {
isEdit = true
currentPage = page
editor?.setText(page?.content ?: "")
editor?.setText(page.content ?: "")
} else {
showError(error)
}
else showError()
}
}
}
@ -74,17 +79,17 @@ class MainActivity : AppCompatActivity(), AdvancedWebView.Listener, FileChooserD
editor?.visibility = View.GONE
currentPage = null
// Load
Api.getPage(path, accessToken()) { success, page ->
if (success) showPage(page)
else showError()
TelegraphApi.getPage(accessToken(), path, true) { success, page, error ->
if (success && page != null) showPage(page)
else showError(error)
}
}
}
private fun showPage(page: Page?) {
private fun showPage(page: TelegraphApi.Page?) {
runOnUiThread {
editorMode = false
canEdit = page?.can_edit ?: false
canEdit = page?.canEdit ?: false
invalidateOptionsMenu()
webView?.visibility = View.VISIBLE
editor?.visibility = View.GONE
@ -94,10 +99,10 @@ class MainActivity : AppCompatActivity(), AdvancedWebView.Listener, FileChooserD
page?.let {
var html = getString(R.string.viewer_html_head)
html += "<h1>${it.title}</h1>"
if (!it.author_name.isEmpty() && !it.author_url.isBlank()) html += "<a href=\"${it.author_url}\">${it.author_name}</a><br>"
else if (!it.author_name.isEmpty()) html += "${it.author_name}<br>"
if (!it.authorName.isNullOrBlank() && !it.authorUrl.isNullOrBlank()) html += "<a href=\"${it.authorUrl}\">${it.authorName}</a><br>"
else if (!it.authorName.isNullOrBlank()) html += "${it.authorName}<br>"
if (it.views != 0) html += "${it.views} times viewed<br><br>"
if (it.content.isBlank()) html += it.description.replace("\n", "<br>") else html += it.content
html += if (it.content.isNullOrBlank()) it.description.replace("\n", "<br>") else it.content
html += getString(R.string.viewer_html_end)
webView?.loadDataWithBaseURL(it.url, html, "text/html; charset=UTF-8", null, null)
currentUrl = it.url
@ -105,11 +110,11 @@ class MainActivity : AppCompatActivity(), AdvancedWebView.Listener, FileChooserD
}
}
private fun showError() {
private fun showError(message: String? = null) {
runOnUiThread {
MaterialDialog.Builder(this)
.title(R.string.error)
.content(R.string.error_desc)
.content(message ?: getString(R.string.error_desc))
.positiveText(android.R.string.ok)
.show()
}
@ -143,8 +148,10 @@ class MainActivity : AppCompatActivity(), AdvancedWebView.Listener, FileChooserD
}
override fun onFileSelection(p0: FileChooserDialog, file: File) {
Api.uploadImage(file) { src ->
if (src != null) editor?.addImage(src)
TelegraphApi.uploadImage(file) { success, src, error ->
if (success && src != null && src.isNotBlank())
editor?.addImage(src)
else showError(error)
}
}
@ -207,18 +214,23 @@ class MainActivity : AppCompatActivity(), AdvancedWebView.Listener, FileChooserD
editor?.getText { json ->
MaterialDialog.Builder(this)
.title(R.string.title_question)
.input(getString(R.string.title_hint), currentPage?.title ?: "", { _, title ->
.input(getString(R.string.title_hint), currentPage?.title
?: "", { _, title ->
MaterialDialog.Builder(this)
.title(R.string.name_question)
.input(getString(R.string.name_hint), if (isEdit) currentPage?.author_name ?: authorName() ?: "" else authorName() ?: "", { _, name ->
.input(getString(R.string.name_hint), if (isEdit) currentPage?.authorName
?: authorName() ?: "" else authorName()
?: "", { _, name ->
if (!isEdit) saveAuthorName(name.toString())
if (isEdit) Api.editPage(accessToken(), currentPage?.path, json, title.toString(), name.toString()) { success, page ->
if (success) showPage(page)
else showError()
}
else Api.createPage(accessToken(), json, title.toString(), name.toString()) { success, page ->
if (success) showPage(page)
else showError()
if (isEdit) TelegraphApi.editPage(accessToken(), currentPage?.path
?: "", authorName = name.toString(), title = title.toString(), content = json
?: "", returnContent = true) { success, page, error ->
if (success && page != null) showPage(page)
else showError(error)
} else TelegraphApi.createPage(accessToken(), content = json
?: "", title = title.toString(), authorName = name.toString(), returnContent = true) { success, page, error ->
if (success && page != null) showPage(page)
else showError(error)
}
})
.show()
@ -255,18 +267,17 @@ class MainActivity : AppCompatActivity(), AdvancedWebView.Listener, FileChooserD
true
}
R.id.published -> {
Api.getPageList(accessToken()) { success, result ->
if (!success || result == null || result.isEmpty()) showError()
else {
TelegraphApi.getPageList(accessToken()) { success, pageList, error ->
if (success && pageList != null && pageList.pages != null) {
MaterialDialog.Builder(this)
.title(R.string.published)
.positiveText(android.R.string.ok)
.items(result.map(Page::title))
.items(pageList.pages.map { it.title })
.itemsCallback { _, _, i, _ ->
loadPage(result.map(Page::path)[i])
loadPage(pageList.pages[i].path)
}
.show()
}
} else showError(error)
}
true
}

View File

@ -3,7 +3,8 @@ package telegra.ph
import android.content.Context
import android.preference.PreferenceManager
fun Context.bookmarks(): MutableList<String> = PreferenceManager.getDefaultSharedPreferences(this).getString("bookmarks", null)?.split("+++;+++")?.toMutableList() ?: mutableListOf("apixxx;xxxAPI Documentation")
fun Context.bookmarks(): MutableList<String> = PreferenceManager.getDefaultSharedPreferences(this).getString("bookmarks", null)?.split("+++;+++")?.toMutableList()
?: mutableListOf("apixxx;xxxAPI Documentation")
fun Context.addBookmark(entry: String) {
PreferenceManager.getDefaultSharedPreferences(this).edit().putString("bookmarks", bookmarks().apply {
@ -15,7 +16,7 @@ fun Context.deleteBookmark(path: String) {
PreferenceManager.getDefaultSharedPreferences(this).edit().putString("bookmarks", bookmarks().filter { !it.contains(path) }.joinToString(separator = "+++;+++")).apply()
}
fun Context.accessToken(): String? = PreferenceManager.getDefaultSharedPreferences(this).getString("accessToken", null)
fun Context.accessToken(): String = PreferenceManager.getDefaultSharedPreferences(this).getString("accessToken", "")
fun Context.saveAccessToken(token: String) {
PreferenceManager.getDefaultSharedPreferences(this).edit().putString("accessToken", token).apply()

View File

@ -2,16 +2,15 @@ package telegra.ph
import com.github.kittinunf.fuel.android.core.Json
import com.github.kittinunf.fuel.android.extension.responseJson
import com.github.kittinunf.fuel.core.FuelError
import com.github.kittinunf.fuel.core.FuelManager
import com.github.kittinunf.fuel.core.Request
import com.github.kittinunf.fuel.core.Response
import com.github.kittinunf.fuel.core.*
import com.github.kittinunf.fuel.httpGet
import com.github.kittinunf.fuel.httpUpload
import com.github.kittinunf.result.Result
import org.json.JSONArray
import org.json.JSONObject
import java.io.File
class TelegraphApi {
object TelegraphApi {
// Telegraph
@ -60,20 +59,20 @@ class TelegraphApi {
}
}
fun getPage(path: String, returnContent: Boolean? = null, callback: (success: Boolean, page: Page?, error: String?) -> Unit) {
callService("/getPage", listOf("path" to path, "return_content" to returnContent)) { _, _, result ->
fun getPage(accessToken: String? = null, path: String, returnContent: Boolean? = null, callback: (success: Boolean, page: Page?, error: String?) -> Unit) {
callService("/getPage", listOf("access_token" to accessToken, "path" to path, "return_content" to returnContent)) { _, _, result ->
handleResponse(result, callback) { obj: JSONObject -> callback(true, Page(obj), null) }
}
}
fun getPageList(accessToken: String, offset: Int? = null, limit: Int? = null, callback: (success: Boolean, page: PageList?, error: String?) -> Unit) {
callService("/getPage", listOf("access_token" to accessToken, "offset" to offset, "limit" to limit)) { _, _, result ->
callService("/getPageList", listOf("access_token" to accessToken, "offset" to offset, "limit" to limit)) { _, _, result ->
handleResponse(result, callback) { obj: JSONObject -> callback(true, PageList(obj), null) }
}
}
fun getViews(path: String, year: Int? = null, month: Int? = null, day: Int? = null, hour: Int? = null, callback: (success: Boolean, page: PageViews?, error: String?) -> Unit) {
callService("/getPage", listOf("path" to path, "year" to year, "month" to month, "day" to day, "hour" to hour)) { _, _, result ->
callService("/getViews", listOf("path" to path, "year" to year, "month" to month, "day" to day, "hour" to hour)) { _, _, result ->
handleResponse(result, callback) { obj: JSONObject -> callback(true, PageViews(obj), null) }
}
}
@ -139,14 +138,34 @@ class TelegraphApi {
if (error == null && json != null) {
val jsonObj = json.obj()
if (jsonObj.optBoolean("ok")) {
handler(true, null, null)
} else {
callback(jsonObj.optJSONObject("result"))
} else {
handler(false, null, jsonObj.optString("error"))
}
} else {
handler(false, null, error?.message)
}
}
fun uploadImage(file: File, callback: (success: Boolean, src: String?, error: String?) -> Unit) {
"http://telegra.ph/upload".httpUpload()
.dataParts { _, _ ->
listOf(DataPart(file, name = "FileUpload"))
}
.responseJson { _, _, result ->
val (json, error) = result
if (error == null && json != null) {
val jsonObj = json.array().optJSONObject(0)
val src = jsonObj?.optString("src")
if (src != null) {
callback(true, src, null)
} else {
callback(false, null, null)
}
} else {
callback(false, null, error?.message)
}
}
}
}