リアクションした投稿の一覧をめいすきーでも見れるようにした
This commit is contained in:
parent
a5d16a6934
commit
bc3f56c22d
|
@ -2682,7 +2682,7 @@ class ActPost : AsyncActivity(),
|
||||||
TootVisibility.DirectPrivate
|
TootVisibility.DirectPrivate
|
||||||
)
|
)
|
||||||
|
|
||||||
true == ti?.hasCapability(InstanceCapability.VisibilityMutual) ->
|
InstanceCapability.visibilityMutual(ti) ->
|
||||||
arrayOf(
|
arrayOf(
|
||||||
TootVisibility.WebSetting,
|
TootVisibility.WebSetting,
|
||||||
TootVisibility.Public,
|
TootVisibility.Public,
|
||||||
|
@ -2693,7 +2693,7 @@ class ActPost : AsyncActivity(),
|
||||||
TootVisibility.DirectSpecified
|
TootVisibility.DirectSpecified
|
||||||
)
|
)
|
||||||
|
|
||||||
true == ti?.hasCapability(InstanceCapability.VisibilityLimited) ->
|
InstanceCapability.visibilityLimited(ti)->
|
||||||
arrayOf(
|
arrayOf(
|
||||||
TootVisibility.WebSetting,
|
TootVisibility.WebSetting,
|
||||||
TootVisibility.Public,
|
TootVisibility.Public,
|
||||||
|
|
|
@ -692,28 +692,52 @@ enum class ColumnType(
|
||||||
REACTIONS(
|
REACTIONS(
|
||||||
42,
|
42,
|
||||||
iconId = { R.drawable.ic_face },
|
iconId = { R.drawable.ic_face },
|
||||||
name1 = { it.getString(R.string.reactions) },
|
name1 = { it.getString(R.string.reactioned_posts) },
|
||||||
bAllowPseudo = false,
|
bAllowPseudo = false,
|
||||||
bAllowMisskey = false,
|
bAllowMisskey = false,
|
||||||
|
|
||||||
loading = { client ->
|
loading = { client ->
|
||||||
if (isMisskey) {
|
if (isMisskey) {
|
||||||
TootApiResult("misskey has no api to list your reactions")
|
getStatusList(
|
||||||
|
client,
|
||||||
|
ApiPath.PATH_M544_REACTIONS,
|
||||||
|
misskeyParams = column.makeMisskeyTimelineParameter(parser),
|
||||||
|
listParser = misskeyCustomParserFavorites
|
||||||
|
)
|
||||||
} else {
|
} else {
|
||||||
getStatusList(client,column.makeReactionsUrl())
|
getStatusList(client,column.makeReactionsUrl())
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
||||||
refresh = { client ->
|
refresh = { client ->
|
||||||
getStatusList(client,column.makeReactionsUrl())
|
if (isMisskey) {
|
||||||
|
getStatusList(
|
||||||
|
client,
|
||||||
|
ApiPath.PATH_M544_REACTIONS,
|
||||||
|
misskeyParams = column.makeMisskeyTimelineParameter(parser),
|
||||||
|
listParser = misskeyCustomParserFavorites
|
||||||
|
)
|
||||||
|
} else {
|
||||||
|
getStatusList(client, column.makeReactionsUrl())
|
||||||
|
}
|
||||||
},
|
},
|
||||||
|
|
||||||
gap = { client ->
|
gap = { client ->
|
||||||
getStatusList(
|
if (isMisskey) {
|
||||||
client,
|
getStatusList(
|
||||||
column.makeReactionsUrl(),
|
client,
|
||||||
mastodonFilterByIdRange = false
|
ApiPath.PATH_M544_REACTIONS,
|
||||||
)
|
mastodonFilterByIdRange = false,
|
||||||
|
misskeyParams = column.makeMisskeyTimelineParameter(parser),
|
||||||
|
listParser = misskeyCustomParserFavorites
|
||||||
|
)
|
||||||
|
} else {
|
||||||
|
getStatusList(
|
||||||
|
client,
|
||||||
|
column.makeReactionsUrl(),
|
||||||
|
mastodonFilterByIdRange = false
|
||||||
|
)
|
||||||
|
}
|
||||||
},
|
},
|
||||||
gapDirection = gapDirectionMastodonWorkaround,
|
gapDirection = gapDirectionMastodonWorkaround,
|
||||||
),
|
),
|
||||||
|
|
|
@ -215,7 +215,8 @@ fun ColumnViewHolder.onPageCreate(column: Column, page_idx: Int, page_count: Int
|
||||||
btnSearchClear.vg(Pref.bpShowSearchClear(activity.pref))
|
btnSearchClear.vg(Pref.bpShowSearchClear(activity.pref))
|
||||||
cbResolve.vg(column.type == ColumnType.SEARCH)
|
cbResolve.vg(column.type == ColumnType.SEARCH)
|
||||||
}
|
}
|
||||||
column.type == ColumnType.REACTIONS -> {
|
|
||||||
|
column.type == ColumnType.REACTIONS && column.access_info.isMastodon -> {
|
||||||
llSearch.vg(true)
|
llSearch.vg(true)
|
||||||
|
|
||||||
flEmoji.vg(true)
|
flEmoji.vg(true)
|
||||||
|
|
|
@ -1,6 +1,5 @@
|
||||||
package jp.juggler.subwaytooter
|
package jp.juggler.subwaytooter
|
||||||
|
|
||||||
import android.app.Activity
|
|
||||||
import android.content.Context
|
import android.content.Context
|
||||||
import android.content.Intent
|
import android.content.Intent
|
||||||
import android.content.pm.PackageManager
|
import android.content.pm.PackageManager
|
||||||
|
@ -23,9 +22,6 @@ import androidx.drawerlayout.widget.DrawerLayout
|
||||||
import jp.juggler.subwaytooter.action.Action_Account
|
import jp.juggler.subwaytooter.action.Action_Account
|
||||||
import jp.juggler.subwaytooter.action.Action_App
|
import jp.juggler.subwaytooter.action.Action_App
|
||||||
import jp.juggler.subwaytooter.action.Action_Instance
|
import jp.juggler.subwaytooter.action.Action_Instance
|
||||||
import jp.juggler.subwaytooter.api.TootApiCallback
|
|
||||||
import jp.juggler.subwaytooter.api.TootApiClient
|
|
||||||
import jp.juggler.subwaytooter.api.entity.TootInstance
|
|
||||||
import jp.juggler.subwaytooter.api.entity.TootStatus
|
import jp.juggler.subwaytooter.api.entity.TootStatus
|
||||||
import jp.juggler.subwaytooter.dialog.AccountPicker
|
import jp.juggler.subwaytooter.dialog.AccountPicker
|
||||||
import jp.juggler.subwaytooter.table.SavedAccount
|
import jp.juggler.subwaytooter.table.SavedAccount
|
||||||
|
@ -269,8 +265,13 @@ class SideMenuAdapter(
|
||||||
Item(icon = R.drawable.ic_bookmark, title = R.string.bookmarks) {
|
Item(icon = R.drawable.ic_bookmark, title = R.string.bookmarks) {
|
||||||
Action_Account.timeline(this, defaultInsertPosition, ColumnType.BOOKMARKS)
|
Action_Account.timeline(this, defaultInsertPosition, ColumnType.BOOKMARKS)
|
||||||
},
|
},
|
||||||
Item(icon = R.drawable.ic_face, title = R.string.fedibird_reactions) {
|
Item(icon = R.drawable.ic_face, title = R.string.reactioned_posts) {
|
||||||
Action_Account.getReactionableAccounts(this, allowMisskey = false) { list ->
|
Action_Account.listAccountsCanSeeMyReactions(this) { list ->
|
||||||
|
if (list.isEmpty()) {
|
||||||
|
showToast(false, R.string.not_available_for_current_accounts)
|
||||||
|
return@listAccountsCanSeeMyReactions
|
||||||
|
}
|
||||||
|
|
||||||
val columnType = ColumnType.REACTIONS
|
val columnType = ColumnType.REACTIONS
|
||||||
AccountPicker.pick(
|
AccountPicker.pick(
|
||||||
this,
|
this,
|
||||||
|
|
|
@ -13,9 +13,7 @@ import jp.juggler.subwaytooter.table.UserRelation
|
||||||
import jp.juggler.subwaytooter.util.LinkHelper
|
import jp.juggler.subwaytooter.util.LinkHelper
|
||||||
import jp.juggler.subwaytooter.util.openBrowser
|
import jp.juggler.subwaytooter.util.openBrowser
|
||||||
import jp.juggler.util.*
|
import jp.juggler.util.*
|
||||||
import kotlinx.coroutines.Dispatchers
|
import kotlinx.coroutines.*
|
||||||
import kotlinx.coroutines.launch
|
|
||||||
import kotlinx.coroutines.withContext
|
|
||||||
|
|
||||||
object Action_Account {
|
object Action_Account {
|
||||||
|
|
||||||
|
@ -385,28 +383,32 @@ object Action_Account {
|
||||||
}.show()
|
}.show()
|
||||||
}
|
}
|
||||||
|
|
||||||
fun getReactionableAccounts(
|
fun listAccountsReactionable(
|
||||||
activity: ActMain,
|
activity: ActMain,
|
||||||
allowMisskey: Boolean = true,
|
|
||||||
block: (ArrayList<SavedAccount>) -> Unit
|
block: (ArrayList<SavedAccount>) -> Unit
|
||||||
) {
|
) {
|
||||||
TootTaskRunner(activity).run(object : TootTask {
|
TootTaskRunner(activity).run(object : TootTask {
|
||||||
var list: List<SavedAccount>? = null
|
var list: List<SavedAccount>? = null
|
||||||
|
|
||||||
|
suspend fun check(client:TootApiClient,a:SavedAccount)=when {
|
||||||
|
client.isApiCancelled -> false
|
||||||
|
a.isPseudo -> false
|
||||||
|
a.isMisskey -> true
|
||||||
|
else -> {
|
||||||
|
val (ti, ri) = TootInstance.getEx(client.copy(), account = a)
|
||||||
|
if (ti == null) {
|
||||||
|
ri?.error?.let { log.w(it) }
|
||||||
|
false
|
||||||
|
} else InstanceCapability.emojiReaction(a,ti)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
override suspend fun background(client: TootApiClient): TootApiResult? {
|
override suspend fun background(client: TootApiClient): TootApiResult? {
|
||||||
list = SavedAccount.loadAccountList(activity).filter { a ->
|
coroutineScope {
|
||||||
when {
|
list = SavedAccount.loadAccountList(activity)
|
||||||
client.isApiCancelled -> false
|
.map { async { if(check(client,it)) it else null } }
|
||||||
a.isPseudo -> false
|
.awaitAll()
|
||||||
a.isMisskey -> allowMisskey
|
.filterNotNull()
|
||||||
else -> {
|
|
||||||
val (ti, ri) = TootInstance.getEx(client, account = a)
|
|
||||||
if (ti == null) {
|
|
||||||
ri?.error?.let { log.w(it) }
|
|
||||||
false
|
|
||||||
} else
|
|
||||||
ti.fedibird_capabilities?.contains("emoji_reaction") == true
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
return if (client.isApiCancelled) null else TootApiResult()
|
return if (client.isApiCancelled) null else TootApiResult()
|
||||||
}
|
}
|
||||||
|
@ -417,7 +419,41 @@ object Action_Account {
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
fun listAccountsCanSeeMyReactions(
|
||||||
|
activity: ActMain,
|
||||||
|
block: (ArrayList<SavedAccount>) -> Unit
|
||||||
|
) {
|
||||||
|
TootTaskRunner(activity).run(object : TootTask {
|
||||||
|
var list: List<SavedAccount>? = null
|
||||||
|
|
||||||
|
suspend fun check(client:TootApiClient,a:SavedAccount)=when {
|
||||||
|
client.isApiCancelled -> false
|
||||||
|
a.isPseudo -> false
|
||||||
|
else -> {
|
||||||
|
val (ti, ri) = TootInstance.getEx(client.copy(), account = a)
|
||||||
|
if (ti == null) {
|
||||||
|
ri?.error?.let { log.w(it) }
|
||||||
|
false
|
||||||
|
} else InstanceCapability.listMyReactions(a,ti)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
override suspend fun background(client: TootApiClient): TootApiResult? {
|
||||||
|
coroutineScope {
|
||||||
|
list = SavedAccount.loadAccountList(activity)
|
||||||
|
.map { async { if(check(client,it)) it else null } }
|
||||||
|
.awaitAll()
|
||||||
|
.filterNotNull()
|
||||||
|
}
|
||||||
|
return if (client.isApiCancelled) null else TootApiResult()
|
||||||
|
}
|
||||||
|
|
||||||
|
override suspend fun handleResult(result: TootApiResult?) {
|
||||||
|
result ?: return
|
||||||
|
if (list != null) block(ArrayList(list))
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
// アカウントを選んでタイムラインカラムを追加
|
// アカウントを選んでタイムラインカラムを追加
|
||||||
fun timelineWithFilter(
|
fun timelineWithFilter(
|
||||||
activity: ActMain,
|
activity: ActMain,
|
||||||
|
|
|
@ -1650,7 +1650,13 @@ object Action_Toot {
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
Action_Account.getReactionableAccounts(activity) { list ->
|
Action_Account.listAccountsReactionable(activity) { list ->
|
||||||
|
|
||||||
|
if (list.isEmpty()) {
|
||||||
|
activity.showToast(false, R.string.not_available_for_current_accounts)
|
||||||
|
return@listAccountsReactionable
|
||||||
|
}
|
||||||
|
|
||||||
AccountPicker.pick(
|
AccountPicker.pick(
|
||||||
activity,
|
activity,
|
||||||
accountListArg = list,
|
accountListArg = list,
|
||||||
|
|
|
@ -53,4 +53,6 @@ object ApiPath {
|
||||||
const val PATH_MISSKEY_FOLLOW_REQUESTS = "/api/following/requests/list"
|
const val PATH_MISSKEY_FOLLOW_REQUESTS = "/api/following/requests/list"
|
||||||
const val PATH_MISSKEY_FOLLOW_SUGGESTION = "/api/users/recommendation"
|
const val PATH_MISSKEY_FOLLOW_SUGGESTION = "/api/users/recommendation"
|
||||||
const val PATH_MISSKEY_FAVORITES = "/api/i/favorites"
|
const val PATH_MISSKEY_FAVORITES = "/api/i/favorites"
|
||||||
}
|
|
||||||
|
const val PATH_M544_REACTIONS ="/api/i/reactions"
|
||||||
|
}
|
||||||
|
|
|
@ -1269,6 +1269,14 @@ class TootApiClient(
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fun copy() =TootApiClient(
|
||||||
|
context,
|
||||||
|
httpClient,
|
||||||
|
callback
|
||||||
|
).also{dst->
|
||||||
|
dst.account = account
|
||||||
|
dst.apiHost = apiHost
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// query: query_string after ? ( ? itself is excluded )
|
// query: query_string after ? ( ? itself is excluded )
|
||||||
|
|
|
@ -104,7 +104,6 @@ class TootTaskRunner(
|
||||||
fun run(instance: Host, callback: TootTask): TootTaskRunner {
|
fun run(instance: Host, callback: TootTask): TootTaskRunner {
|
||||||
client.apiHost = instance
|
client.apiHost = instance
|
||||||
return run(callback)
|
return run(callback)
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
fun progressPrefix(s: String): TootTaskRunner {
|
fun progressPrefix(s: String): TootTaskRunner {
|
||||||
|
|
|
@ -11,7 +11,6 @@ import jp.juggler.subwaytooter.util.LinkHelper
|
||||||
import jp.juggler.subwaytooter.util.VersionString
|
import jp.juggler.subwaytooter.util.VersionString
|
||||||
import jp.juggler.util.*
|
import jp.juggler.util.*
|
||||||
import kotlinx.coroutines.Dispatchers
|
import kotlinx.coroutines.Dispatchers
|
||||||
import kotlinx.coroutines.GlobalScope
|
|
||||||
import kotlinx.coroutines.channels.Channel
|
import kotlinx.coroutines.channels.Channel
|
||||||
import kotlinx.coroutines.launch
|
import kotlinx.coroutines.launch
|
||||||
import okhttp3.Request
|
import okhttp3.Request
|
||||||
|
@ -28,39 +27,45 @@ enum class InstanceType {
|
||||||
Pleroma
|
Pleroma
|
||||||
}
|
}
|
||||||
|
|
||||||
enum class CapabilitySource {
|
object InstanceCapability {
|
||||||
Fedibird,
|
// FavouriteHashtag(CapabilitySource.Fedibird, "favourite_hashtag"),
|
||||||
}
|
// FavouriteDomain(CapabilitySource.Fedibird, "favourite_domain"),
|
||||||
|
// StatusExpire(CapabilitySource.Fedibird, "status_expire"),
|
||||||
|
// FollowNoDelivery(CapabilitySource.Fedibird, "follow_no_delivery"),
|
||||||
|
// FollowHashtag(CapabilitySource.Fedibird, "follow_hashtag"),
|
||||||
|
// SubscribeAccount(CapabilitySource.Fedibird, "subscribe_account"),
|
||||||
|
// SubscribeDomain(CapabilitySource.Fedibird, "subscribe_domain"),
|
||||||
|
// SubscribeKeyword(CapabilitySource.Fedibird, "subscribe_keyword"),
|
||||||
|
// TimelineNoLocal(CapabilitySource.Fedibird, "timeline_no_local"),
|
||||||
|
// TimelineDomain(CapabilitySource.Fedibird, "timeline_domain"),
|
||||||
|
// TimelineGroup(CapabilitySource.Fedibird, "timeline_group"),
|
||||||
|
// TimelineGroupDirectory(CapabilitySource.Fedibird, "timeline_group_directory"),
|
||||||
|
|
||||||
enum class InstanceCapability(
|
fun visibilityMutual(ti: TootInstance?) =
|
||||||
private val capabilitySource: CapabilitySource,
|
ti?.fedibird_capabilities?.contains("visibility_mutual") == true
|
||||||
private val id: String
|
|
||||||
) {
|
|
||||||
FavouriteHashtag(CapabilitySource.Fedibird, "favourite_hashtag"),
|
|
||||||
FavouriteDomain(CapabilitySource.Fedibird, "favourite_domain"),
|
|
||||||
StatusExpire(CapabilitySource.Fedibird, "status_expire"),
|
|
||||||
FollowNoDelivery(CapabilitySource.Fedibird, "follow_no_delivery"),
|
|
||||||
FollowHashtag(CapabilitySource.Fedibird, "follow_hashtag"),
|
|
||||||
SubscribeAccount(CapabilitySource.Fedibird, "subscribe_account"),
|
|
||||||
SubscribeDomain(CapabilitySource.Fedibird, "subscribe_domain"),
|
|
||||||
SubscribeKeyword(CapabilitySource.Fedibird, "subscribe_keyword"),
|
|
||||||
TimelineNoLocal(CapabilitySource.Fedibird, "timeline_no_local"),
|
|
||||||
TimelineDomain(CapabilitySource.Fedibird, "timeline_domain"),
|
|
||||||
TimelineGroup(CapabilitySource.Fedibird, "timeline_group"),
|
|
||||||
TimelineGroupDirectory(CapabilitySource.Fedibird, "timeline_group_directory"),
|
|
||||||
VisibilityMutual(CapabilitySource.Fedibird, "visibility_mutual"),
|
|
||||||
VisibilityLimited(CapabilitySource.Fedibird, "visibility_limited"),
|
|
||||||
;
|
|
||||||
|
|
||||||
fun hasCapability(instance: TootInstance): Boolean {
|
|
||||||
when (capabilitySource) {
|
fun visibilityLimited(ti: TootInstance?) =
|
||||||
CapabilitySource.Fedibird -> {
|
ti?.fedibird_capabilities?.contains("visibility_limited") == true
|
||||||
if (instance.fedibird_capabilities?.any { it == id } == true) return true
|
|
||||||
}
|
|
||||||
|
fun emojiReaction(ai: SavedAccount, ti: TootInstance?) =
|
||||||
|
when {
|
||||||
|
ai.isPseudo -> false
|
||||||
|
ai.isMisskey -> true
|
||||||
|
else -> ti?.fedibird_capabilities?.contains("emoji_reaction") == true
|
||||||
|
}
|
||||||
|
|
||||||
|
fun listMyReactions(ai: SavedAccount, ti: TootInstance?) =
|
||||||
|
when {
|
||||||
|
ai.isPseudo -> false
|
||||||
|
ai.isMisskey ->
|
||||||
|
// m544 extension
|
||||||
|
ti?.misskeyEndpoints?.contains("i/reactions") == true
|
||||||
|
else ->
|
||||||
|
// fedibird extension
|
||||||
|
ti?.fedibird_capabilities?.contains("emoji_reaction") == true
|
||||||
}
|
}
|
||||||
// XXX: もし機能がMastodon公式に取り込まれたならバージョン番号で判断できるはず
|
|
||||||
return false
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
class TootInstance(parser: TootParser, src: JsonObject) {
|
class TootInstance(parser: TootParser, src: JsonObject) {
|
||||||
|
@ -121,13 +126,17 @@ class TootInstance(parser: TootParser, src: JsonObject) {
|
||||||
|
|
||||||
var feature_quote = false
|
var feature_quote = false
|
||||||
|
|
||||||
var fedibird_capabilities: JsonArray? = null
|
var fedibird_capabilities: Set<String>? = null
|
||||||
|
|
||||||
|
var misskeyEndpoints: Set<String>? = null
|
||||||
|
|
||||||
// XXX: urls をパースしてない。使ってないから…
|
// XXX: urls をパースしてない。使ってないから…
|
||||||
|
|
||||||
init {
|
init {
|
||||||
if (parser.serviceType == ServiceType.MISSKEY) {
|
if (parser.serviceType == ServiceType.MISSKEY) {
|
||||||
|
|
||||||
|
this.misskeyEndpoints = src.jsonArray("_endpoints")?.stringList()?.toSet()
|
||||||
|
|
||||||
this.uri = parser.apiHost.ascii
|
this.uri = parser.apiHost.ascii
|
||||||
this.title = parser.apiHost.pretty
|
this.title = parser.apiHost.pretty
|
||||||
val sv = src.jsonObject("maintainer")?.string("url")
|
val sv = src.jsonObject("maintainer")?.string("url")
|
||||||
|
@ -192,7 +201,7 @@ class TootInstance(parser: TootParser, src: JsonObject) {
|
||||||
|
|
||||||
this.invites_enabled = src.boolean("invites_enabled")
|
this.invites_enabled = src.boolean("invites_enabled")
|
||||||
|
|
||||||
this.fedibird_capabilities = src.jsonArray("fedibird_capabilities")
|
this.fedibird_capabilities = src.jsonArray("fedibird_capabilities")?.stringList()?.toSet()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -222,8 +231,6 @@ class TootInstance(parser: TootParser, src: JsonObject) {
|
||||||
return i >= 0
|
return i >= 0
|
||||||
}
|
}
|
||||||
|
|
||||||
fun hasCapability(cap: InstanceCapability) = cap.hasCapability(this)
|
|
||||||
|
|
||||||
companion object {
|
companion object {
|
||||||
|
|
||||||
private val rePleroma = """\bpleroma\b""".asciiPattern(Pattern.CASE_INSENSITIVE)
|
private val rePleroma = """\bpleroma\b""".asciiPattern(Pattern.CASE_INSENSITIVE)
|
||||||
|
@ -274,7 +281,7 @@ class TootInstance(parser: TootParser, src: JsonObject) {
|
||||||
if (sendRequest(result) {
|
if (sendRequest(result) {
|
||||||
val builder = Request.Builder().url("https://${apiHost?.ascii}/api/v1/instance")
|
val builder = Request.Builder().url("https://${apiHost?.ascii}/api/v1/instance")
|
||||||
|
|
||||||
(forceAccessToken ?: account?.getAccessToken() )
|
(forceAccessToken ?: account?.getAccessToken())
|
||||||
?.notEmpty()?.let { builder.header("Authorization", "Bearer $it") }
|
?.notEmpty()?.let { builder.header("Authorization", "Bearer $it") }
|
||||||
builder.build()
|
builder.build()
|
||||||
}
|
}
|
||||||
|
@ -285,6 +292,26 @@ class TootInstance(parser: TootParser, src: JsonObject) {
|
||||||
return result
|
return result
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private suspend fun TootApiClient.getMisskeyEndpoints(
|
||||||
|
forceAccessToken: String? = null
|
||||||
|
): TootApiResult? {
|
||||||
|
val result = TootApiResult.makeWithCaption(apiHost?.pretty)
|
||||||
|
if (result.error != null) return result
|
||||||
|
|
||||||
|
if (sendRequest(result) {
|
||||||
|
jsonObject {
|
||||||
|
(forceAccessToken ?: account?.misskeyApiToken)
|
||||||
|
?.notEmpty()?.let { put("i", it) }
|
||||||
|
}.toPostRequestBuilder()
|
||||||
|
.url("https://${apiHost?.ascii}/api/endpoints")
|
||||||
|
.build()
|
||||||
|
}
|
||||||
|
) {
|
||||||
|
parseJson(result) ?: return null
|
||||||
|
}
|
||||||
|
return result
|
||||||
|
}
|
||||||
|
|
||||||
// 疑似アカウントの追加時に、インスタンスの検証を行う
|
// 疑似アカウントの追加時に、インスタンスの検証を行う
|
||||||
private suspend fun TootApiClient.getInstanceInformationMisskey(
|
private suspend fun TootApiClient.getInstanceInformationMisskey(
|
||||||
forceAccessToken: String? = null
|
forceAccessToken: String? = null
|
||||||
|
@ -295,7 +322,7 @@ class TootInstance(parser: TootParser, src: JsonObject) {
|
||||||
if (sendRequest(result) {
|
if (sendRequest(result) {
|
||||||
jsonObject {
|
jsonObject {
|
||||||
put("dummy", 1)
|
put("dummy", 1)
|
||||||
(forceAccessToken ?: account?.misskeyApiToken )
|
(forceAccessToken ?: account?.misskeyApiToken)
|
||||||
?.notEmpty()?.let { put("i", it) }
|
?.notEmpty()?.let { put("i", it) }
|
||||||
}.toPostRequestBuilder()
|
}.toPostRequestBuilder()
|
||||||
.url("https://${apiHost?.ascii}/api/meta")
|
.url("https://${apiHost?.ascii}/api/meta")
|
||||||
|
@ -309,6 +336,10 @@ class TootInstance(parser: TootParser, src: JsonObject) {
|
||||||
if (m.find()) {
|
if (m.find()) {
|
||||||
put(TootApiClient.KEY_MISSKEY_VERSION, max(1, m.groupEx(1)!!.toInt()))
|
put(TootApiClient.KEY_MISSKEY_VERSION, max(1, m.groupEx(1)!!.toInt()))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// add endpoints
|
||||||
|
val r2 = getMisskeyEndpoints(forceAccessToken)
|
||||||
|
r2?.jsonArray?.let { result.jsonObject?.put("_endpoints", it) }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return result
|
return result
|
||||||
|
@ -419,9 +450,9 @@ class TootInstance(parser: TootParser, src: JsonObject) {
|
||||||
return queuedRequest(allowPixelfed) { cached ->
|
return queuedRequest(allowPixelfed) { cached ->
|
||||||
|
|
||||||
// may use cached item.
|
// may use cached item.
|
||||||
if (!forceUpdate && forceAccessToken == null && cached!=null) {
|
if (!forceUpdate && forceAccessToken == null && cached != null) {
|
||||||
val now = SystemClock.elapsedRealtime()
|
val now = SystemClock.elapsedRealtime()
|
||||||
if ( now - cached.time_parse <= EXPIRE)
|
if (now - cached.time_parse <= EXPIRE)
|
||||||
return@queuedRequest Pair(cached, TootApiResult())
|
return@queuedRequest Pair(cached, TootApiResult())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -96,7 +96,7 @@ class TootReaction(
|
||||||
|
|
||||||
val UNKNOWN = TootReaction(name = "?")
|
val UNKNOWN = TootReaction(name = "?")
|
||||||
|
|
||||||
fun isUnicodeEmoji(code: String): Boolean =
|
private fun isUnicodeEmoji(code: String): Boolean =
|
||||||
code.any { it.code >= 0x7f }
|
code.any { it.code >= 0x7f }
|
||||||
|
|
||||||
fun splitEmojiDomain(code: String): Pair<String?, String?> {
|
fun splitEmojiDomain(code: String): Pair<String?, String?> {
|
||||||
|
@ -111,11 +111,7 @@ class TootReaction(
|
||||||
fun canReaction(
|
fun canReaction(
|
||||||
access_info: SavedAccount,
|
access_info: SavedAccount,
|
||||||
ti: TootInstance? = TootInstance.getCached(access_info.apiHost)
|
ti: TootInstance? = TootInstance.getCached(access_info.apiHost)
|
||||||
) = when {
|
) = InstanceCapability.emojiReaction(access_info,ti)
|
||||||
access_info.isPseudo -> false
|
|
||||||
access_info.isMisskey -> true
|
|
||||||
else -> ti?.fedibird_capabilities?.contains("emoji_reaction") == true
|
|
||||||
}
|
|
||||||
|
|
||||||
fun decodeEmojiQuery(jsonText: String?): List<TootReaction> =
|
fun decodeEmojiQuery(jsonText: String?): List<TootReaction> =
|
||||||
jsonText.notEmpty()?.let { src ->
|
jsonText.notEmpty()?.let { src ->
|
||||||
|
@ -137,9 +133,6 @@ class TootReaction(
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private val isUnicodeEmoji: Boolean
|
|
||||||
get() = isUnicodeEmoji(name)
|
|
||||||
|
|
||||||
fun splitEmojiDomain() =
|
fun splitEmojiDomain() =
|
||||||
splitEmojiDomain(name)
|
splitEmojiDomain(name)
|
||||||
|
|
||||||
|
|
File diff suppressed because it is too large
Load Diff
|
@ -1079,7 +1079,7 @@
|
||||||
<string name="confirm_mail_description">確認メールの再送を要求した後の手順:\n- あなたのメーラーで新着メールが届くのを確認する。\n- メール中の確認リンクを開く。\n- このダイアログを閉じてカラムをリロードする。</string>
|
<string name="confirm_mail_description">確認メールの再送を要求した後の手順:\n- あなたのメーラーで新着メールが届くのを確認する。\n- メール中の確認リンクを開く。\n- このダイアログを閉じてカラムをリロードする。</string>
|
||||||
<string name="push_notification_filter">プッシュ通知フィルタ(Mastodon 3.4.0以降。プッシュ通知の更新が必要)</string>
|
<string name="push_notification_filter">プッシュ通知フィルタ(Mastodon 3.4.0以降。プッシュ通知の更新が必要)</string>
|
||||||
<string name="no_one">誰もいない</string>
|
<string name="no_one">誰もいない</string>
|
||||||
<string name="fedibird_reactions">リアクション (Fedibird)</string>
|
<string name="reactioned_posts">リアクションした投稿</string>
|
||||||
<string name="reactions">リアクション</string>
|
<string name="reactions">リアクション</string>
|
||||||
<string name="cant_reaction_remote_custom_emoji">リモートのカスタム絵文字でリアクションできません %1$s</string>
|
<string name="cant_reaction_remote_custom_emoji">リモートのカスタム絵文字でリアクションできません %1$s</string>
|
||||||
<string name="keep_reaction_space">リアクション表示用の空間を確保する</string>
|
<string name="keep_reaction_space">リアクション表示用の空間を確保する</string>
|
||||||
|
@ -1090,5 +1090,5 @@
|
||||||
<string name="cant_save_duplicated_keyword">既に存在するキーワードを重複保存できません</string>
|
<string name="cant_save_duplicated_keyword">既に存在するキーワードを重複保存できません</string>
|
||||||
<string name="discard_changes">変更を破棄しますか?</string>
|
<string name="discard_changes">変更を破棄しますか?</string>
|
||||||
<string name="saved">保存しました</string>
|
<string name="saved">保存しました</string>
|
||||||
|
<string name="not_available_for_current_accounts">この機能を利用できるアカウントがありません</string>
|
||||||
</resources>
|
</resources>
|
||||||
|
|
|
@ -1093,7 +1093,7 @@
|
||||||
<string name="confirm_mail_description">After requesting resending confirm E-mail,\n- please check the mail on your mailer.\n- open confirm link in the mail.\n- close this dialog and reload column.</string>
|
<string name="confirm_mail_description">After requesting resending confirm E-mail,\n- please check the mail on your mailer.\n- open confirm link in the mail.\n- close this dialog and reload column.</string>
|
||||||
<string name="push_notification_filter">Push notification filter (Mastodon 3.4.0+, requires update push subscription)</string>
|
<string name="push_notification_filter">Push notification filter (Mastodon 3.4.0+, requires update push subscription)</string>
|
||||||
<string name="no_one">No one</string>
|
<string name="no_one">No one</string>
|
||||||
<string name="fedibird_reactions">Reactions (Fedibird)</string>
|
<string name="reactioned_posts">Reactioned posts</string>
|
||||||
<string name="reactions">Reactions</string>
|
<string name="reactions">Reactions</string>
|
||||||
<string name="cant_reaction_remote_custom_emoji">can\'t reaction with remote custom emoji %1$s</string>
|
<string name="cant_reaction_remote_custom_emoji">can\'t reaction with remote custom emoji %1$s</string>
|
||||||
<string name="keep_reaction_space">Keep Spacing for Reactions</string>
|
<string name="keep_reaction_space">Keep Spacing for Reactions</string>
|
||||||
|
@ -1103,4 +1103,6 @@
|
||||||
<string name="cant_save_duplicated_keyword">Can\'t save duplicated keyword.</string>
|
<string name="cant_save_duplicated_keyword">Can\'t save duplicated keyword.</string>
|
||||||
<string name="discard_changes">Discard changes?</string>
|
<string name="discard_changes">Discard changes?</string>
|
||||||
<string name="saved">saved.</string>
|
<string name="saved">saved.</string>
|
||||||
|
<string name="not_available_for_current_accounts">Unavailable for current accounts</string>
|
||||||
|
|
||||||
</resources>
|
</resources>
|
||||||
|
|
Loading…
Reference in New Issue