「アプリ設定/投稿/添付メディア(Pixelfed)の最大バイト数」を追加。インスタンス情報キャッシュのリファクタ。
This commit is contained in:
parent
0313b5d264
commit
de8a4b7575
|
@ -15,6 +15,7 @@
|
||||||
<w>basi</w>
|
<w>basi</w>
|
||||||
<w>blockee</w>
|
<w>blockee</w>
|
||||||
<w>blurhash</w>
|
<w>blurhash</w>
|
||||||
|
<w>bpixelfed</w>
|
||||||
<w>buggie</w>
|
<w>buggie</w>
|
||||||
<w>bumptech</w>
|
<w>bumptech</w>
|
||||||
<w>codepoint</w>
|
<w>codepoint</w>
|
||||||
|
|
|
@ -239,6 +239,7 @@ class ActAppSettingChild : AppCompatActivity()
|
||||||
private var etCardDescriptionLength : EditText? = null
|
private var etCardDescriptionLength : EditText? = null
|
||||||
private var etMediaSizeMax : EditText? = null
|
private var etMediaSizeMax : EditText? = null
|
||||||
private var etMovieSizeMax : EditText? = null
|
private var etMovieSizeMax : EditText? = null
|
||||||
|
private var etMediaSizeMaxPixelfed : EditText? = null
|
||||||
private var etRoundRatio : EditText? = null
|
private var etRoundRatio : EditText? = null
|
||||||
private var etBoostAlpha : EditText? = null
|
private var etBoostAlpha : EditText? = null
|
||||||
private var etMediaReadTimeout : EditText? = null
|
private var etMediaReadTimeout : EditText? = null
|
||||||
|
@ -565,6 +566,9 @@ class ActAppSettingChild : AppCompatActivity()
|
||||||
etMovieSizeMax = findViewById(R.id.etMovieSizeMax)
|
etMovieSizeMax = findViewById(R.id.etMovieSizeMax)
|
||||||
etMovieSizeMax?.addTextChangedListener(this)
|
etMovieSizeMax?.addTextChangedListener(this)
|
||||||
|
|
||||||
|
etMediaSizeMaxPixelfed= findViewById(R.id.etMediaSizeMaxPixelfed)
|
||||||
|
etMediaSizeMaxPixelfed?.addTextChangedListener(this)
|
||||||
|
|
||||||
etRoundRatio = findViewById(R.id.etRoundRatio)
|
etRoundRatio = findViewById(R.id.etRoundRatio)
|
||||||
etRoundRatio?.addTextChangedListener(this)
|
etRoundRatio?.addTextChangedListener(this)
|
||||||
|
|
||||||
|
@ -732,6 +736,7 @@ class ActAppSettingChild : AppCompatActivity()
|
||||||
|
|
||||||
etMediaSizeMax?.setText(Pref.spMediaSizeMax(pref))
|
etMediaSizeMax?.setText(Pref.spMediaSizeMax(pref))
|
||||||
etMovieSizeMax?.setText(Pref.spMovieSizeMax(pref))
|
etMovieSizeMax?.setText(Pref.spMovieSizeMax(pref))
|
||||||
|
etMediaSizeMaxPixelfed?.setText(Pref.spMediaSizeMaxPixelfed(pref))
|
||||||
etRoundRatio?.setText(Pref.spRoundRatio(pref))
|
etRoundRatio?.setText(Pref.spRoundRatio(pref))
|
||||||
etBoostAlpha?.setText(Pref.spBoostAlpha(pref))
|
etBoostAlpha?.setText(Pref.spBoostAlpha(pref))
|
||||||
|
|
||||||
|
@ -828,6 +833,7 @@ class ActAppSettingChild : AppCompatActivity()
|
||||||
putText(Pref.spPullNotificationCheckInterval, etPullNotificationCheckInterval)
|
putText(Pref.spPullNotificationCheckInterval, etPullNotificationCheckInterval)
|
||||||
putText(Pref.spMediaSizeMax, etMediaSizeMax)
|
putText(Pref.spMediaSizeMax, etMediaSizeMax)
|
||||||
putText(Pref.spMovieSizeMax, etMovieSizeMax)
|
putText(Pref.spMovieSizeMax, etMovieSizeMax)
|
||||||
|
putText(Pref.spMediaSizeMaxPixelfed, etMediaSizeMaxPixelfed)
|
||||||
putText(Pref.spRoundRatio, etRoundRatio)
|
putText(Pref.spRoundRatio, etRoundRatio)
|
||||||
putText(Pref.spBoostAlpha, etBoostAlpha)
|
putText(Pref.spBoostAlpha, etBoostAlpha)
|
||||||
putText(Pref.spMediaReadTimeout, etMediaReadTimeout)
|
putText(Pref.spMediaReadTimeout, etMediaReadTimeout)
|
||||||
|
|
|
@ -972,9 +972,7 @@ class ActPost : AppCompatActivity(),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
visibility = visibility
|
visibility = visibility ?: account?.visibility ?: TootVisibility.Public
|
||||||
?: account?.visibility
|
|
||||||
?: TootVisibility.Public
|
|
||||||
// 2017/9/13 VISIBILITY_WEB_SETTING から VISIBILITY_PUBLICに変更した
|
// 2017/9/13 VISIBILITY_WEB_SETTING から VISIBILITY_PUBLICに変更した
|
||||||
// VISIBILITY_WEB_SETTING だと 1.5未満のタンスでトラブルになるので…
|
// VISIBILITY_WEB_SETTING だと 1.5未満のタンスでトラブルになるので…
|
||||||
|
|
||||||
|
@ -1271,42 +1269,30 @@ class ActPost : AppCompatActivity(),
|
||||||
|
|
||||||
else -> {
|
else -> {
|
||||||
// インスタンス情報を確認する
|
// インスタンス情報を確認する
|
||||||
val info = account.instance
|
val info = TootInstance.getCached(account.host)
|
||||||
if(info == null || System.currentTimeMillis() - info.time_parse >= 300000L) {
|
if(info == null || info.isExpire ) {
|
||||||
// 情報がないか古いなら再取得
|
// 情報がないか古いなら再取得
|
||||||
|
|
||||||
// 同時に実行するタスクは1つまで
|
// 同時に実行するタスクは1つまで
|
||||||
var lastTask = lastInstanceTask
|
if(lastInstanceTask?.isActive != true) {
|
||||||
if(lastTask?.isActive != true) {
|
lastInstanceTask = TootTaskRunner(this, TootTaskRunner.PROGRESS_NONE)
|
||||||
lastTask = TootTaskRunner(this, TootTaskRunner.PROGRESS_NONE)
|
.run(account, object : TootTask {
|
||||||
lastInstanceTask = lastTask
|
var newInfo : TootInstance? = null
|
||||||
lastTask.run(account, object : TootTask {
|
|
||||||
var newInfo : TootInstance? = null
|
override fun background(client : TootApiClient) : TootApiResult? {
|
||||||
|
val (result, ti) = TootInstance.get(client, account)
|
||||||
override fun background(client : TootApiClient) : TootApiResult? {
|
newInfo = ti
|
||||||
val result = if(account.isMisskey) {
|
return result
|
||||||
client.request(
|
|
||||||
"/api/meta",
|
|
||||||
account.putMisskeyApiToken().toPostRequestBuilder()
|
|
||||||
)
|
|
||||||
} else {
|
|
||||||
client.request("/api/v1/instance")
|
|
||||||
}
|
}
|
||||||
newInfo =
|
|
||||||
TootParser(this@ActPost, account).instance(result?.jsonObject)
|
override fun handleResult(result : TootApiResult?) {
|
||||||
return result
|
if(isFinishing || isDestroyed) return
|
||||||
}
|
if(newInfo != null) updateTextCount()
|
||||||
|
|
||||||
override fun handleResult(result : TootApiResult?) {
|
|
||||||
if(isFinishing || isDestroyed) return
|
|
||||||
if(newInfo != null) {
|
|
||||||
account.instance = newInfo
|
|
||||||
updateTextCount()
|
|
||||||
}
|
}
|
||||||
}
|
})
|
||||||
})
|
|
||||||
// fall thru
|
// fall thru
|
||||||
}
|
}
|
||||||
|
// fall thru
|
||||||
}
|
}
|
||||||
|
|
||||||
val max = info?.max_toot_chars
|
val max = info?.max_toot_chars
|
||||||
|
@ -2094,9 +2080,17 @@ class ActPost : AppCompatActivity(),
|
||||||
|
|
||||||
client.account = account
|
client.account = account
|
||||||
|
|
||||||
|
val (tiResult, ti) = TootInstance.get(client, account)
|
||||||
|
if(ti == null) return tiResult
|
||||||
|
|
||||||
val opener = createOpener(uri, mimeType)
|
val opener = createOpener(uri, mimeType)
|
||||||
|
|
||||||
val media_size_max = when {
|
val media_size_max = when {
|
||||||
|
|
||||||
|
ti.instanceType == TootInstance.InstanceType.Pixelfed -> {
|
||||||
|
1000000 * max(1, Pref.spMediaSizeMaxPixelfed.toInt(pref))
|
||||||
|
}
|
||||||
|
|
||||||
mimeType.startsWith("video") || mimeType.startsWith("audio") -> {
|
mimeType.startsWith("video") || mimeType.startsWith("audio") -> {
|
||||||
1000000 * max(1, Pref.spMovieSizeMax.toInt(pref))
|
1000000 * max(1, Pref.spMovieSizeMax.toInt(pref))
|
||||||
}
|
}
|
||||||
|
|
|
@ -122,7 +122,6 @@ class Column(
|
||||||
internal const val PATH_STATUSES = "/api/v1/statuses/%s" // 1:status_id
|
internal const val PATH_STATUSES = "/api/v1/statuses/%s" // 1:status_id
|
||||||
internal const val PATH_STATUSES_CONTEXT = "/api/v1/statuses/%s/context" // 1:status_id
|
internal const val PATH_STATUSES_CONTEXT = "/api/v1/statuses/%s/context" // 1:status_id
|
||||||
// search args 1: query(urlencoded) , also, append "&resolve=1" if resolve non-local accounts
|
// search args 1: query(urlencoded) , also, append "&resolve=1" if resolve non-local accounts
|
||||||
// internal const val PATH_INSTANCE = "/api/v1/instance"
|
|
||||||
internal const val PATH_LIST_INFO = "/api/v1/lists/%s"
|
internal const val PATH_LIST_INFO = "/api/v1/lists/%s"
|
||||||
|
|
||||||
const val PATH_FILTERS = "/api/v1/filters"
|
const val PATH_FILTERS = "/api/v1/filters"
|
||||||
|
|
|
@ -18,8 +18,6 @@ class ColumnTask_Loading(
|
||||||
internal val log = LogCategory("CT_Loading")
|
internal val log = LogCategory("CT_Loading")
|
||||||
}
|
}
|
||||||
|
|
||||||
internal var instance_tmp : TootInstance? = null
|
|
||||||
|
|
||||||
internal var list_pinned : ArrayList<TimelineItem>? = null
|
internal var list_pinned : ArrayList<TimelineItem>? = null
|
||||||
|
|
||||||
override fun doInBackground(vararg unused : Void) : TootApiResult? {
|
override fun doInBackground(vararg unused : Void) : TootApiResult? {
|
||||||
|
@ -88,8 +86,8 @@ class ColumnTask_Loading(
|
||||||
val list_new = column.duplicate_map.filterDuplicate(list_pinned)
|
val list_new = column.duplicate_map.filterDuplicate(list_pinned)
|
||||||
column.list_data.addAll(list_new)
|
column.list_data.addAll(list_new)
|
||||||
}
|
}
|
||||||
|
|
||||||
val list_new = when(column.type){
|
val list_new = when(column.type) {
|
||||||
|
|
||||||
// 検索カラムはIDによる重複排除が不可能
|
// 検索カラムはIDによる重複排除が不可能
|
||||||
ColumnType.SEARCH -> list_tmp
|
ColumnType.SEARCH -> list_tmp
|
||||||
|
@ -97,7 +95,7 @@ class ColumnTask_Loading(
|
||||||
// 他のカラムは重複排除してから追加
|
// 他のカラムは重複排除してから追加
|
||||||
else -> column.duplicate_map.filterDuplicate(list_tmp)
|
else -> column.duplicate_map.filterDuplicate(list_tmp)
|
||||||
}
|
}
|
||||||
|
|
||||||
column.list_data.addAll(list_new)
|
column.list_data.addAll(list_new)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -114,23 +112,7 @@ class ColumnTask_Loading(
|
||||||
/////////////////////////////////////////////////////////////////
|
/////////////////////////////////////////////////////////////////
|
||||||
// functions that called from ColumnTask.loading lambda.
|
// functions that called from ColumnTask.loading lambda.
|
||||||
|
|
||||||
internal fun getInstanceInformation(
|
|
||||||
client : TootApiClient,
|
|
||||||
instance_name : String?
|
|
||||||
) : TootApiResult? {
|
|
||||||
when {
|
|
||||||
// 「インスタンス情報」カラムをNAアカウントで開く場合
|
|
||||||
instance_name != null -> client.instance = instance_name
|
|
||||||
|
|
||||||
// カラムに紐付けられたアカウントのタンスのインスタンス情報を取得する
|
|
||||||
else -> {
|
|
||||||
}
|
|
||||||
}
|
|
||||||
val (result, ti) = client.parseInstanceInformation(client.getInstanceInformation())
|
|
||||||
instance_tmp = ti
|
|
||||||
return result
|
|
||||||
}
|
|
||||||
|
|
||||||
internal fun getStatusesPinned(client : TootApiClient, path_base : String) {
|
internal fun getStatusesPinned(client : TootApiClient, path_base : String) {
|
||||||
val result = client.request(path_base)
|
val result = client.request(path_base)
|
||||||
val jsonArray = result?.jsonArray
|
val jsonArray = result?.jsonArray
|
||||||
|
@ -700,14 +682,8 @@ class ColumnTask_Loading(
|
||||||
) : TootApiResult? {
|
) : TootApiResult? {
|
||||||
// (Mastodonのみ対応)
|
// (Mastodonのみ対応)
|
||||||
|
|
||||||
var instance = access_info.instance
|
val (instanceResult, instance) = TootInstance.get(client, access_info)
|
||||||
if(instance == null) {
|
if(instance == null) return instanceResult
|
||||||
getInstanceInformation(client, null)
|
|
||||||
if(instance_tmp != null) {
|
|
||||||
instance = instance_tmp
|
|
||||||
access_info.instance = instance
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// ステータスIDに該当するトゥート
|
// ステータスIDに該当するトゥート
|
||||||
// タンスをまたいだりすると存在しないかもしれないが、エラーは出さない
|
// タンスをまたいだりすると存在しないかもしれないが、エラーは出さない
|
||||||
|
@ -722,7 +698,7 @@ class ColumnTask_Loading(
|
||||||
column.idRecent = null
|
column.idRecent = null
|
||||||
|
|
||||||
var bInstanceTooOld = false
|
var bInstanceTooOld = false
|
||||||
if(instance?.versionGE(TootInstance.VERSION_2_6_0) == true) {
|
if(instance.versionGE(TootInstance.VERSION_2_6_0)) {
|
||||||
// 指定より新しいトゥート
|
// 指定より新しいトゥート
|
||||||
result = getStatusList(client, url, aroundMin = true)
|
result = getStatusList(client, url, aroundMin = true)
|
||||||
if(result == null || result.error != null) return result
|
if(result == null || result.error != null) return result
|
||||||
|
@ -750,14 +726,8 @@ class ColumnTask_Loading(
|
||||||
internal fun getAccountAroundStatuses(client : TootApiClient) : TootApiResult? {
|
internal fun getAccountAroundStatuses(client : TootApiClient) : TootApiResult? {
|
||||||
// (Mastodonのみ対応)
|
// (Mastodonのみ対応)
|
||||||
|
|
||||||
var instance = access_info.instance
|
val (instanceResult, instance) = TootInstance.get(client, access_info)
|
||||||
if(instance == null) {
|
if(instance == null) return instanceResult
|
||||||
getInstanceInformation(client, null)
|
|
||||||
if(instance_tmp != null) {
|
|
||||||
instance = instance_tmp
|
|
||||||
access_info.instance = instance
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// ステータスIDに該当するトゥート
|
// ステータスIDに該当するトゥート
|
||||||
// タンスをまたいだりすると存在しないかもしれない
|
// タンスをまたいだりすると存在しないかもしれない
|
||||||
|
@ -774,7 +744,7 @@ class ColumnTask_Loading(
|
||||||
column.idRecent = null
|
column.idRecent = null
|
||||||
|
|
||||||
var bInstanceTooOld = false
|
var bInstanceTooOld = false
|
||||||
if(instance?.versionGE(TootInstance.VERSION_2_6_0) == true) {
|
if(instance.versionGE(TootInstance.VERSION_2_6_0)) {
|
||||||
// 指定より新しいトゥート
|
// 指定より新しいトゥート
|
||||||
result = getStatusList(client, path, aroundMin = true)
|
result = getStatusList(client, path, aroundMin = true)
|
||||||
if(result == null || result.error != null) return result
|
if(result == null || result.error != null) return result
|
||||||
|
@ -1007,31 +977,25 @@ class ColumnTask_Loading(
|
||||||
return TootApiResult(context.getString(R.string.search_is_not_available_on_pseudo_account))
|
return TootApiResult(context.getString(R.string.search_is_not_available_on_pseudo_account))
|
||||||
}
|
}
|
||||||
|
|
||||||
var instance = access_info.instance
|
val(instanceResult,instance) = TootInstance.get(client,access_info)
|
||||||
if(instance == null) {
|
if( instance==null) return instanceResult
|
||||||
getInstanceInformation(client, null)
|
|
||||||
if(instance_tmp != null) {
|
|
||||||
instance = instance_tmp
|
|
||||||
access_info.instance = instance
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
var query="q=${column.search_query.encodePercent()}"
|
var query = "q=${column.search_query.encodePercent()}"
|
||||||
if(column.search_resolve) query += "&resolve=1"
|
if(column.search_resolve) query += "&resolve=1"
|
||||||
|
|
||||||
val(apiResult,searchResult)= client.requestMastodonSearch(parser,query)
|
val (apiResult, searchResult) = client.requestMastodonSearch(parser, query)
|
||||||
if( searchResult != null){
|
if(searchResult != null) {
|
||||||
list_tmp = java.util.ArrayList()
|
list_tmp = java.util.ArrayList()
|
||||||
addAll(list_tmp, searchResult.hashtags)
|
addAll(list_tmp, searchResult.hashtags)
|
||||||
if(searchResult.searchApiVersion>=2 && searchResult.hashtags.isNotEmpty()) {
|
if(searchResult.searchApiVersion >= 2 && searchResult.hashtags.isNotEmpty()) {
|
||||||
addOne(list_tmp, TootSearchGap(TootSearchGap.SearchType.Hashtag))
|
addOne(list_tmp, TootSearchGap(TootSearchGap.SearchType.Hashtag))
|
||||||
}
|
}
|
||||||
addAll(list_tmp, searchResult.accounts)
|
addAll(list_tmp, searchResult.accounts)
|
||||||
if(searchResult.searchApiVersion>=2 && searchResult.accounts.isNotEmpty()) {
|
if(searchResult.searchApiVersion >= 2 && searchResult.accounts.isNotEmpty()) {
|
||||||
addOne(list_tmp, TootSearchGap(TootSearchGap.SearchType.Account))
|
addOne(list_tmp, TootSearchGap(TootSearchGap.SearchType.Account))
|
||||||
}
|
}
|
||||||
addAll(list_tmp, searchResult.statuses)
|
addAll(list_tmp, searchResult.statuses)
|
||||||
if( searchResult.searchApiVersion>=2 && searchResult.statuses.isNotEmpty()) {
|
if(searchResult.searchApiVersion >= 2 && searchResult.statuses.isNotEmpty()) {
|
||||||
addOne(list_tmp, TootSearchGap(TootSearchGap.SearchType.Status))
|
addOne(list_tmp, TootSearchGap(TootSearchGap.SearchType.Status))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -57,28 +57,21 @@ enum class ColumnType(
|
||||||
|
|
||||||
ProfileStatusMastodon(
|
ProfileStatusMastodon(
|
||||||
loading = { client ->
|
loading = { client ->
|
||||||
var instance = access_info.instance
|
val(instanceResult,instance) = TootInstance.get(client,access_info)
|
||||||
|
if(instance==null){
|
||||||
// まだ取得してない
|
instanceResult
|
||||||
// 疑似アカウントの場合は過去のデータが別タンスかもしれない?
|
}else {
|
||||||
if(instance == null || access_info.isPseudo) {
|
val path = column.makeProfileStatusesUrl(column.profile_id)
|
||||||
getInstanceInformation(client, null)
|
|
||||||
if(instance_tmp != null) {
|
if(instance.versionGE(TootInstance.VERSION_1_6)
|
||||||
instance = instance_tmp
|
// 将来的に正しく判定できる見込みがないので、Pleroma条件でのフィルタは行わない
|
||||||
access_info.instance = instance
|
// && instance.instanceType != TootInstance.InstanceType.Pleroma
|
||||||
|
) {
|
||||||
|
getStatusesPinned(client, "$path&pinned=true")
|
||||||
}
|
}
|
||||||
|
|
||||||
|
getStatusList(client, path)
|
||||||
}
|
}
|
||||||
|
|
||||||
val path = column.makeProfileStatusesUrl(column.profile_id)
|
|
||||||
|
|
||||||
if(instance?.versionGE(TootInstance.VERSION_1_6) == true
|
|
||||||
// 将来的に正しく判定できる見込みがないので、Pleroma条件でのフィルタは行わない
|
|
||||||
// && instance.instanceType != TootInstance.InstanceType.Pleroma
|
|
||||||
) {
|
|
||||||
getStatusesPinned(client, "$path&pinned=true")
|
|
||||||
}
|
|
||||||
|
|
||||||
getStatusList(client, path)
|
|
||||||
},
|
},
|
||||||
|
|
||||||
refresh = { client ->
|
refresh = { client ->
|
||||||
|
@ -1102,12 +1095,26 @@ enum class ColumnType(
|
||||||
headerType = HeaderType.Instance,
|
headerType = HeaderType.Instance,
|
||||||
|
|
||||||
loading = { client ->
|
loading = { client ->
|
||||||
val result = getInstanceInformation(client, column.instance_uri)
|
val(instanceResult,instance) = TootInstance.get(client,access_info,column.instance_uri)
|
||||||
if(instance_tmp != null) {
|
if(instance!=null) {
|
||||||
column.instance_information = instance_tmp
|
column.instance_information = instance
|
||||||
column.handshake = result?.response?.handshake
|
column.handshake = instanceResult?.response?.handshake
|
||||||
}
|
}
|
||||||
result
|
instanceResult
|
||||||
|
//
|
||||||
|
// // 「インスタンス情報」カラムをNAアカウントで開く場合
|
||||||
|
// instance_name != null -> client.instance = instance_name
|
||||||
|
//
|
||||||
|
// val (result, ti) = client.parseInstanceInformation(client.getInstanceInformation())
|
||||||
|
// instance_tmp = ti
|
||||||
|
// return result
|
||||||
|
// }
|
||||||
|
//
|
||||||
|
// val result = getInstanceInformation(client, column.instance_uri)
|
||||||
|
// if(instance_tmp != null) {
|
||||||
|
//
|
||||||
|
// }
|
||||||
|
// result
|
||||||
}
|
}
|
||||||
),
|
),
|
||||||
|
|
||||||
|
|
|
@ -519,6 +519,7 @@ object Pref {
|
||||||
val spStripIconSize = StringPref("StripIconSize", "30")
|
val spStripIconSize = StringPref("StripIconSize", "30")
|
||||||
val spMediaSizeMax = StringPref("max_media_size", "8")
|
val spMediaSizeMax = StringPref("max_media_size", "8")
|
||||||
val spMovieSizeMax = StringPref("max_movie_size", "40")
|
val spMovieSizeMax = StringPref("max_movie_size", "40")
|
||||||
|
val spMediaSizeMaxPixelfed = StringPref("MediaSizeMaxPixelfed", "15")
|
||||||
val spTimelineFont = StringPref("timeline_font", "", skipImport = true)
|
val spTimelineFont = StringPref("timeline_font", "", skipImport = true)
|
||||||
val spTimelineFontBold = StringPref("timeline_font_bold", "", skipImport = true)
|
val spTimelineFontBold = StringPref("timeline_font_bold", "", skipImport = true)
|
||||||
val spMspUserToken = StringPref("mastodon_search_portal_user_token", "")
|
val spMspUserToken = StringPref("mastodon_search_portal_user_token", "")
|
||||||
|
|
|
@ -1,34 +1,97 @@
|
||||||
package jp.juggler.subwaytooter.api.entity
|
package jp.juggler.subwaytooter.api.entity
|
||||||
|
|
||||||
|
import android.os.SystemClock
|
||||||
|
import jp.juggler.subwaytooter.api.TootApiClient
|
||||||
|
import jp.juggler.subwaytooter.api.TootApiResult
|
||||||
import jp.juggler.subwaytooter.api.TootParser
|
import jp.juggler.subwaytooter.api.TootParser
|
||||||
|
import jp.juggler.subwaytooter.table.SavedAccount
|
||||||
import jp.juggler.subwaytooter.util.*
|
import jp.juggler.subwaytooter.util.*
|
||||||
import jp.juggler.util.parseInt
|
import jp.juggler.util.*
|
||||||
import jp.juggler.util.parseLong
|
|
||||||
import jp.juggler.util.parseString
|
|
||||||
import jp.juggler.util.toStringArrayList
|
|
||||||
import org.json.JSONObject
|
import org.json.JSONObject
|
||||||
|
import java.util.*
|
||||||
import java.util.regex.Pattern
|
import java.util.regex.Pattern
|
||||||
|
import kotlin.collections.ArrayList
|
||||||
|
import kotlin.collections.HashMap
|
||||||
|
|
||||||
class TootInstance(parser : TootParser, src : JSONObject) {
|
class TootInstance(parser : TootParser, src : JSONObject) {
|
||||||
|
|
||||||
companion object {
|
companion object {
|
||||||
private val rePleroma = Pattern.compile("\\bpleroma\\b", Pattern.CASE_INSENSITIVE)
|
private val rePleroma = Pattern.compile("\\bpleroma\\b", Pattern.CASE_INSENSITIVE)
|
||||||
|
private val rePixelfed = Pattern.compile("\\bpixelfed\\b", Pattern.CASE_INSENSITIVE)
|
||||||
|
|
||||||
val VERSION_1_6 = VersionString("1.6")
|
val VERSION_1_6 = VersionString("1.6")
|
||||||
val VERSION_2_4_0_rc1 = VersionString("2.4.0rc1")
|
val VERSION_2_4_0_rc1 = VersionString("2.4.0rc1")
|
||||||
val VERSION_2_4_0_rc2 = VersionString("2.4.0rc2")
|
val VERSION_2_4_0_rc2 = VersionString("2.4.0rc2")
|
||||||
// val VERSION_2_4_0 = VersionString("2.4.0")
|
// val VERSION_2_4_0 = VersionString("2.4.0")
|
||||||
// val VERSION_2_4_1_rc1 = VersionString("2.4.1rc1")
|
// val VERSION_2_4_1_rc1 = VersionString("2.4.1rc1")
|
||||||
val VERSION_2_4_1 = VersionString("2.4.1")
|
val VERSION_2_4_1 = VersionString("2.4.1")
|
||||||
val VERSION_2_6_0 = VersionString("2.6.0")
|
val VERSION_2_6_0 = VersionString("2.6.0")
|
||||||
val VERSION_2_7_0_rc1 = VersionString("2.7.0rc1")
|
val VERSION_2_7_0_rc1 = VersionString("2.7.0rc1")
|
||||||
val VERSION_3_0_0_rc1 = VersionString("3.0.0rc1")
|
val VERSION_3_0_0_rc1 = VersionString("3.0.0rc1")
|
||||||
|
|
||||||
val MISSKEY_VERSION_11 = VersionString("11.0")
|
val MISSKEY_VERSION_11 = VersionString("11.0")
|
||||||
|
|
||||||
|
private const val EXPIRE = 600000L
|
||||||
|
|
||||||
|
private val cache = HashMap<String, TootInstance>()
|
||||||
|
|
||||||
|
// get from cache
|
||||||
|
// no request, no expiration check
|
||||||
|
fun getCached(host : String) : TootInstance? {
|
||||||
|
synchronized(cache) {
|
||||||
|
return cache[host.toLowerCase(Locale.JAPAN)]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fun get(
|
||||||
|
client : TootApiClient,
|
||||||
|
account : SavedAccount,
|
||||||
|
host : String? = null
|
||||||
|
) : Pair<TootApiResult?, TootInstance?> {
|
||||||
|
val tmpInstance = client.instance
|
||||||
|
val tmpAccount = client.account
|
||||||
|
try {
|
||||||
|
synchronized(cache) {
|
||||||
|
// re-use cached item.
|
||||||
|
val now = SystemClock.elapsedRealtime()
|
||||||
|
val item = cache[account.host.toLowerCase(Locale.JAPAN)]
|
||||||
|
if(item != null && now - item.time_parse <= EXPIRE)
|
||||||
|
return Pair(TootApiResult(), item)
|
||||||
|
|
||||||
|
// get new information
|
||||||
|
client.account = account
|
||||||
|
if(host != null) client.instance = host
|
||||||
|
val result = if(account.isMisskey) {
|
||||||
|
val params = JSONObject().apply {
|
||||||
|
put("dummy", 1)
|
||||||
|
}
|
||||||
|
client.request("/api/meta", params.toPostRequestBuilder())
|
||||||
|
} else {
|
||||||
|
client.request("/api/v1/instance")
|
||||||
|
}
|
||||||
|
|
||||||
|
val data = parseItem(
|
||||||
|
::TootInstance,
|
||||||
|
TootParser(client.context, account),
|
||||||
|
result?.jsonObject
|
||||||
|
)
|
||||||
|
if(data != null) {
|
||||||
|
cache[account.host.toLowerCase(Locale.JAPAN)] = data
|
||||||
|
}
|
||||||
|
return Pair(result, data)
|
||||||
|
}
|
||||||
|
} finally {
|
||||||
|
client.account = tmpAccount
|
||||||
|
client.instance = tmpInstance // must be last.
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// いつ取得したか(内部利用)
|
// いつ取得したか(内部利用)
|
||||||
var time_parse : Long = System.currentTimeMillis()
|
private var time_parse : Long = SystemClock.elapsedRealtime()
|
||||||
|
|
||||||
|
val isExpire : Boolean
|
||||||
|
get() = SystemClock.elapsedRealtime() - time_parse >= EXPIRE
|
||||||
|
|
||||||
// URI of the current instance
|
// URI of the current instance
|
||||||
val uri : String?
|
val uri : String?
|
||||||
|
@ -64,9 +127,11 @@ class TootInstance(parser : TootParser, src : JSONObject) {
|
||||||
|
|
||||||
// インスタンスの種別
|
// インスタンスの種別
|
||||||
enum class InstanceType {
|
enum class InstanceType {
|
||||||
|
|
||||||
Mastodon,
|
Mastodon,
|
||||||
Pleroma,
|
Misskey,
|
||||||
Misskey
|
Pixelfed,
|
||||||
|
Pleroma
|
||||||
}
|
}
|
||||||
|
|
||||||
val instanceType : InstanceType
|
val instanceType : InstanceType
|
||||||
|
@ -74,15 +139,15 @@ class TootInstance(parser : TootParser, src : JSONObject) {
|
||||||
// XXX: urls をパースしてない。使ってないから…
|
// XXX: urls をパースしてない。使ってないから…
|
||||||
|
|
||||||
init {
|
init {
|
||||||
if(parser.serviceType == ServiceType.MISSKEY){
|
if(parser.serviceType == ServiceType.MISSKEY) {
|
||||||
|
|
||||||
this.uri = parser.accessHost
|
this.uri = parser.accessHost
|
||||||
this.title = parser.accessHost
|
this.title = parser.accessHost
|
||||||
this.description = "(Misskey instance)"
|
this.description = "(Misskey instance)"
|
||||||
val sv = src.optJSONObject("maintainer")?.parseString("url")
|
val sv = src.optJSONObject("maintainer")?.parseString("url")
|
||||||
this.email = when{
|
this.email = when {
|
||||||
sv?.startsWith("mailto:") ==true-> sv.substring(7)
|
sv?.startsWith("mailto:") == true -> sv.substring(7)
|
||||||
else-> sv
|
else -> sv
|
||||||
}
|
}
|
||||||
|
|
||||||
this.version = src.parseString("version")
|
this.version = src.parseString("version")
|
||||||
|
@ -94,15 +159,15 @@ class TootInstance(parser : TootParser, src : JSONObject) {
|
||||||
this.languages = src.optJSONArray("langs")?.toStringArrayList() ?: ArrayList()
|
this.languages = src.optJSONArray("langs")?.toStringArrayList() ?: ArrayList()
|
||||||
this.contact_account = null
|
this.contact_account = null
|
||||||
|
|
||||||
}else {
|
} else {
|
||||||
this.uri = src.parseString("uri")
|
this.uri = src.parseString("uri")
|
||||||
this.title = src.parseString("title")
|
this.title = src.parseString("title")
|
||||||
this.description = src.parseString("description")
|
this.description = src.parseString("description")
|
||||||
|
|
||||||
val sv = src.parseString("email")
|
val sv = src.parseString("email")
|
||||||
this.email = when{
|
this.email = when {
|
||||||
sv?.startsWith("mailto:") ==true-> sv.substring(7)
|
sv?.startsWith("mailto:") == true -> sv.substring(7)
|
||||||
else-> sv
|
else -> sv
|
||||||
}
|
}
|
||||||
|
|
||||||
this.version = src.parseString("version")
|
this.version = src.parseString("version")
|
||||||
|
@ -114,6 +179,7 @@ class TootInstance(parser : TootParser, src : JSONObject) {
|
||||||
|
|
||||||
this.instanceType = when {
|
this.instanceType = when {
|
||||||
rePleroma.matcher(version ?: "").find() -> InstanceType.Pleroma
|
rePleroma.matcher(version ?: "").find() -> InstanceType.Pleroma
|
||||||
|
rePixelfed.matcher(version ?: "").find() -> InstanceType.Pixelfed
|
||||||
else -> InstanceType.Mastodon
|
else -> InstanceType.Mastodon
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -145,11 +211,71 @@ class TootInstance(parser : TootParser, src : JSONObject) {
|
||||||
val i = VersionString.compare(decoded_version, check)
|
val i = VersionString.compare(decoded_version, check)
|
||||||
return i >= 0
|
return i >= 0
|
||||||
}
|
}
|
||||||
|
|
||||||
val misskeyVersion :Int
|
val misskeyVersion : Int
|
||||||
get()=when{
|
get() = when {
|
||||||
instanceType != InstanceType.Misskey -> 0
|
instanceType != InstanceType.Misskey -> 0
|
||||||
versionGE(MISSKEY_VERSION_11) -> 11
|
versionGE(MISSKEY_VERSION_11) -> 11
|
||||||
else->10
|
else -> 10
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//
|
||||||
|
//import android.os.SystemClock
|
||||||
|
//import jp.juggler.subwaytooter.api.TootApiClient
|
||||||
|
//import jp.juggler.subwaytooter.api.TootApiResult
|
||||||
|
//import jp.juggler.subwaytooter.api.TootParser
|
||||||
|
//import jp.juggler.subwaytooter.api.entity.TootInstance
|
||||||
|
//import jp.juggler.subwaytooter.api.entity.parseItem
|
||||||
|
//import jp.juggler.subwaytooter.table.SavedAccount
|
||||||
|
//import jp.juggler.util.toPostRequestBuilder
|
||||||
|
//import org.json.JSONObject
|
||||||
|
//import java.util.*
|
||||||
|
//import kotlin.collections.HashMap
|
||||||
|
//
|
||||||
|
//object InstanceInformationCache {
|
||||||
|
//
|
||||||
|
//
|
||||||
|
// // var instance =
|
||||||
|
// // if(instance == null) {
|
||||||
|
// // val r2 = getInstanceInformation(client)
|
||||||
|
// // instance = instance_tmp ?: return r2
|
||||||
|
// // account.instance = instance
|
||||||
|
// // }
|
||||||
|
// // var instance_tmp : TootInstance? = null
|
||||||
|
// // fun getInstanceInformation(client : TootApiClient) : TootApiResult? {
|
||||||
|
// //
|
||||||
|
// // instance_tmp =
|
||||||
|
// // return result
|
||||||
|
// // }
|
||||||
|
// //
|
||||||
|
// // client.instance = host
|
||||||
|
// // val result = if(isMisskey) {
|
||||||
|
// // client.getInstanceInformation()
|
||||||
|
// // client.request(
|
||||||
|
// // "/api/meta",
|
||||||
|
// // account.putMisskeyApiToken().toPostRequestBuilder()
|
||||||
|
// // )
|
||||||
|
// // } else {
|
||||||
|
// // client.request("/api/v1/instance")
|
||||||
|
// // }
|
||||||
|
// // newInfo =
|
||||||
|
// // TootParser(this@ActPost, account).instance(result?.jsonObject)
|
||||||
|
// // return Pair(null,null)
|
||||||
|
// // }
|
||||||
|
//
|
||||||
|
// //private val refInstance = AtomicReference<TootInstance>(null)
|
||||||
|
// //
|
||||||
|
// //// DBには保存しない
|
||||||
|
// //var instance : TootInstance?
|
||||||
|
// // get() {
|
||||||
|
// // val instance = refInstance.get()
|
||||||
|
// // return when {
|
||||||
|
// // instance == null -> null
|
||||||
|
// // System.currentTimeMillis() - instance.time_parse > INSTANCE_INFORMATION_EXPIRE -> null
|
||||||
|
// // else -> instance
|
||||||
|
// // }
|
||||||
|
// // }
|
||||||
|
// // set(instance) = refInstance.set(instance)
|
||||||
|
//
|
||||||
|
//}
|
|
@ -66,19 +66,7 @@ class SavedAccount(
|
||||||
|
|
||||||
var max_toot_chars = 0
|
var max_toot_chars = 0
|
||||||
|
|
||||||
private val refInstance = AtomicReference<TootInstance>(null)
|
|
||||||
|
|
||||||
// DBには保存しない
|
|
||||||
var instance : TootInstance?
|
|
||||||
get() {
|
|
||||||
val instance = refInstance.get()
|
|
||||||
return when {
|
|
||||||
instance == null -> null
|
|
||||||
System.currentTimeMillis() - instance.time_parse > INSTANCE_INFORMATION_EXPIRE -> null
|
|
||||||
else -> instance
|
|
||||||
}
|
|
||||||
}
|
|
||||||
set(instance) = refInstance.set(instance)
|
|
||||||
|
|
||||||
init {
|
init {
|
||||||
val pos = acct.indexOf('@')
|
val pos = acct.indexOf('@')
|
||||||
|
@ -431,7 +419,6 @@ class SavedAccount(
|
||||||
/////////////////////////////////
|
/////////////////////////////////
|
||||||
// login information
|
// login information
|
||||||
const val INVALID_DB_ID = - 1L
|
const val INVALID_DB_ID = - 1L
|
||||||
private const val INSTANCE_INFORMATION_EXPIRE = 60000L * 5
|
|
||||||
|
|
||||||
// アプリデータのインポート時に呼ばれる
|
// アプリデータのインポート時に呼ばれる
|
||||||
fun onDBDelete(db : SQLiteDatabase) {
|
fun onDBDelete(db : SQLiteDatabase) {
|
||||||
|
|
|
@ -250,7 +250,6 @@ class PostHelper(
|
||||||
|
|
||||||
var status : TootStatus? = null
|
var status : TootStatus? = null
|
||||||
|
|
||||||
var instance_tmp : TootInstance? = null
|
|
||||||
|
|
||||||
var credential_tmp : TootAccount? = null
|
var credential_tmp : TootAccount? = null
|
||||||
|
|
||||||
|
@ -258,19 +257,6 @@ class PostHelper(
|
||||||
|
|
||||||
var scheduledStatusSucceeded = false
|
var scheduledStatusSucceeded = false
|
||||||
|
|
||||||
fun getInstanceInformation(client : TootApiClient) : TootApiResult? {
|
|
||||||
val result = if(account.isMisskey) {
|
|
||||||
val params = JSONObject().apply {
|
|
||||||
put("dummy", 1)
|
|
||||||
}
|
|
||||||
client.request("/api/meta", params.toPostRequestBuilder())
|
|
||||||
} else {
|
|
||||||
client.request("/api/v1/instance")
|
|
||||||
}
|
|
||||||
instance_tmp = parseItem(::TootInstance, parser, result?.jsonObject)
|
|
||||||
return result
|
|
||||||
}
|
|
||||||
|
|
||||||
fun getCredential(client : TootApiClient) : TootApiResult? {
|
fun getCredential(client : TootApiClient) : TootApiResult? {
|
||||||
val result = client.request("/api/v1/accounts/verify_credentials")
|
val result = client.request("/api/v1/accounts/verify_credentials")
|
||||||
credential_tmp = parser.account(result?.jsonObject)
|
credential_tmp = parser.account(result?.jsonObject)
|
||||||
|
@ -311,12 +297,8 @@ class PostHelper(
|
||||||
|
|
||||||
var visibility_checked : TootVisibility? = visibility
|
var visibility_checked : TootVisibility? = visibility
|
||||||
|
|
||||||
var instance = account.instance
|
val(ri,instance) = TootInstance.get(client,account)
|
||||||
if(instance == null) {
|
if(instance==null) return ri
|
||||||
val r2 = getInstanceInformation(client)
|
|
||||||
instance = instance_tmp ?: return r2
|
|
||||||
account.instance = instance
|
|
||||||
}
|
|
||||||
|
|
||||||
if(visibility == TootVisibility.WebSetting) {
|
if(visibility == TootVisibility.WebSetting) {
|
||||||
visibility_checked =
|
visibility_checked =
|
||||||
|
|
|
@ -79,6 +79,25 @@
|
||||||
|
|
||||||
<View style="@style/setting_divider"/>
|
<View style="@style/setting_divider"/>
|
||||||
|
|
||||||
|
<TextView
|
||||||
|
style="@style/setting_row_label"
|
||||||
|
android:labelFor="@+id/etMediaSizeMaxPixelfed"
|
||||||
|
android:text="@string/media_attachment_max_byte_size_pixelfed"
|
||||||
|
/>
|
||||||
|
|
||||||
|
<LinearLayout style="@style/setting_row_form">
|
||||||
|
|
||||||
|
<EditText
|
||||||
|
android:id="@+id/etMediaSizeMaxPixelfed"
|
||||||
|
style="@style/setting_horizontal_stretch"
|
||||||
|
android:inputType="number"
|
||||||
|
android:gravity="center"
|
||||||
|
/>
|
||||||
|
|
||||||
|
</LinearLayout>
|
||||||
|
|
||||||
|
<View style="@style/setting_divider"/>
|
||||||
|
|
||||||
<TextView
|
<TextView
|
||||||
style="@style/setting_row_label"
|
style="@style/setting_row_label"
|
||||||
android:text="@string/refresh_after_toot"
|
android:text="@string/refresh_after_toot"
|
||||||
|
|
|
@ -414,6 +414,7 @@
|
||||||
<string name="media_attachment_empty">添付メディアがありません</string>
|
<string name="media_attachment_empty">添付メディアがありません</string>
|
||||||
<string name="media_attachment_max_byte_size">添付メディア(静止画)の最大バイト数(単位:MB。デフォルトは8)</string>
|
<string name="media_attachment_max_byte_size">添付メディア(静止画)の最大バイト数(単位:MB。デフォルトは8)</string>
|
||||||
<string name="media_attachment_max_byte_size_movie">添付メディア(動画)の最大バイト数(単位:MB。デフォルトは40)</string>
|
<string name="media_attachment_max_byte_size_movie">添付メディア(動画)の最大バイト数(単位:MB。デフォルトは40)</string>
|
||||||
|
<string name="media_attachment_max_byte_size_pixelfed">添付メディア(Pixelfed)の最大バイト数(単位:MB。デフォルトは15)</string>
|
||||||
<string name="media_attachment_still_uploading">添付メディアのアップロードが終わってません</string>
|
<string name="media_attachment_still_uploading">添付メディアのアップロードが終わってません</string>
|
||||||
<string name="media_attachment_type_error">添付メディアの種類\"%1$s\"はこのアプリでは開けません。下の「…」にある「ブラウザで開く」を試すことができます</string>
|
<string name="media_attachment_type_error">添付メディアの種類\"%1$s\"はこのアプリでは開けません。下の「…」にある「ブラウザで開く」を試すことができます</string>
|
||||||
<string name="media_description">(添付 %1$d) %2$s</string>
|
<string name="media_description">(添付 %1$d) %2$s</string>
|
||||||
|
|
|
@ -572,6 +572,9 @@
|
||||||
<string name="your_lists">Your lists</string>
|
<string name="your_lists">Your lists</string>
|
||||||
<string name="media_attachment_max_byte_size">Media attachment (image) bytes size limit (Unit:MB. The default is 8)</string>
|
<string name="media_attachment_max_byte_size">Media attachment (image) bytes size limit (Unit:MB. The default is 8)</string>
|
||||||
<string name="media_attachment_max_byte_size_movie">Media attachment (movie) bytes size limit (Unit:MB. The default is 40)</string>
|
<string name="media_attachment_max_byte_size_movie">Media attachment (movie) bytes size limit (Unit:MB. The default is 40)</string>
|
||||||
|
<string name="media_attachment_max_byte_size_pixelfed">Media attachment (Pixelfed) bytes size limit (Unit:MB. The default is 15)</string>
|
||||||
|
|
||||||
|
|
||||||
<string name="tootsearch">tootsearch (JP)</string>
|
<string name="tootsearch">tootsearch (JP)</string>
|
||||||
<string name="cant_handle_uri_of">Subway Tooter can\'t handle URI \"%1$s\". Please select other app.</string>
|
<string name="cant_handle_uri_of">Subway Tooter can\'t handle URI \"%1$s\". Please select other app.</string>
|
||||||
<string name="use_internal_media_viewer">Use built-in media viewer</string>
|
<string name="use_internal_media_viewer">Use built-in media viewer</string>
|
||||||
|
|
Loading…
Reference in New Issue