diff --git a/app/src/main/java/jp/juggler/subwaytooter/api/entity/TootAccount.kt b/app/src/main/java/jp/juggler/subwaytooter/api/entity/TootAccount.kt index fb72bfab..dbac290f 100644 --- a/app/src/main/java/jp/juggler/subwaytooter/api/entity/TootAccount.kt +++ b/app/src/main/java/jp/juggler/subwaytooter/api/entity/TootAccount.kt @@ -138,10 +138,10 @@ open class TootAccount(parser : TootParser, src : JsonObject) { this.apiHost = src.string("host")?.let { Host.parse(it) } ?: parser.apiHost - ?: error("missing host") - + ?: error("missing host") + this.url = "https://${apiHost.ascii}/@$username" - + this.apDomain = apiHost // FIXME apiHostとapDomainが異なる場合はMisskeyだとどうなの…? @Suppress("LeakingThis") @@ -175,7 +175,7 @@ open class TootAccount(parser : TootParser, src : JsonObject) { this.id = EntityId.mayDefault(src.string("id")) - + this.followers_count = src.long("followersCount") ?: - 1L this.following_count = src.long("followingCount") ?: - 1L this.statuses_count = src.long("notesCount") ?: - 1L @@ -264,7 +264,7 @@ open class TootAccount(parser : TootParser, src : JsonObject) { val tmpAcct = src.stringOrThrow("acct") - val(apiHost,apDomain) = findHostFromUrl(tmpAcct, parser.linkHelper, url) + val (apiHost, apDomain) = findHostFromUrl(tmpAcct, parser.linkHelper, url) apiHost ?: error("can't get apiHost from acct or url") apDomain ?: error("can't get apDomain from acct or url") this.apiHost = apiHost @@ -292,7 +292,7 @@ open class TootAccount(parser : TootParser, src : JsonObject) { val tmpAcct = src.stringOrThrow("acct") - val(apiHost,apDomain) = findHostFromUrl(tmpAcct, null, url) + val (apiHost, apDomain) = findHostFromUrl(tmpAcct, null, url) apiHost ?: error("can't get apiHost from acct or url") apDomain ?: error("can't get apDomain from acct or url") this.apiHost = apiHost @@ -317,7 +317,7 @@ open class TootAccount(parser : TootParser, src : JsonObject) { this.id = EntityId.mayDefault(src.string("id")) // MSPはLTLの情報しか持ってないのでacctは常にホスト名部分を持たない - val(apiHost,apDomain) = findHostFromUrl(null,null, url) + val (apiHost, apDomain) = findHostFromUrl(null, null, url) apiHost ?: error("can't get apiHost from acct or url") apDomain ?: error("can't get apDomain from acct or url") @@ -347,6 +347,7 @@ open class TootAccount(parser : TootParser, src : JsonObject) { } class Source(src : JsonObject) { + // デフォルト公開範囲 val privacy : String? @@ -458,7 +459,8 @@ open class TootAccount(parser : TootParser, src : JsonObject) { decodeEmoji = true, emojiMapProfile = profile_emojis, emojiMapCustom = custom_emojis, - unwrapEmojiImageTag = true + unwrapEmojiImageTag = true, + mentionDefaultDomain = apDomain, ).decodeHTML(note) .replaceAllEx(reNoteLineFeed, " ") .trimEx() @@ -486,6 +488,7 @@ open class TootAccount(parser : TootParser, src : JsonObject) { } companion object { + private val log = LogCategory("TootAccount") internal val reWhitespace = "[\\s\\t\\x0d\\x0a]+".asciiPattern() @@ -544,7 +547,7 @@ open class TootAccount(parser : TootParser, src : JsonObject) { // MisskeyのMFMはIDNをサポートしていない private val reMisskeyMentionBase = """@(\w+(?:[\w-]*\w)?)(?:@($reMisskeyHost))?""" .asciiPattern() - + // MFMパース時に使う internal val reMisskeyMentionMFM = """\A$reMisskeyMentionBase""" .asciiPattern() @@ -597,34 +600,37 @@ open class TootAccount(parser : TootParser, src : JsonObject) { } } - - private fun findApDomain(acctArg : String?, linkHelper : LinkHelper?):Host?{ + private fun findApDomain(acctArg : String?, linkHelper : LinkHelper?) : Host? { // acctから調べる if(acctArg != null) { val acct = Acct.parse(acctArg) if(acct.host != null) return acct.host } - + // Acctはnullか、hostを含まない if(linkHelper != null) return linkHelper.apDomain return null } - private fun findApiHost( url:String?):Host?{ + private fun findApiHost(url : String?) : Host? { // URLから調べる // たぶんどんなURLでもauthorityの部分にホスト名が来るだろう(慢心) url.mayUri()?.authority?.notEmpty()?.let { return Host.parse(it) } - + log.e("findApiHost: can't parse host from URL $url") return null } // Tootsearch用。URLやUriを使ってアカウントのインスタンス名を調べる - fun findHostFromUrl(acctArg : String?, linkHelper : LinkHelper?, url : String?) : Pair { - val apDomain = findApDomain(acctArg,linkHelper) + fun findHostFromUrl( + acctArg : String?, + linkHelper : LinkHelper?, + url : String? + ) : Pair { + val apDomain = findApDomain(acctArg, linkHelper) val apiHost = findApiHost(url) - return Pair( apiHost?: apDomain, apDomain ?: apiHost ) + return Pair(apiHost ?: apDomain, apDomain ?: apiHost) } fun parseFields(src : JsonArray?) : ArrayList? { diff --git a/app/src/main/java/jp/juggler/subwaytooter/api/entity/TootAccountRef.kt b/app/src/main/java/jp/juggler/subwaytooter/api/entity/TootAccountRef.kt index f37e6c1c..b6a056d1 100644 --- a/app/src/main/java/jp/juggler/subwaytooter/api/entity/TootAccountRef.kt +++ b/app/src/main/java/jp/juggler/subwaytooter/api/entity/TootAccountRef.kt @@ -26,7 +26,8 @@ class TootAccountRef(parser: TootParser, account:TootAccount) : TimelineItem() { decodeEmoji = true, emojiMapProfile = account.profile_emojis, emojiMapCustom = account.custom_emojis, - unwrapEmojiImageTag = true + unwrapEmojiImageTag = true, + mentionDefaultDomain = account.apDomain, ).decodeHTML(account.note) } diff --git a/app/src/main/java/jp/juggler/subwaytooter/util/DecodeOptions.kt b/app/src/main/java/jp/juggler/subwaytooter/util/DecodeOptions.kt index 3ccab06c..b13d1b39 100644 --- a/app/src/main/java/jp/juggler/subwaytooter/util/DecodeOptions.kt +++ b/app/src/main/java/jp/juggler/subwaytooter/util/DecodeOptions.kt @@ -4,10 +4,7 @@ import android.content.Context import android.text.Spannable import android.text.SpannableStringBuilder import android.text.style.ReplacementSpan -import jp.juggler.subwaytooter.api.entity.CustomEmoji -import jp.juggler.subwaytooter.api.entity.NicoProfileEmoji -import jp.juggler.subwaytooter.api.entity.TootAttachmentLike -import jp.juggler.subwaytooter.api.entity.TootMention +import jp.juggler.subwaytooter.api.entity.* import jp.juggler.subwaytooter.table.HighlightWord import jp.juggler.util.WordTrieTree import java.util.* @@ -27,7 +24,9 @@ class DecodeOptions( var enlargeEmoji : Float = 1f, var forceHtml : Boolean = false, // force use HTML instead of Misskey Markdown var mentionFullAcct : Boolean = false, - var mentions : ArrayList? = null + var mentions : ArrayList? = null, + // Account.note などmentionsがない状況でメンションリンクをfull acct化するにはアカウント等からapDomainを補う必要がある + var mentionDefaultDomain : Host? = null, ) { internal fun isMediaAttachment(url : String?) : Boolean { diff --git a/app/src/main/java/jp/juggler/subwaytooter/util/HTMLDecoder.kt b/app/src/main/java/jp/juggler/subwaytooter/util/HTMLDecoder.kt index 0957c3b0..e3c90acb 100644 --- a/app/src/main/java/jp/juggler/subwaytooter/util/HTMLDecoder.kt +++ b/app/src/main/java/jp/juggler/subwaytooter/util/HTMLDecoder.kt @@ -607,8 +607,15 @@ object HTMLDecoder { // Account.note does not have mentions metadata. // fallback to resolve acct by mention URL. - val rawAcct = mention?.acct ?: Acct.parse(originalCaption.toString().substring(1)) - val fullAcct = getFullAcctOrNull(options.linkHelper, rawAcct, href) + val rawAcct = mention?.acct + ?: Acct.parse(originalCaption.toString().substring(1)) + + val fullAcct = getFullAcctOrNull( + options.linkHelper, + rawAcct, + href, + mentionDefaultDomain = options.mentionDefaultDomain + ) if(fullAcct != null) { diff --git a/app/src/main/java/jp/juggler/subwaytooter/util/LinkHelper.kt b/app/src/main/java/jp/juggler/subwaytooter/util/LinkHelper.kt index fbd974b9..f25eab84 100644 --- a/app/src/main/java/jp/juggler/subwaytooter/util/LinkHelper.kt +++ b/app/src/main/java/jp/juggler/subwaytooter/util/LinkHelper.kt @@ -3,8 +3,10 @@ package jp.juggler.subwaytooter.util import jp.juggler.subwaytooter.api.entity.Acct import jp.juggler.subwaytooter.api.entity.Host import jp.juggler.subwaytooter.api.entity.TootAccount +import jp.juggler.subwaytooter.api.entity.TootMention import jp.juggler.subwaytooter.table.SavedAccount import jp.juggler.util.groupEx +import java.util.ArrayList interface LinkHelper { @@ -104,16 +106,21 @@ fun getFullAcctOrNull( fun getFullAcctOrNull( linkHelper : LinkHelper?, src : Acct, - url : String + url : String, + mentionDefaultDomain: Host? = null ) : Acct? { // 既にFull Acctだった if(src.host != null) return src - val apDomain = linkHelper?.apDomain + // Account.noteなどメンション情報が含まれない場合、デフォルトのドメインは投稿者のドメインである + if(mentionDefaultDomain!=null){ + return src.followHost( mentionDefaultDomain) + } // トゥート検索等でないならアクセス元ホストを補って良いはず - if(linkHelper is SavedAccount && ! linkHelper.isNA && apDomain != null) { + val apDomain = linkHelper?.apDomain + if(apDomain != null && linkHelper is SavedAccount && ! linkHelper.isNA ) { return Acct.parse(src.username, apDomain) } diff --git a/app/src/main/java/jp/juggler/subwaytooter/util/MisskeyMarkdownDecoder.kt b/app/src/main/java/jp/juggler/subwaytooter/util/MisskeyMarkdownDecoder.kt index f17836c8..e7ba8314 100644 --- a/app/src/main/java/jp/juggler/subwaytooter/util/MisskeyMarkdownDecoder.kt +++ b/app/src/main/java/jp/juggler/subwaytooter/util/MisskeyMarkdownDecoder.kt @@ -831,6 +831,7 @@ object MisskeyMarkdownDecoder { ) { // ユーザが記述したacct val rawAcct = Acct.parse(username, strHost) + .followHost(options.mentionDefaultDomain) val linkHelper = linkHelper if(linkHelper == null) { diff --git a/app/src/main/java/jp/juggler/subwaytooter/util/TootTextEncoder.kt b/app/src/main/java/jp/juggler/subwaytooter/util/TootTextEncoder.kt index 31fb7ba7..e98e3b76 100644 --- a/app/src/main/java/jp/juggler/subwaytooter/util/TootTextEncoder.kt +++ b/app/src/main/java/jp/juggler/subwaytooter/util/TootTextEncoder.kt @@ -11,6 +11,7 @@ import jp.juggler.subwaytooter.table.SavedAccount import java.util.* object TootTextEncoder { + private fun StringBuilder.addAfterLine(text : CharSequence) { if(isNotEmpty() && this[length - 1] != '\n') { append('\n') @@ -268,7 +269,13 @@ object TootTextEncoder { sb.addAfterLine("\n") - sb.append(DecodeOptions(context, access_info).decodeHTML(who.note)) + sb.append( + DecodeOptions( + context, + access_info, + mentionDefaultDomain = who.apDomain + ).decodeHTML(who.note) + ) sb.addAfterLine("\n") @@ -294,7 +301,7 @@ object TootTextEncoder { addHeader(context, sb, R.string.send_header_account_created_at, who.created_at) addHeader(context, sb, R.string.send_header_account_statuses_count, who.statuses_count) - if(! Pref.bpHideFollowCount( App1.getAppState(context).pref)) { + if(! Pref.bpHideFollowCount(App1.getAppState(context).pref)) { addHeader( context, sb,