- Profile metadata のfield name のカスタム絵文字対応
- TimelineItemのアカウント表示でnoteのデコード結果が空の場合は空行を追加しない - fix #108, メンション解読の改善
This commit is contained in:
parent
739e7b78f2
commit
0b692a773f
|
@ -257,11 +257,11 @@ class ActAccountSetting
|
|||
setContentView(R.layout.act_account_setting)
|
||||
App1.initEdgeToEdge(this)
|
||||
|
||||
val root :View = findViewById(R.id.svContent)
|
||||
val root : View = findViewById(R.id.svContent)
|
||||
|
||||
Styler.fixHorizontalPadding(root)
|
||||
|
||||
ActAppSettingChild.setSwitchColor(this,pref,root)
|
||||
|
||||
ActAppSettingChild.setSwitchColor(this, pref, root)
|
||||
|
||||
tvInstance = findViewById(R.id.tvInstance)
|
||||
tvUser = findViewById(R.id.tvUser)
|
||||
|
@ -368,7 +368,7 @@ class ActAccountSetting
|
|||
name_invalidator = NetworkEmojiInvalidator(handler, etDisplayName)
|
||||
note_invalidator = NetworkEmojiInvalidator(handler, etNote)
|
||||
default_text_invalidator = NetworkEmojiInvalidator(handler, etDefaultText)
|
||||
|
||||
|
||||
listFieldNameInvalidator = listEtFieldName.map {
|
||||
NetworkEmojiInvalidator(handler, it)
|
||||
}
|
||||
|
@ -418,7 +418,7 @@ class ActAccountSetting
|
|||
|
||||
override fun afterTextChanged(s : Editable?) {
|
||||
val num = etMaxTootChars.parseInt()
|
||||
if( num != null && num >= 0){
|
||||
if(num != null && num >= 0) {
|
||||
saveUIToData()
|
||||
}
|
||||
}
|
||||
|
@ -426,11 +426,11 @@ class ActAccountSetting
|
|||
|
||||
}
|
||||
|
||||
private fun EditText.parseInt():Int?{
|
||||
private fun EditText.parseInt() : Int? {
|
||||
val sv = this.text?.toString() ?: return null
|
||||
return try{
|
||||
Integer.parseInt(sv,10)
|
||||
}catch(ex:Throwable){
|
||||
return try {
|
||||
Integer.parseInt(sv, 10)
|
||||
} catch(ex : Throwable) {
|
||||
null
|
||||
}
|
||||
}
|
||||
|
@ -472,7 +472,7 @@ class ActAccountSetting
|
|||
|
||||
etDefaultText.setText(a.default_text)
|
||||
etMaxTootChars.setText(a.max_toot_chars.toString())
|
||||
|
||||
|
||||
loading = false
|
||||
|
||||
val enabled = ! a.isPseudo
|
||||
|
@ -543,14 +543,14 @@ class ActAccountSetting
|
|||
account.confirm_unfavourite = cbConfirmUnfavourite.isChecked
|
||||
account.confirm_post = cbConfirmToot.isChecked
|
||||
account.default_text = etDefaultText.text.toString()
|
||||
|
||||
|
||||
val num = etMaxTootChars.parseInt()
|
||||
account.max_toot_chars = if( num != null && num >= 0){
|
||||
account.max_toot_chars = if(num != null && num >= 0) {
|
||||
num
|
||||
}else{
|
||||
} else {
|
||||
0
|
||||
}
|
||||
|
||||
|
||||
account.saveSetting()
|
||||
|
||||
}
|
||||
|
@ -677,7 +677,7 @@ class ActAccountSetting
|
|||
var bChanged = false
|
||||
try {
|
||||
loading = true
|
||||
|
||||
|
||||
val tmpVisibility =
|
||||
TootVisibility.parseMastodon(json.parseString("posting:default:visibility"))
|
||||
if(tmpVisibility != null) {
|
||||
|
@ -953,12 +953,6 @@ class ActAccountSetting
|
|||
emojiMapProfile = src.profile_emojis,
|
||||
emojiMapCustom = src.custom_emojis
|
||||
)
|
||||
// fieldsのnameにはカスタム絵文字が適用されない
|
||||
val decodeOptionsNoCustomEmoji = DecodeOptions(
|
||||
context = this@ActAccountSetting,
|
||||
linkHelper = account,
|
||||
emojiMapProfile = src.profile_emojis
|
||||
)
|
||||
|
||||
val display_name = src.display_name
|
||||
val name = decodeOptions.decodeEmoji(display_name)
|
||||
|
@ -993,7 +987,10 @@ class ActAccountSetting
|
|||
if(src.source?.fields != null) {
|
||||
val fields = src.source.fields
|
||||
listEtFieldName.forEachIndexed { i, et ->
|
||||
val text = decodeOptionsNoCustomEmoji.decodeEmoji(
|
||||
// いつからかfields name にもカスタム絵文字が使えるようになった
|
||||
// https://github.com/tootsuite/mastodon/pull/11350
|
||||
// しかし
|
||||
val text = decodeOptions.decodeEmoji(
|
||||
when {
|
||||
i >= fields.size -> ""
|
||||
else -> fields[i].name
|
||||
|
@ -1022,7 +1019,9 @@ class ActAccountSetting
|
|||
val fields = src.fields
|
||||
|
||||
listEtFieldName.forEachIndexed { i, et ->
|
||||
val text = decodeOptionsNoCustomEmoji.decodeEmoji(
|
||||
// いつからかfields name にもカスタム絵文字が使えるようになった
|
||||
// https://github.com/tootsuite/mastodon/pull/11350
|
||||
val text = decodeOptions.decodeEmoji(
|
||||
when {
|
||||
fields == null || i >= fields.size -> ""
|
||||
else -> fields[i].name
|
||||
|
@ -1576,11 +1575,13 @@ class ActAccountSetting
|
|||
|
||||
}
|
||||
|
||||
@Suppress("DEPRECATION")
|
||||
progress.isIndeterminate = true
|
||||
|
||||
@Suppress("DEPRECATION")
|
||||
progress.setMessage("preparing image…")
|
||||
progress.setOnCancelListener {
|
||||
task.cancel(true)
|
||||
}
|
||||
|
||||
progress.setOnCancelListener { task.cancel(true) }
|
||||
progress.show()
|
||||
|
||||
task.executeOnExecutor(App1.task_executor)
|
||||
|
|
|
@ -844,7 +844,11 @@ class ActPost : AppCompatActivity(),
|
|||
|
||||
// 再編集の場合はdefault_textは反映されない
|
||||
|
||||
val decodeOptions = DecodeOptions(this, mentionFullAcct = true)
|
||||
val decodeOptions = DecodeOptions(
|
||||
this,
|
||||
mentionFullAcct = true,
|
||||
mentions = base_status.mentions
|
||||
)
|
||||
|
||||
var text : CharSequence = if(account.isMisskey) {
|
||||
base_status.content ?: ""
|
||||
|
@ -862,12 +866,14 @@ class ActPost : AppCompatActivity(),
|
|||
val src_enquete = base_status.enquete
|
||||
val src_items = src_enquete?.items
|
||||
when {
|
||||
src_items == null ->{
|
||||
src_items == null -> {
|
||||
|
||||
}
|
||||
|
||||
src_enquete.pollType == TootPollsType.FriendsNico && src_enquete.type != TootPolls.TYPE_ENQUETE -> {
|
||||
// フレニコAPIのアンケート結果は再編集の対象外
|
||||
}
|
||||
|
||||
else -> {
|
||||
spEnquete.setSelection(
|
||||
if(src_enquete.pollType == TootPollsType.FriendsNico) {
|
||||
|
@ -888,6 +894,7 @@ class ActPost : AppCompatActivity(),
|
|||
src_index == src_items.size - 1 && choice.text == "\uD83E\uDD14" -> {
|
||||
// :thinking_face: は再現しない
|
||||
}
|
||||
|
||||
else -> {
|
||||
et.setText(decodeOptions.decodeEmoji(choice.text))
|
||||
++ src_index
|
||||
|
@ -1590,6 +1597,7 @@ class ActPost : AppCompatActivity(),
|
|||
pa.attachment?.isAudio == true -> {
|
||||
// can't set focus
|
||||
}
|
||||
|
||||
else -> a.addAction(getString(R.string.set_focus_point)) {
|
||||
openFocusPoint(pa)
|
||||
}
|
||||
|
|
|
@ -1156,7 +1156,7 @@ internal class ItemViewHolder(
|
|||
|
||||
setAcct(tvFollowerAcct, access_info.getFullAcct(who), who.acct)
|
||||
|
||||
who.setLastStatusText(tvLastStatusAt,access_info)
|
||||
who.setAccountExtra(tvLastStatusAt,access_info)
|
||||
|
||||
|
||||
val relation = UserRelation.load(access_info.db_id, who.id)
|
||||
|
|
|
@ -216,7 +216,7 @@ internal class ViewHolderHeaderProfile(
|
|||
tvCreated.text =
|
||||
TootStatus.formatTime(tvCreated.context, (whoDetail ?: who).time_created_at, true)
|
||||
|
||||
who.setLastStatusText(tvLastStatusAt,access_info,fromProfileHeader = true)
|
||||
who.setAccountExtra(tvLastStatusAt,access_info,fromProfileHeader = true)
|
||||
|
||||
|
||||
ivBackground.setImageUrl(
|
||||
|
@ -338,17 +338,10 @@ internal class ViewHolderHeaderProfile(
|
|||
|
||||
llFields.visibility = View.VISIBLE
|
||||
|
||||
// fieldsのnameにはカスタム絵文字が適用されない
|
||||
val nameDecodeOptions = DecodeOptions(
|
||||
context = activity,
|
||||
decodeEmoji = true,
|
||||
linkHelper = access_info,
|
||||
short = true,
|
||||
emojiMapProfile = who.profile_emojis
|
||||
)
|
||||
|
||||
// valueはMisskeyならMFM、MastodonならHTML
|
||||
val valueDecodeOptions = DecodeOptions(
|
||||
// fieldsのnameにはカスタム絵文字が適用されるようになった
|
||||
// https://github.com/tootsuite/mastodon/pull/11350
|
||||
// fieldsのvalueはMisskeyならMFM、MastodonならHTML
|
||||
val fieldDecodeOptions = DecodeOptions(
|
||||
context = activity,
|
||||
decodeEmoji = true,
|
||||
linkHelper = access_info,
|
||||
|
@ -368,7 +361,7 @@ internal class ViewHolderHeaderProfile(
|
|||
LinearLayout.LayoutParams.MATCH_PARENT,
|
||||
LinearLayout.LayoutParams.WRAP_CONTENT
|
||||
)
|
||||
val nameText = nameDecodeOptions.decodeEmoji(item.name)
|
||||
val nameText = fieldDecodeOptions.decodeEmoji(item.name)
|
||||
val nameInvalidator = NetworkEmojiInvalidator(activity.handler, nameView)
|
||||
nameInvalidator.register(nameText)
|
||||
|
||||
|
@ -387,7 +380,7 @@ internal class ViewHolderHeaderProfile(
|
|||
LinearLayout.LayoutParams.WRAP_CONTENT
|
||||
)
|
||||
|
||||
val valueText = valueDecodeOptions.decodeHTML(item.value)
|
||||
val valueText = fieldDecodeOptions.decodeHTML(item.value)
|
||||
if(item.verified_at > 0L) {
|
||||
valueText.append('\n')
|
||||
|
||||
|
|
|
@ -26,11 +26,9 @@ internal class ViewHolderHeaderSearch(
|
|||
override fun bindData(column : Column) {
|
||||
super.bindData(column)
|
||||
|
||||
val html = column.getHeaderDesc() ?: ""
|
||||
val sv = DecodeOptions(activity, access_info,decodeEmoji = true).decodeHTML( html)
|
||||
|
||||
tvSearchDesc.text = sv
|
||||
tvSearchDesc.textColor = column.getContentColor()
|
||||
tvSearchDesc.text = DecodeOptions(activity, access_info, decodeEmoji = true)
|
||||
.decodeHTML(column.getHeaderDesc() ?: "")
|
||||
}
|
||||
|
||||
override fun onViewRecycled() {
|
||||
|
|
|
@ -378,13 +378,13 @@ open class TootAccount(parser : TootParser, src : JSONObject) {
|
|||
}
|
||||
}
|
||||
|
||||
fun setLastStatusText(
|
||||
tvLastStatusAt : TextView,
|
||||
fun setAccountExtra(
|
||||
tv : TextView,
|
||||
accessInfo : SavedAccount,
|
||||
fromProfileHeader : Boolean = false
|
||||
) {
|
||||
val pref = App1.pref
|
||||
val context = tvLastStatusAt.context
|
||||
val context = tv.context
|
||||
|
||||
var sb : SpannableStringBuilder? = null
|
||||
fun prepareSb() = sb?.apply { append('\n') } ?: SpannableStringBuilder().also { sb = it }
|
||||
|
@ -416,19 +416,21 @@ open class TootAccount(parser : TootParser, src : JSONObject) {
|
|||
.decodeHTML(note)
|
||||
.replaceAllEx(reNoteLineFeed, " ")
|
||||
.trimEx()
|
||||
prepareSb().append(
|
||||
if(decodedNote is SpannableStringBuilder && decodedNote.length > 200) {
|
||||
decodedNote.replace(200, decodedNote.length, "…")
|
||||
} else {
|
||||
decodedNote
|
||||
}
|
||||
)
|
||||
if(decodedNote.isNotBlank()) {
|
||||
prepareSb().append(
|
||||
if(decodedNote is SpannableStringBuilder && decodedNote.length > 200) {
|
||||
decodedNote.replace(200, decodedNote.length, "…")
|
||||
} else {
|
||||
decodedNote
|
||||
}
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if(vg(tvLastStatusAt, sb != null)) {
|
||||
tvLastStatusAt.text = sb
|
||||
tvLastStatusAt.movementMethod = MyLinkMovementMethod
|
||||
if(vg(tv, sb != null)) {
|
||||
tv.text = sb
|
||||
tv.movementMethod = MyLinkMovementMethod
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -449,28 +451,37 @@ open class TootAccount(parser : TootParser, src : JSONObject) {
|
|||
internal val reAccountUrl : Pattern =
|
||||
Pattern.compile("""\Ahttps://(\w[\w.-]*\w)/@(\w+[\w-]*)(?:@(\w[\w.-]*\w))?(?=\z|[?#])""")
|
||||
|
||||
// host,user
|
||||
internal val reAccountUrl2 : Pattern =
|
||||
Pattern.compile("""\Ahttps://(\w[\w.-]*\w)/users/(\w|\w+[\w-]*\w)(?=\z|[?#])""")
|
||||
|
||||
fun getAcctFromUrl(url : String?) : String? {
|
||||
|
||||
url ?: return null
|
||||
|
||||
val m = reAccountUrl.matcher(url)
|
||||
return if(m.find()) {
|
||||
val host = m.group(1)
|
||||
val user = m.group(2).decodePercent()
|
||||
var m = reAccountUrl.matcher(url)
|
||||
if(m.find()) {
|
||||
val host = m.groupOrNull(1)
|
||||
val user = m.groupOrNull(2)?.decodePercent()
|
||||
val instance = m.groupOrNull(3)?.decodePercent()
|
||||
if(instance?.isNotEmpty() == true) {
|
||||
return if(instance?.isNotEmpty() == true) {
|
||||
"$user@$instance"
|
||||
} else {
|
||||
"$user@$host"
|
||||
}
|
||||
} else {
|
||||
null
|
||||
}
|
||||
|
||||
m = reAccountUrl2.matcher(url)
|
||||
if(m.find()) {
|
||||
val host = m.groupOrNull(1)
|
||||
val user = m.groupOrNull(2)?.decodePercent()
|
||||
|
||||
return "$user@$host"
|
||||
}
|
||||
|
||||
return null
|
||||
}
|
||||
|
||||
// host,user
|
||||
internal val reAccountUrl2 : Pattern =
|
||||
Pattern.compile("""\Ahttps://(\w[\w.-]*\w)/users/(\w|\w+[\w-]*\w)(?=\z|[?#])""")
|
||||
|
||||
private fun parseSource(src : JSONObject?) : Source? {
|
||||
src ?: return null
|
||||
|
|
|
@ -107,7 +107,8 @@ class TootPolls private constructor(
|
|||
attachmentList = list_attachment,
|
||||
linkTag = status,
|
||||
emojiMapCustom = status.custom_emojis,
|
||||
emojiMapProfile = status.profile_emojis
|
||||
emojiMapProfile = status.profile_emojis,
|
||||
mentions = status.mentions
|
||||
).decodeHTML(this.question ?: "?")
|
||||
|
||||
}
|
||||
|
@ -124,7 +125,8 @@ class TootPolls private constructor(
|
|||
attachmentList = list_attachment,
|
||||
linkTag = status,
|
||||
emojiMapCustom = status.custom_emojis,
|
||||
emojiMapProfile = status.profile_emojis
|
||||
emojiMapProfile = status.profile_emojis,
|
||||
mentions = status.mentions
|
||||
).decodeHTML(this.question ?: "?")
|
||||
|
||||
this.items = parseChoiceListMastodon(
|
||||
|
@ -178,7 +180,8 @@ class TootPolls private constructor(
|
|||
attachmentList = list_attachment,
|
||||
linkTag = status,
|
||||
emojiMapCustom = status.custom_emojis,
|
||||
emojiMapProfile = status.profile_emojis
|
||||
emojiMapProfile = status.profile_emojis,
|
||||
mentions = status.mentions
|
||||
).decodeHTML(this.question ?: "?")
|
||||
|
||||
this.items = parseChoiceListFriendsNico(
|
||||
|
|
|
@ -280,7 +280,8 @@ class TootStatus(parser : TootParser, src : JSONObject) : TimelineItem() {
|
|||
emojiMapCustom = custom_emojis,
|
||||
emojiMapProfile = profile_emojis,
|
||||
attachmentList = media_attachments,
|
||||
highlightTrie = parser.highlightTrie
|
||||
highlightTrie = parser.highlightTrie,
|
||||
mentions = null // MisskeyはMFMをパースし終わるまでメンションが分からない
|
||||
)
|
||||
|
||||
this.decoded_content = options.decodeHTML(content)
|
||||
|
@ -290,14 +291,9 @@ class TootStatus(parser : TootParser, src : JSONObject) : TimelineItem() {
|
|||
}
|
||||
|
||||
// Markdownのデコード結果からmentionsを読むのだった
|
||||
this.mentions =
|
||||
(decoded_content as? MisskeyMarkdownDecoder.SpannableStringBuilderEx)?.mentions
|
||||
this.decoded_mentions = HTMLDecoder.decodeMentions(
|
||||
parser.linkHelper,
|
||||
this.mentions,
|
||||
this
|
||||
) ?: EMPTY_SPANNABLE
|
||||
|
||||
val mentions1 = (decoded_content as? MisskeyMarkdownDecoder.SpannableStringBuilderEx)?.mentions
|
||||
|
||||
|
||||
val sv = src.parseString("cw")?.cleanCW()
|
||||
this.spoiler_text = when {
|
||||
sv == null -> "" // CWなし
|
||||
|
@ -305,6 +301,7 @@ class TootStatus(parser : TootParser, src : JSONObject) : TimelineItem() {
|
|||
else -> sv
|
||||
}
|
||||
|
||||
// ハイライト検出のためにDecodeOptionsを作り直す?
|
||||
options = DecodeOptions(
|
||||
parser.context,
|
||||
parser.linkHelper,
|
||||
|
@ -313,7 +310,8 @@ class TootStatus(parser : TootParser, src : JSONObject) : TimelineItem() {
|
|||
emojiMapCustom = custom_emojis,
|
||||
emojiMapProfile = profile_emojis,
|
||||
attachmentList = media_attachments,
|
||||
highlightTrie = parser.highlightTrie
|
||||
highlightTrie = parser.highlightTrie,
|
||||
mentions = null // MisskeyはMFMをパースし終わるまでメンションが分からない
|
||||
)
|
||||
this.decoded_spoiler_text = options.decodeHTML(spoiler_text)
|
||||
|
||||
|
@ -321,6 +319,15 @@ class TootStatus(parser : TootParser, src : JSONObject) : TimelineItem() {
|
|||
if(options.highlight_sound != null && this.highlight_sound == null) {
|
||||
this.highlight_sound = options.highlight_sound
|
||||
}
|
||||
|
||||
val mentions2 = (decoded_spoiler_text as? MisskeyMarkdownDecoder.SpannableStringBuilderEx)?.mentions
|
||||
|
||||
this.mentions = mergeMentions(mentions1,mentions2)
|
||||
this.decoded_mentions = HTMLDecoder.decodeMentions(
|
||||
parser.linkHelper,
|
||||
this.mentions,
|
||||
this
|
||||
) ?: EMPTY_SPANNABLE
|
||||
|
||||
// contentを読んだ後にアンケートのデコード
|
||||
this.enquete = TootPolls.parse(
|
||||
|
@ -410,7 +417,7 @@ class TootStatus(parser : TootParser, src : JSONObject) : TimelineItem() {
|
|||
this.uri = src.parseString("uri") ?: error("missing uri")
|
||||
this.id = findStatusIdFromUri(uri, url) ?: EntityId.DEFAULT
|
||||
|
||||
this.time_created_at = TootStatus.parseTime(this.created_at)
|
||||
this.time_created_at = parseTime(this.created_at)
|
||||
this.media_attachments = parseListOrNull(
|
||||
::TootAttachment,
|
||||
parser,
|
||||
|
@ -470,7 +477,8 @@ class TootStatus(parser : TootParser, src : JSONObject) : TimelineItem() {
|
|||
emojiMapCustom = custom_emojis,
|
||||
emojiMapProfile = profile_emojis,
|
||||
attachmentList = media_attachments,
|
||||
highlightTrie = parser.highlightTrie
|
||||
highlightTrie = parser.highlightTrie,
|
||||
mentions = mentions
|
||||
)
|
||||
|
||||
this.decoded_content = options.decodeHTML(content)
|
||||
|
@ -486,11 +494,13 @@ class TootStatus(parser : TootParser, src : JSONObject) : TimelineItem() {
|
|||
else -> sv
|
||||
}
|
||||
|
||||
// ハイライト検出のためにDecodeOptionsを作り直す?
|
||||
options = DecodeOptions(
|
||||
parser.context,
|
||||
emojiMapCustom = custom_emojis,
|
||||
emojiMapProfile = profile_emojis,
|
||||
highlightTrie = parser.highlightTrie
|
||||
highlightTrie = parser.highlightTrie,
|
||||
mentions = mentions
|
||||
)
|
||||
|
||||
this.decoded_spoiler_text = options.decodeEmoji(spoiler_text)
|
||||
|
@ -533,6 +543,18 @@ class TootStatus(parser : TootParser, src : JSONObject) : TimelineItem() {
|
|||
}
|
||||
}
|
||||
|
||||
private fun mergeMentions(
|
||||
mentions1 : java.util.ArrayList<TootMention>?,
|
||||
mentions2 : java.util.ArrayList<TootMention>?
|
||||
) : java.util.ArrayList<TootMention>? {
|
||||
val size = (mentions1?.size?:0) + (mentions2?.size?:0)
|
||||
if( size == 0) return null
|
||||
val dst = ArrayList<TootMention>(size)
|
||||
if(mentions1!=null) dst.addAll(mentions1)
|
||||
if(mentions2!=null) dst.addAll(mentions2)
|
||||
return dst
|
||||
}
|
||||
|
||||
///////////////////////////////////////////////////
|
||||
// ユーティリティ
|
||||
|
||||
|
@ -545,14 +567,14 @@ class TootStatus(parser : TootParser, src : JSONObject) : TimelineItem() {
|
|||
fun checkMuted() : Boolean {
|
||||
|
||||
// app mute
|
||||
val muted_app = TootStatus.muted_app
|
||||
val muted_app = muted_app
|
||||
if(muted_app != null) {
|
||||
val name = application?.name
|
||||
if(name != null && muted_app.contains(name)) return true
|
||||
}
|
||||
|
||||
// word mute
|
||||
val muted_word = TootStatus.muted_word
|
||||
val muted_word = muted_word
|
||||
if(muted_word != null) {
|
||||
if(muted_word.matchShort(decoded_content)) return true
|
||||
if(muted_word.matchShort(decoded_spoiler_text)) return true
|
||||
|
@ -971,15 +993,15 @@ class TootStatus(parser : TootParser, src : JSONObject) : TimelineItem() {
|
|||
if(uri?.isNotEmpty() == true) {
|
||||
// https://friends.nico/users/(who)/statuses/(status_id)
|
||||
var m = reTootUriAP1.matcher(uri)
|
||||
if(m.find()) return EntityId(m.group(2))
|
||||
if(m.find()) return EntityId(m.group(2)!!)
|
||||
|
||||
// https://server/@user/(status_id)
|
||||
m = reTootUriAP2.matcher(uri)
|
||||
if(m.find()) return EntityId(m.group(2))
|
||||
if(m.find()) return EntityId(m.group(2)!!)
|
||||
|
||||
// https://misskey.xyz/notes/5b802367744b650030a13640
|
||||
m = reStatusPageMisskey.matcher(uri)
|
||||
if(m.find()) return EntityId(m.group(2))
|
||||
if(m.find()) return EntityId(m.group(2)!!)
|
||||
|
||||
// https://pl.at7s.me/objects/feeb4399-cd7a-48c8-8999-b58868daaf43
|
||||
// tootsearch中の投稿からIDを読めるようにしたい
|
||||
|
@ -989,11 +1011,11 @@ class TootStatus(parser : TootParser, src : JSONObject) : TimelineItem() {
|
|||
|
||||
// https://pl.telteltel.com/notice/9fGFPu4LAgbrTby0xc
|
||||
m = reStatusPageNotice.matcher(uri)
|
||||
if(m.find()) return EntityId(m.group(2))
|
||||
if(m.find()) return EntityId(m.group(2)!!)
|
||||
|
||||
// tag:mstdn.osaka,2017-12-19:objectId=5672321:objectType=Status
|
||||
m = reTootUriOS.matcher(uri)
|
||||
if(m.find()) return EntityId(m.group(2))
|
||||
if(m.find()) return EntityId(m.group(2)!!)
|
||||
|
||||
log.w("can't parse status uri: $uri")
|
||||
}
|
||||
|
@ -1002,15 +1024,15 @@ class TootStatus(parser : TootParser, src : JSONObject) : TimelineItem() {
|
|||
|
||||
// https://friends.nico/users/(who)/statuses/(status_id)
|
||||
var m = reTootUriAP1.matcher(url)
|
||||
if(m.find()) return EntityId(m.group(2))
|
||||
if(m.find()) return EntityId(m.group(2)!!)
|
||||
|
||||
// https://friends.nico/@(who)/(status_id)
|
||||
m = reTootUriAP2.matcher(url)
|
||||
if(m.find()) return EntityId(m.group(2))
|
||||
if(m.find()) return EntityId(m.group(2)!!)
|
||||
|
||||
// https://misskey.xyz/notes/5b802367744b650030a13640
|
||||
m = reStatusPageMisskey.matcher(url)
|
||||
if(m.find()) return EntityId(m.group(2))
|
||||
if(m.find()) return EntityId(m.group(2)!!)
|
||||
|
||||
// https://pl.at7s.me/objects/feeb4399-cd7a-48c8-8999-b58868daaf43
|
||||
// tootsearch中の投稿からIDを読めるようにしたい
|
||||
|
@ -1020,7 +1042,7 @@ class TootStatus(parser : TootParser, src : JSONObject) : TimelineItem() {
|
|||
|
||||
// https://pl.telteltel.com/notice/9fGFPu4LAgbrTby0xc
|
||||
m = reStatusPageNotice.matcher(url)
|
||||
if(m.find()) return EntityId(m.group(2))
|
||||
if(m.find()) return EntityId(m.group(2)!!)
|
||||
|
||||
|
||||
log.w("can't parse status URL: $url")
|
||||
|
|
|
@ -5,6 +5,7 @@ import android.text.Spannable
|
|||
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.table.HighlightWord
|
||||
import jp.juggler.util.WordTrieTree
|
||||
import java.util.*
|
||||
|
@ -22,7 +23,8 @@ class DecodeOptions(
|
|||
var unwrapEmojiImageTag : Boolean = false,
|
||||
var enlargeCustomEmoji : Float = 1f,
|
||||
var forceHtml : Boolean = false, // force use HTML instead of Misskey Markdown
|
||||
var mentionFullAcct : Boolean = false
|
||||
var mentionFullAcct : Boolean = false,
|
||||
var mentions: ArrayList<TootMention>? = null
|
||||
) {
|
||||
|
||||
internal fun isMediaAttachment(url : String?) : Boolean {
|
||||
|
|
|
@ -435,12 +435,15 @@ object HTMLDecoder {
|
|||
for(item in src_list) {
|
||||
if(sb.isNotEmpty()) sb.append(" ")
|
||||
val start = sb.length
|
||||
|
||||
sb.append('@')
|
||||
if(Pref.bpMentionFullAcct(App1.pref)) {
|
||||
sb.append(linkHelper.getFullAcct(item.acct))
|
||||
} else {
|
||||
sb.append(item.acct)
|
||||
}
|
||||
.append(
|
||||
if(Pref.bpMentionFullAcct(App1.pref)) {
|
||||
linkHelper.getFullAcct(item.acct)
|
||||
} else {
|
||||
item.acct
|
||||
}
|
||||
)
|
||||
val end = sb.length
|
||||
val url = item.url
|
||||
if(end > start) {
|
||||
|
@ -510,6 +513,20 @@ object HTMLDecoder {
|
|||
'@' -> {
|
||||
// @mention
|
||||
if(options.mentionFullAcct || Pref.bpMentionFullAcct(App1.pref)) {
|
||||
|
||||
// https://github.com/tateisu/SubwayTooter/issues/108
|
||||
// check mentions to skip getAcctFromUrl
|
||||
val mentions = options.mentions
|
||||
if( mentions != null){
|
||||
for( it in mentions){
|
||||
if( it.url == href ){
|
||||
val acct = it.acct
|
||||
if( acct.contains('@')) return "@$acct"
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Account.note does not have mentions metadata. we can't drop resolving by mention URL.
|
||||
val acct = TootAccount.getAcctFromUrl(href)
|
||||
if(acct != null) return "@$acct"
|
||||
}
|
||||
|
|
|
@ -63,7 +63,7 @@ object TootTextEncoder {
|
|||
sb.addAfterLine( "\n")
|
||||
|
||||
intent.putExtra(ActText.EXTRA_CONTENT_START, sb.length)
|
||||
sb.append(DecodeOptions(context, access_info).decodeHTML(status.content))
|
||||
sb.append(DecodeOptions(context, access_info,mentions = status.mentions).decodeHTML(status.content))
|
||||
|
||||
encodePolls(sb,context,status)
|
||||
|
||||
|
@ -90,7 +90,7 @@ object TootTextEncoder {
|
|||
sb.append(sv).append("\n\n")
|
||||
}
|
||||
|
||||
sb.append(DecodeOptions(context, access_info).decodeHTML(status.content))
|
||||
sb.append(DecodeOptions(context, access_info,mentions=status.mentions).decodeHTML(status.content))
|
||||
|
||||
encodePolls(sb,context,status)
|
||||
|
||||
|
|
|
@ -327,7 +327,7 @@ fun Bundle.parseString(key : String) : String? {
|
|||
// Pattern
|
||||
|
||||
fun Matcher.groupOrNull(g : Int) : String? =
|
||||
if(groupCount() >= g) {
|
||||
if(g in 0 until groupCount() ) {
|
||||
group(g)
|
||||
} else {
|
||||
null
|
||||
|
|
Loading…
Reference in New Issue