疑似アカウントでプロフカラムを開く

This commit is contained in:
tateisu 2018-12-26 13:47:16 +09:00
parent 6f7596ca68
commit cba123bf8c
7 changed files with 226 additions and 228 deletions

View File

@ -1895,9 +1895,9 @@ class Column(
stopStreaming()
initFilter()
useInstanceTicker = Pref.bpInstanceTicker( app_state.pref)
useInstanceTicker = Pref.bpInstanceTicker(app_state.pref)
mRefreshLoadingErrorPopupState = 0
mRefreshLoadingError = ""
mInitialLoadingError = ""
@ -2585,11 +2585,10 @@ class Column(
override fun doInBackground(vararg unused : Void) : TootApiResult? {
ctStarted.set(true)
if( Pref.bpInstanceTicker(app_state.pref)){
if(Pref.bpInstanceTicker(app_state.pref)) {
InstanceTicker.load()
}
val client = TootApiClient(context, callback = object : TootApiCallback {
override val isApiCancelled : Boolean
get() = isCancelled || is_dispose.get()
@ -2607,9 +2606,8 @@ class Column(
try {
var result : TootApiResult? = access_info.checkConfirmed(context,client)
if( result == null || result?.error != null ) return result
var result : TootApiResult? = access_info.checkConfirmed(context, client)
if(result == null || result?.error != null) return result
val q : String
@ -2669,66 +2667,105 @@ class Column(
when(profile_tab) {
TAB_FOLLOWING -> return if(isMisskey) {
pagingType = PagingType.Cursor
parseAccountList(
client
,
PATH_MISSKEY_PROFILE_FOLLOWING
,
emptyMessage = context.getString(R.string.none_or_hidden_following)
,
misskeyParams = makeMisskeyParamsUserId(parser)
,
misskeyArrayFinder = misskeyArrayFinderUsers
)
} else {
parseAccountList(
client,
String.format(
Locale.JAPAN,
PATH_ACCOUNT_FOLLOWING,
profile_id
),
emptyMessage = context.getString(R.string.none_or_hidden_following)
)
TAB_FOLLOWING -> return when {
access_info.isPseudo -> {
idRecent = null
idOld = null
list_tmp = addOne(
list_tmp,
TootMessageHolder(context.getString(R.string.pseudo_account_cant_get_follow_list))
)
TootApiResult()
}
isMisskey -> {
pagingType = PagingType.Cursor
parseAccountList(
client,
PATH_MISSKEY_PROFILE_FOLLOWING,
emptyMessage = context.getString(R.string.none_or_hidden_following),
misskeyParams = makeMisskeyParamsUserId(parser),
misskeyArrayFinder = misskeyArrayFinderUsers
)
}
else -> {
parseAccountList(
client,
String.format(
Locale.JAPAN,
PATH_ACCOUNT_FOLLOWING,
profile_id
),
emptyMessage = context.getString(R.string.none_or_hidden_following)
)
}
}
TAB_FOLLOWERS -> return if(isMisskey) {
pagingType = PagingType.Cursor
parseAccountList(
client,
PATH_MISSKEY_PROFILE_FOLLOWERS,
emptyMessage = context.getString(R.string.none_or_hidden_followers),
misskeyParams = makeMisskeyParamsUserId(parser),
misskeyArrayFinder = misskeyArrayFinderUsers
)
} else {
parseAccountList(
client,
String.format(
Locale.JAPAN,
PATH_ACCOUNT_FOLLOWERS,
profile_id
),
emptyMessage = context.getString(R.string.none_or_hidden_followers)
)
TAB_FOLLOWERS -> return when {
access_info.isPseudo -> {
idRecent = null
idOld = null
list_tmp = addOne(
list_tmp,
TootMessageHolder(context.getString(R.string.pseudo_account_cant_get_follow_list))
)
TootApiResult()
}
isMisskey -> {
pagingType = PagingType.Cursor
parseAccountList(
client,
PATH_MISSKEY_PROFILE_FOLLOWERS,
emptyMessage = context.getString(R.string.none_or_hidden_followers),
misskeyParams = makeMisskeyParamsUserId(parser),
misskeyArrayFinder = misskeyArrayFinderUsers
)
}
else -> {
parseAccountList(
client,
String.format(
Locale.JAPAN,
PATH_ACCOUNT_FOLLOWERS,
profile_id
),
emptyMessage = context.getString(R.string.none_or_hidden_followers)
)
}
}
else -> {
var instance = access_info.instance
return if(! isMisskey) {
return if(isMisskey) {
// 固定トゥートの取得
val pinnedNotes = who_account?.get()?.pinnedNotes
if(pinnedNotes != null) {
this.list_pinned =
addWithFilterStatus(null, pinnedNotes)
}
// 通常トゥートの取得
getStatuses(
client,
PATH_MISSKEY_PROFILE_STATUSES,
misskeyParams = makeMisskeyParamsProfileStatuses(parser),
initialUntilDate = true
)
} else {
// まだ取得してない
// 疑似アカウントの場合は過去のデータが別タンスかもしれない?
if(instance == null || access_info.isPseudo) {
val r2 = getInstanceInformation(client, null)
getInstanceInformation(client, null)
if(instance_tmp != null) {
instance = instance_tmp
access_info.instance = instance
}
if(access_info.isPseudo) return r2
}
var path = String.format(
@ -2744,22 +2781,8 @@ class Column(
) {
getStatusesPinned(client, "$path&pinned=true")
}
getStatuses(client, path)
} else {
// 固定トゥートの取得
val pinnedNotes = who_account?.get()?.pinnedNotes
if(pinnedNotes != null) {
this.list_pinned =
addWithFilterStatus(null, pinnedNotes)
}
// 通常トゥートの取得
getStatuses(
client,
PATH_MISSKEY_PROFILE_STATUSES,
misskeyParams = makeMisskeyParamsProfileStatuses(parser),
initialUntilDate = true
)
getStatuses(client, path)
}
}
}
@ -5822,8 +5845,7 @@ class Column(
TYPE_ENDORSEMENT -> getAccountList(client, PATH_ENDORSEMENT)
TYPE_PROFILE
-> when(profile_tab) {
TYPE_PROFILE -> when(profile_tab) {
TAB_FOLLOWING -> if(isMisskey) {
getAccountList(

View File

@ -141,10 +141,10 @@ internal class ItemViewHolder(
private lateinit var tvMessageHolder : TextView
private lateinit var llInstanceTicker:View
private lateinit var ivInstanceTicker:MyNetworkImageView
private lateinit var tvInstanceTicker:TextView
private lateinit var llInstanceTicker : View
private lateinit var ivInstanceTicker : MyNetworkImageView
private lateinit var tvInstanceTicker : TextView
private lateinit var access_info : SavedAccount
private var buttons_for_status : StatusButtons? = null
@ -1046,7 +1046,6 @@ internal class ItemViewHolder(
showInstanceTicker(who)
var content = status.decoded_content
// ニコフレのアンケートの表示
@ -1186,42 +1185,44 @@ internal class ItemViewHolder(
}
}
private fun showInstanceTicker(who:TootAccount) {
private fun showInstanceTicker(who : TootAccount) {
try {
if( !Column.useInstanceTicker) return
if(! Column.useInstanceTicker) return
val host = who.host
// LTLでホスト名が同じならTickerを表示しない
when(column.column_type){
Column.TYPE_LOCAL,Column.TYPE_LOCAL_AROUND->{
if( host == access_info.host) return
when(column.column_type) {
Column.TYPE_LOCAL, Column.TYPE_LOCAL_AROUND -> {
if(host == access_info.host) return
}
}
val item = InstanceTicker.lastList[host] ?: return
tvInstanceTicker.text = item.name
tvInstanceTicker.textColor = item.colorText
val density = activity.density
val lp = ivInstanceTicker.layoutParams
lp.height = (density*16f+0.5f).toInt()
lp.width = (density*item.imageWidth+0.5f).toInt()
lp.height = (density * 16f + 0.5f).toInt()
lp.width = (density * item.imageWidth + 0.5f).toInt()
ivInstanceTicker.layoutParams = lp
ivInstanceTicker.setImageUrl(activity.pref, 0f, item.image)
val colorBg = item.colorBg
when {
colorBg.isEmpty() ->{
colorBg.isEmpty() -> {
tvInstanceTicker.background = null
ivInstanceTicker.background = null
}
colorBg.size == 1 -> {
tvInstanceTicker.setBackgroundColor(colorBg.first())
ivInstanceTicker.setBackgroundColor(colorBg.first())
}
else -> {
ivInstanceTicker.setBackgroundColor(colorBg.last())
tvInstanceTicker.background = colorBg.getGradation()
@ -1230,8 +1231,8 @@ internal class ItemViewHolder(
}
llInstanceTicker.visibility = View.VISIBLE
llInstanceTicker.requestLayout()
}catch(ex:Throwable){
} catch(ex : Throwable) {
log.trace(ex)
}
}
@ -1422,7 +1423,7 @@ internal class ItemViewHolder(
iv.visibility = View.GONE
return
}
iv.visibility = View.VISIBLE
iv.setFocusPoint(ta.focusX, ta.focusY)
@ -1436,26 +1437,33 @@ internal class ItemViewHolder(
when(ta.type) {
TootAttachmentLike.TYPE_AUDIO->{
TootAttachmentLike.TYPE_AUDIO -> {
iv.setMediaType(0)
iv.setDefaultImageResId(getAttributeResourceId(activity,R.attr.ic_music))
iv.setImageUrl(activity.pref,0f,null)
iv.setDefaultImageResId(getAttributeResourceId(activity, R.attr.ic_music))
iv.setImageUrl(activity.pref, 0f, null)
}
TootAttachmentLike.TYPE_UNKNOWN->{
TootAttachmentLike.TYPE_UNKNOWN -> {
iv.setMediaType(0)
iv.setDefaultImageResId(getAttributeResourceId(activity,R.attr.ic_question))
iv.setImageUrl(activity.pref,0f,null)
iv.setDefaultImageResId(getAttributeResourceId(activity, R.attr.ic_question))
iv.setImageUrl(activity.pref, 0f, null)
}
else->{
val url =ta.urlForThumbnail
when{
url?.isEmpty() != false ->{
else -> {
val url = ta.urlForThumbnail
when {
url?.isEmpty() != false -> {
iv.setMediaType(0)
iv.setDefaultImageResId(getAttributeResourceId(activity,R.attr.ic_question))
iv.setImageUrl(activity.pref,0f,null)
iv.setDefaultImageResId(
getAttributeResourceId(
activity,
R.attr.ic_question
)
)
iv.setImageUrl(activity.pref, 0f, null)
}
else->{
else -> {
when(ta.type) {
TootAttachmentLike.TYPE_VIDEO -> {
iv.setMediaType(R.drawable.media_type_video)
@ -1551,20 +1559,22 @@ internal class ItemViewHolder(
ivThumbnail -> status_account?.let { whoRef ->
when {
access_info.isMisskey -> Action_User.profileLocal(
activity,
pos,
access_info,
whoRef.get()
)
access_info.isPseudo -> DlgContextMenu(
access_info.isNA ->DlgContextMenu(
activity,
column,
whoRef,
null,
notification
).show()
else -> Action_User.profileLocal(activity, pos, access_info, whoRef.get())
// 2018/12/26 疑似アカウントでもプロフカラムを表示する https://github.com/tootsuite/mastodon/commit/108b2139cd87321f6c0aec63ef93db85ce30bfec
else -> Action_User.profileLocal(
activity,
pos,
access_info,
whoRef.get()
)
}
}
@ -1951,8 +1961,6 @@ internal class ItemViewHolder(
}
private fun addLinkAndCaption(
sb : StringBuilder,
header : String,
@ -2262,7 +2270,7 @@ internal class ItemViewHolder(
)
} else {
client.request(
"/api/v1/votes/${enquete.status_id}" ,
"/api/v1/votes/${enquete.status_id}",
JSONObject()
.put("item_index", idx.toString())
.toPostRequestBuilder()
@ -2480,21 +2488,21 @@ internal class ItemViewHolder(
tvName = textView {
}.lparams(matchParent, wrapContent)
llInstanceTicker = linearLayout{
llInstanceTicker = linearLayout {
lparams(matchParent, wrapContent)
ivInstanceTicker = myNetworkImageView{
}.lparams(dip(16), dip(16)){
ivInstanceTicker = myNetworkImageView {
}.lparams(dip(16), dip(16)) {
isBaselineAligned = false
}
tvInstanceTicker = textView{
setTextSize(TypedValue.COMPLEX_UNIT_DIP,10f)
gravity=Gravity.CENTER_VERTICAL
setPaddingStartEnd( dip(4f), dip(4f) )
}.lparams(0,dip(16) ){
tvInstanceTicker = textView {
setTextSize(TypedValue.COMPLEX_UNIT_DIP, 10f)
gravity = Gravity.CENTER_VERTICAL
setPaddingStartEnd(dip(4f), dip(4f))
}.lparams(0, dip(16)) {
isBaselineAligned = false
weight=1f
weight = 1f
}
}

View File

@ -1,7 +1,6 @@
package jp.juggler.subwaytooter.action
import android.content.Context
import jp.juggler.subwaytooter.ActMain
import jp.juggler.subwaytooter.api.*
import jp.juggler.subwaytooter.api.entity.EntityId
import jp.juggler.subwaytooter.api.entity.TootAccount
@ -10,51 +9,11 @@ import jp.juggler.subwaytooter.api.entity.parseList
import jp.juggler.subwaytooter.table.SavedAccount
import jp.juggler.subwaytooter.table.UserRelation
import jp.juggler.subwaytooter.table.UserRelationMisskey
import jp.juggler.subwaytooter.util.TootAccountOrNullCallback
import jp.juggler.util.LogCategory
import jp.juggler.util.encodePercent
import jp.juggler.util.showToast
import org.json.JSONObject
import java.util.*
// ユーザ名からアカウントIDを取得する
internal fun findAccountByName(
activity : ActMain,
access_info : SavedAccount,
host : String,
user : String,
callback : TootAccountOrNullCallback // 失敗するとnullがコールバックされる
) {
TootTaskRunner(activity).run(access_info, object : TootTask {
var who : TootAccount? = null
override fun background(client : TootApiClient) : TootApiResult? {
val result = client.request("/api/v1/accounts/search?q=${user.encodePercent()}")
val array = result?.jsonArray
if(array != null) {
val parser = TootParser(activity, access_info)
for(i in 0 until array.length()) {
val a = parser.account(array.optJSONObject(i)) ?: continue
if(a.username == user
&& access_info.getFullAcct(a).equals("$user@$host", ignoreCase = true)
) {
who = a
break
}
}
}
return result
}
override fun handleResult(result : TootApiResult?) {
callback(who)
}
})
}
// 疑似アカウントを作成する
// 既に存在する場合は再利用する
// 実アカウントを返すことはない

View File

@ -69,7 +69,7 @@ object Action_User {
! bMute -> "".toRequestBody()
else ->
JSONObject()
.put("notifications" ,bMuteNotification)
.put("notifications", bMuteNotification)
.toRequestBody()
}.toPost()
)
@ -290,24 +290,7 @@ object Action_User {
}
// 今のアカウントでユーザプロフを開く
fun profileLocal(
activity : ActMain,
pos : Int,
access_info : SavedAccount,
who : TootAccount
) {
when {
access_info.isMisskey -> activity.addColumn(
pos,
access_info,
Column.TYPE_PROFILE,
who.id
)
access_info.isPseudo -> profileFromAnotherAccount(activity, pos, access_info, who)
else -> activity.addColumn(pos, access_info, Column.TYPE_PROFILE, who.id)
}
}
//////////////////////////////////////////////////////////////////////////////////////
// URLからユーザを検索してプロフを開く
private fun profileFromUrl(
@ -318,30 +301,31 @@ object Action_User {
) {
TootTaskRunner(activity).run(access_info, object : TootTask {
var who_local : TootAccount? = null
override fun background(client : TootApiClient) : TootApiResult? {
val result = client.syncAccountByUrl(access_info, who_url)
who_local = result?.data as? TootAccount
return result
}
var who : TootAccount? = null
override fun background(client : TootApiClient) : TootApiResult? =
client.syncAccountByUrl(access_info, who_url)?.also { result ->
who = result.data as? TootAccount
}
override fun handleResult(result : TootApiResult?) {
result ?: return // cancelled.
val wl = who_local
if(wl != null) {
activity.addColumn(pos, access_info, Column.TYPE_PROFILE, wl.id)
} else {
showToast(activity, true, result.error)
when(val who = this.who) {
null -> {
showToast(activity, true, result.error)
// 仕方ないのでchrome tab で開く
App1.openCustomTab(activity, who_url)
}
// 仕方ないのでchrome tab で開く
App1.openCustomTab(activity, who_url)
else -> activity.addColumn(pos, access_info, Column.TYPE_PROFILE, who.id)
}
}
})
}
// アカウントを選んでユーザプロフを開く
fun profileFromAnotherAccount(
activity : ActMain,
@ -370,8 +354,21 @@ object Action_User {
}
}
// Intent-FilterからUser URL で指定されたユーザのプロフを開く
// openChromeTabからUser URL で指定されたユーザのプロフを開く
// 今のアカウントでユーザプロフを開く
fun profileLocal(
activity : ActMain,
pos : Int,
access_info : SavedAccount,
who : TootAccount
) {
when {
access_info.isNA -> profileFromAnotherAccount(activity, pos, access_info, who)
else -> activity.addColumn(pos, access_info, Column.TYPE_PROFILE, who.id)
}
}
// User URL で指定されたユーザのプロフを開く
// Intent-Filter や openChromeTabから 呼ばれる
fun profile(
activity : ActMain,
pos : Int,
@ -380,35 +377,51 @@ object Action_User {
host : String,
user : String
) {
// リンクタップした文脈のアカウントが疑似でないなら
if(access_info != null && ! access_info.isPseudo) {
if(access_info?.isPseudo == false) {
// 文脈のアカウントがあり、疑似アカウントではない
if(access_info.host.equals(host, ignoreCase = true)) {
// 文脈のアカウントと同じインスタンスなら、アカウントIDを探して開いてしまう
findAccountByName(activity, access_info, host, user) { who : TootAccount? ->
if(who != null) {
profileLocal(activity, pos, access_info, who)
} else {
// ダメならchromeで開く
App1.openCustomTab(activity, url)
val acct = "$user@$host"
TootTaskRunner(activity).run(access_info, object : TootTask {
var who : TootAccount? = null
override fun background(client : TootApiClient) : TootApiResult? =
client.syncAccountByAcct(access_info, acct)?.also {
this.who = it.data as? TootAccount
}
override fun handleResult(result : TootApiResult?) {
result ?: return // cancelled
when(val who = this.who) {
null -> {
// ダメならchromeで開く
App1.openCustomTab(activity, url)
}
else -> profileLocal(activity, pos, access_info, who)
}
}
}
})
} else {
// 文脈のアカウント異なるインスタンスなら、別アカウントで開く
// 文脈のアカウント異なるインスタンスなら、別アカウントで開く
profileFromUrl(activity, pos, access_info, url)
}
return
}
// 文脈がない、もしくは疑似アカウントだった
// 疑似ではないアカウントの一覧
// 疑似アカウントでは検索APIを使えないため、IDが分からない
if(! SavedAccount.hasRealAccount()) {
// 疑似アカウントではユーザ情報APIを呼べないし検索APIも使えない
// chrome tab で開くしかない
// 疑似アカウントしか登録されていない
// chrome tab で開く
App1.openCustomTab(activity, url)
} else {
// アカウントを選択して開く
// 疑似ではないアカウントの一覧から選択して開く
AccountPicker.pick(
activity,
bAllowPseudo = false,
@ -418,17 +431,12 @@ object Action_User {
AcctColor.getNickname("$user@$host")
),
accountListArg = makeAccountListNonPseudo(activity, host)
) { ai ->
profileFromUrl(
activity,
pos,
ai,
url
)
}
) { profileFromUrl(activity, pos, it, url) }
}
}
//////////////////////////////////////////////////////////////////////////////////////
// 通報フォームを開く
fun reportForm(
activity : ActMain, access_info : SavedAccount, who : TootAccount, status : TootStatus

View File

@ -13,7 +13,6 @@ typealias EmptyCallback = ()->Unit
typealias TootApiResultCallback = (result : TootApiResult) -> Unit
typealias TootAccountOrNullCallback = (who : TootAccount?) -> Unit
typealias SavedAccountCallback = (ai : SavedAccount) -> Unit

View File

@ -828,5 +828,6 @@
<string name="instance_rules">インスタンスのルール</string>
<string name="terms">プライバシーポリシー</string>
<string name="agree_terms">サービスの規約に同意します</string>
<string name="pseudo_account_cant_get_follow_list">Can\'t read follow list from pseudo account.</string>
</resources>

View File

@ -850,5 +850,6 @@
<string name="email_empty">Please specift the E-mail address.</string>
<string name="password_empty">Please specify the password.</string>
<string name="username_not_need_atmark">The user name must not contains \"@\" or \"/\".</string>
<string name="pseudo_account_cant_get_follow_list">Can\'t read follow list from pseudo account.</string>
</resources>