diff --git a/app/src/main/java/jp/juggler/subwaytooter/ActAccountSetting.kt b/app/src/main/java/jp/juggler/subwaytooter/ActAccountSetting.kt index a21d48be..69b5084b 100644 --- a/app/src/main/java/jp/juggler/subwaytooter/ActAccountSetting.kt +++ b/app/src/main/java/jp/juggler/subwaytooter/ActAccountSetting.kt @@ -542,7 +542,7 @@ class ActAccountSetting : AsyncActivity(), View.OnClickListener, tvUserCustom.backgroundColor = ac.color_bg tvUserCustom.text = ac.nickname tvUserCustom.textColor = ac.color_fg.notZero() - ?: getAttributeColor(R.attr.colorTimeSmall) + ?: attrColor(R.attr.colorTimeSmall) } private fun saveUIToData() { diff --git a/app/src/main/java/jp/juggler/subwaytooter/ActAppSetting.kt b/app/src/main/java/jp/juggler/subwaytooter/ActAppSetting.kt index f643bf50..153e976c 100644 --- a/app/src/main/java/jp/juggler/subwaytooter/ActAppSetting.kt +++ b/app/src/main/java/jp/juggler/subwaytooter/ActAppSetting.kt @@ -373,7 +373,7 @@ class ActAppSetting : AsyncActivity(), ColorPickerDialogListener, View.OnClickLi val margin_tb = dip(6) setMargins(margin_lr, margin_tb, margin_lr, margin_tb) } - setBackgroundColor(context.getAttributeColor(R.attr.colorSettingDivider)) + setBackgroundColor(context.attrColor(R.attr.colorSettingDivider)) }) } diff --git a/app/src/main/java/jp/juggler/subwaytooter/ActColumnList.kt b/app/src/main/java/jp/juggler/subwaytooter/ActColumnList.kt index 94b840fc..63da4b8c 100644 --- a/app/src/main/java/jp/juggler/subwaytooter/ActColumnList.kt +++ b/app/src/main/java/jp/juggler/subwaytooter/ActColumnList.kt @@ -200,7 +200,7 @@ class ActColumnList : AppCompatActivity() { val type = ColumnType.parse(json.optInt(Column.KEY_TYPE)) val acct_color_bg = json.optInt(Column.KEY_COLUMN_ACCESS_COLOR_BG, 0) val acct_color_fg = json.optInt(Column.KEY_COLUMN_ACCESS_COLOR, 0) - .notZero() ?: context.getAttributeColor(R.attr.colorColumnListItemText) + .notZero() ?: context.attrColor(R.attr.colorColumnListItemText) var bOldSelection : Boolean = false fun setOldSelection(b : Boolean) { @@ -274,7 +274,7 @@ class ActColumnList : AppCompatActivity() { clickedView.findViewById(R.id.ivBookmark).visibility dragView.findViewById(R.id.item_layout) - .setBackgroundColor(getAttributeColor(R.attr.list_item_bg_pressed_dragged)) + .setBackgroundColor(attrColor(R.attr.list_item_bg_pressed_dragged)) } } diff --git a/app/src/main/java/jp/juggler/subwaytooter/ActFavMute.kt b/app/src/main/java/jp/juggler/subwaytooter/ActFavMute.kt index 36093556..7773aece 100644 --- a/app/src/main/java/jp/juggler/subwaytooter/ActFavMute.kt +++ b/app/src/main/java/jp/juggler/subwaytooter/ActFavMute.kt @@ -172,7 +172,7 @@ class ActFavMute : AppCompatActivity() { clickedView.findViewById(R.id.tvName).text dragView.findViewById(R.id.item_layout) - .setBackgroundColor(getAttributeColor(R.attr.list_item_bg_pressed_dragged)) + .setBackgroundColor(attrColor(R.attr.list_item_bg_pressed_dragged)) } } diff --git a/app/src/main/java/jp/juggler/subwaytooter/ActHighlightWordEdit.kt b/app/src/main/java/jp/juggler/subwaytooter/ActHighlightWordEdit.kt index 1857d71a..0fd27605 100644 --- a/app/src/main/java/jp/juggler/subwaytooter/ActHighlightWordEdit.kt +++ b/app/src/main/java/jp/juggler/subwaytooter/ActHighlightWordEdit.kt @@ -142,7 +142,7 @@ class ActHighlightWordEdit tvName.text = item.name tvName.setBackgroundColor(item.color_bg) // may 0 tvName.textColor = item.color_fg.notZero() - ?: getAttributeColor(android.R.attr.textColorPrimary) + ?: attrColor(android.R.attr.textColorPrimary) } finally { bBusy = false diff --git a/app/src/main/java/jp/juggler/subwaytooter/ActHighlightWordList.kt b/app/src/main/java/jp/juggler/subwaytooter/ActHighlightWordList.kt index 76747d35..37c566d9 100644 --- a/app/src/main/java/jp/juggler/subwaytooter/ActHighlightWordList.kt +++ b/app/src/main/java/jp/juggler/subwaytooter/ActHighlightWordList.kt @@ -160,7 +160,7 @@ class ActHighlightWordList : AppCompatActivity(), View.OnClickListener { tvName.setBackgroundColor(item.color_bg) tvName.setTextColor( item.color_fg.notZero() - ?: getAttributeColor(android.R.attr.textColorPrimary) + ?: attrColor(android.R.attr.textColorPrimary) ) btnSound.vg(item.sound_type != HighlightWord.SOUND_TYPE_NONE)?.apply { @@ -219,7 +219,7 @@ class ActHighlightWordList : AppCompatActivity(), View.OnClickListener { clickedView.findViewById(R.id.ivSpeech).visibility dragView.findViewById(R.id.item_layout) - .setBackgroundColor(getAttributeColor(R.attr.list_item_bg_pressed_dragged)) + .setBackgroundColor(attrColor(R.attr.list_item_bg_pressed_dragged)) } } diff --git a/app/src/main/java/jp/juggler/subwaytooter/ActLanguageFilter.kt b/app/src/main/java/jp/juggler/subwaytooter/ActLanguageFilter.kt index b8d39463..48f32be8 100644 --- a/app/src/main/java/jp/juggler/subwaytooter/ActLanguageFilter.kt +++ b/app/src/main/java/jp/juggler/subwaytooter/ActLanguageFilter.kt @@ -240,7 +240,7 @@ class ActLanguageFilter : AsyncActivity(), View.OnClickListener { getDesc(item), getString(if(item.allow) R.string.language_show else R.string.language_hide) ) - tv.textColor = getAttributeColor( + tv.textColor = attrColor( when(item.allow) { true -> R.attr.colorContentText false -> R.attr.colorRegexFilterError @@ -373,7 +373,7 @@ class ActLanguageFilter : AsyncActivity(), View.OnClickListener { btnPresets.setEnabledColor( activity, R.drawable.ic_edit, - activity.getAttributeColor(R.attr.colorVectorDrawable), + activity.attrColor(R.attr.colorVectorDrawable), false ) } diff --git a/app/src/main/java/jp/juggler/subwaytooter/ActMain.kt b/app/src/main/java/jp/juggler/subwaytooter/ActMain.kt index 5eac076a..003a3823 100644 --- a/app/src/main/java/jp/juggler/subwaytooter/ActMain.kt +++ b/app/src/main/java/jp/juggler/subwaytooter/ActMain.kt @@ -540,7 +540,7 @@ class ActMain : AsyncActivity(), View.OnClickListener, ItemViewHolder.toot_color_direct_me = Pref.ipTootColorDirectMe(pref) MyClickableSpan.showLinkUnderline = Pref.bpShowLinkUnderline(pref) MyClickableSpan.defaultLinkColor = Pref.ipLinkColor(pref).notZero() - ?: getAttributeColor(R.attr.colorLink) + ?: attrColor(R.attr.colorLink) CustomShare.reloadCache(this, pref) @@ -2316,7 +2316,7 @@ class ActMain : AsyncActivity(), View.OnClickListener, val footer_tab_indicator_color = Pref.ipFooterTabIndicatorColor(pref) val colorColumnStripBackground = footer_tab_bg_color.notZero() - ?: getAttributeColor(R.attr.colorColumnStripBackground) + ?: attrColor(R.attr.colorColumnStripBackground) svColumnStrip.setBackgroundColor(colorColumnStripBackground) llQuickTootBar.setBackgroundColor(colorColumnStripBackground) @@ -2325,7 +2325,7 @@ class ActMain : AsyncActivity(), View.OnClickListener, ?: colorColumnStripBackground val colorButtonFg = footer_button_fg_color.notZero() - ?: getAttributeColor(R.attr.colorRippleEffect) + ?: attrColor(R.attr.colorRippleEffect) btnMenu.backgroundDrawable = getAdaptiveRippleDrawableRound(this, colorButtonBg, colorButtonFg) @@ -2338,7 +2338,7 @@ class ActMain : AsyncActivity(), View.OnClickListener, val csl = ColorStateList.valueOf( footer_button_fg_color.notZero() - ?: getAttributeColor(R.attr.colorVectorDrawable) + ?: attrColor(R.attr.colorVectorDrawable) ) btnToot.imageTintList = csl btnMenu.imageTintList = csl @@ -2351,7 +2351,7 @@ class ActMain : AsyncActivity(), View.OnClickListener, vFooterDivider2.setBackgroundColor(c) llColumnStrip.indicatorColor = footer_tab_indicator_color.notZero() - ?: getAttributeColor(R.attr.colorAccent) + ?: attrColor(R.attr.colorAccent) } ///////////////////////////////////////////////////////////////////////// diff --git a/app/src/main/java/jp/juggler/subwaytooter/ActMutedApp.kt b/app/src/main/java/jp/juggler/subwaytooter/ActMutedApp.kt index 911e9c63..d566d456 100644 --- a/app/src/main/java/jp/juggler/subwaytooter/ActMutedApp.kt +++ b/app/src/main/java/jp/juggler/subwaytooter/ActMutedApp.kt @@ -8,7 +8,7 @@ import android.view.ViewGroup import android.widget.TextView import jp.juggler.subwaytooter.table.MutedApp import jp.juggler.util.LogCategory -import jp.juggler.util.getAttributeColor +import jp.juggler.util.attrColor import java.util.* import com.woxthebox.draglistview.DragItem import com.woxthebox.draglistview.DragItemAdapter @@ -170,7 +170,7 @@ class ActMutedApp : AppCompatActivity() { clickedView.findViewById(R.id.tvName).text dragView.findViewById(R.id.item_layout) - .setBackgroundColor(getAttributeColor(R.attr.list_item_bg_pressed_dragged)) + .setBackgroundColor(attrColor(R.attr.list_item_bg_pressed_dragged)) } } diff --git a/app/src/main/java/jp/juggler/subwaytooter/ActMutedPseudoAccount.kt b/app/src/main/java/jp/juggler/subwaytooter/ActMutedPseudoAccount.kt index bc6457bd..7701c780 100644 --- a/app/src/main/java/jp/juggler/subwaytooter/ActMutedPseudoAccount.kt +++ b/app/src/main/java/jp/juggler/subwaytooter/ActMutedPseudoAccount.kt @@ -13,7 +13,7 @@ import com.woxthebox.draglistview.swipe.ListSwipeHelper import com.woxthebox.draglistview.swipe.ListSwipeItem import jp.juggler.subwaytooter.table.UserRelation import jp.juggler.util.LogCategory -import jp.juggler.util.getAttributeColor +import jp.juggler.util.attrColor import java.util.* class ActMutedPseudoAccount : AppCompatActivity() { @@ -169,7 +169,7 @@ class ActMutedPseudoAccount : AppCompatActivity() { clickedView.findViewById(R.id.tvName).text dragView.findViewById(R.id.item_layout) - .setBackgroundColor(getAttributeColor(R.attr.list_item_bg_pressed_dragged)) + .setBackgroundColor(attrColor(R.attr.list_item_bg_pressed_dragged)) } } diff --git a/app/src/main/java/jp/juggler/subwaytooter/ActMutedWord.kt b/app/src/main/java/jp/juggler/subwaytooter/ActMutedWord.kt index 5db40851..d9390bfe 100644 --- a/app/src/main/java/jp/juggler/subwaytooter/ActMutedWord.kt +++ b/app/src/main/java/jp/juggler/subwaytooter/ActMutedWord.kt @@ -13,7 +13,7 @@ import com.woxthebox.draglistview.swipe.ListSwipeHelper import com.woxthebox.draglistview.swipe.ListSwipeItem import jp.juggler.subwaytooter.table.MutedWord import jp.juggler.util.LogCategory -import jp.juggler.util.getAttributeColor +import jp.juggler.util.attrColor import java.util.* class ActMutedWord : AppCompatActivity() { @@ -169,7 +169,7 @@ class ActMutedWord : AppCompatActivity() { clickedView.findViewById(R.id.tvName).text dragView.findViewById(R.id.item_layout) - .setBackgroundColor(getAttributeColor(R.attr.list_item_bg_pressed_dragged)) + .setBackgroundColor(attrColor(R.attr.list_item_bg_pressed_dragged)) } } diff --git a/app/src/main/java/jp/juggler/subwaytooter/ActNickname.kt b/app/src/main/java/jp/juggler/subwaytooter/ActNickname.kt index 2a108a90..c8dc4309 100644 --- a/app/src/main/java/jp/juggler/subwaytooter/ActNickname.kt +++ b/app/src/main/java/jp/juggler/subwaytooter/ActNickname.kt @@ -180,7 +180,7 @@ class ActNickname : AppCompatActivity(), View.OnClickListener, ColorPickerDialog private fun show() { val s = etNickname.text.toString().trim { it <= ' ' } tvPreview.text = s.notEmpty() ?: acctPretty - tvPreview.textColor = color_fg.notZero() ?: getAttributeColor(R.attr.colorTimeSmall) + tvPreview.textColor = color_fg.notZero() ?: attrColor(R.attr.colorTimeSmall) tvPreview.backgroundColor = color_bg } diff --git a/app/src/main/java/jp/juggler/subwaytooter/ActPost.kt b/app/src/main/java/jp/juggler/subwaytooter/ActPost.kt index 728f15b4..afa4d085 100644 --- a/app/src/main/java/jp/juggler/subwaytooter/ActPost.kt +++ b/app/src/main/java/jp/juggler/subwaytooter/ActPost.kt @@ -1414,7 +1414,7 @@ class ActPost : AsyncActivity(), tvCharCount.text = remain.toString() tvCharCount.setTextColor( - getAttributeColor( + attrColor( if (remain < 0) R.attr.colorRegexFilterError else @@ -1496,7 +1496,7 @@ class ActPost : AsyncActivity(), if (a == null) { btnAccount.text = getString(R.string.not_selected) - btnAccount.setTextColor(getAttributeColor(android.R.attr.textColorPrimary)) + btnAccount.setTextColor(attrColor(android.R.attr.textColorPrimary)) btnAccount.setBackgroundResource(R.drawable.btn_bg_transparent_round6dp) } else { @@ -1516,7 +1516,7 @@ class ActPost : AsyncActivity(), } btnAccount.textColor = ac.color_fg.notZero() - ?: getAttributeColor(android.R.attr.textColorPrimary) + ?: attrColor(android.R.attr.textColorPrimary) } updateTextCount() updateFeaturedTags() diff --git a/app/src/main/java/jp/juggler/subwaytooter/AppSettingItem.kt b/app/src/main/java/jp/juggler/subwaytooter/AppSettingItem.kt index ad7a1841..643ec9e7 100644 --- a/app/src/main/java/jp/juggler/subwaytooter/AppSettingItem.kt +++ b/app/src/main/java/jp/juggler/subwaytooter/AppSettingItem.kt @@ -830,12 +830,12 @@ val appSettingRoot = AppSettingItem(null, SettingType.Section, R.string.app_sett val header_bg = when { color_column_header_bg != 0 -> color_column_header_bg - else -> activity.getAttributeColor(R.attr.color_column_header) + else -> activity.attrColor(R.attr.color_column_header) } val header_fg = when { color_column_header_fg != 0 -> color_column_header_fg - else -> activity.getAttributeColor(R.attr.colorColumnHeaderName) + else -> activity.attrColor(R.attr.colorColumnHeaderName) } llColumnHeader.background = getAdaptiveRippleDrawable(header_bg, header_fg) @@ -866,12 +866,12 @@ val appSettingRoot = AppSettingItem(null, SettingType.Section, R.string.app_sett tvSampleAcct.setTextColor( color_column_acct.notZero() - ?: activity.getAttributeColor(R.attr.colorTimeSmall) + ?: activity.attrColor(R.attr.colorTimeSmall) ) tvSampleContent.setTextColor( color_column_text.notZero() - ?: activity.getAttributeColor(R.attr.colorContentText) + ?: activity.attrColor(R.attr.colorContentText) ) } @@ -906,7 +906,7 @@ val appSettingRoot = AppSettingItem(null, SettingType.Section, R.string.app_sett val footer_tab_indicator_color = Pref.ipFooterTabIndicatorColor(pref) val colorColumnStripBackground = footer_tab_bg_color.notZero() - ?: activity.getAttributeColor(R.attr.colorColumnStripBackground) + ?: activity.attrColor(R.attr.colorColumnStripBackground) llFooterBG.setBackgroundColor(colorColumnStripBackground) @@ -914,7 +914,7 @@ val appSettingRoot = AppSettingItem(null, SettingType.Section, R.string.app_sett ?: colorColumnStripBackground val colorButtonFg = footer_button_fg_color.notZero() - ?: activity.getAttributeColor(R.attr.colorRippleEffect) + ?: activity.attrColor(R.attr.colorRippleEffect) ivFooterMenu.backgroundDrawable = getAdaptiveRippleDrawableRound(activity, colorButtonBg, colorButtonFg) @@ -923,7 +923,7 @@ val appSettingRoot = AppSettingItem(null, SettingType.Section, R.string.app_sett val csl = ColorStateList.valueOf( footer_button_fg_color.notZero() - ?: activity.getAttributeColor(R.attr.colorVectorDrawable) + ?: activity.attrColor(R.attr.colorVectorDrawable) ) ivFooterToot.imageTintList = csl ivFooterMenu.imageTintList = csl @@ -935,7 +935,7 @@ val appSettingRoot = AppSettingItem(null, SettingType.Section, R.string.app_sett vIndicator.setBackgroundColor( footer_tab_indicator_color.notZero() - ?: activity.getAttributeColor(R.attr.colorAccent) + ?: activity.attrColor(R.attr.colorAccent) ) } diff --git a/app/src/main/java/jp/juggler/subwaytooter/Column.kt b/app/src/main/java/jp/juggler/subwaytooter/Column.kt index b68bb4ca..62c8da04 100644 --- a/app/src/main/java/jp/juggler/subwaytooter/Column.kt +++ b/app/src/main/java/jp/juggler/subwaytooter/Column.kt @@ -348,22 +348,22 @@ class Column( fun reloadDefaultColor(activity: AppCompatActivity, pref: SharedPreferences) { defaultColorHeaderBg = Pref.ipCcdHeaderBg(pref).notZero() - ?: activity.getAttributeColor(R.attr.color_column_header) + ?: activity.attrColor(R.attr.color_column_header) defaultColorHeaderName = Pref.ipCcdHeaderFg(pref).notZero() - ?: activity.getAttributeColor(R.attr.colorColumnHeaderName) + ?: activity.attrColor(R.attr.colorColumnHeaderName) defaultColorHeaderPageNumber = Pref.ipCcdHeaderFg(pref).notZero() - ?: activity.getAttributeColor(R.attr.colorColumnHeaderPageNumber) + ?: activity.attrColor(R.attr.colorColumnHeaderPageNumber) defaultColorContentBg = Pref.ipCcdContentBg(pref) // may zero defaultColorContentAcct = Pref.ipCcdContentAcct(pref).notZero() - ?: activity.getAttributeColor(R.attr.colorTimeSmall) + ?: activity.attrColor(R.attr.colorTimeSmall) defaultColorContentText = Pref.ipCcdContentText(pref).notZero() - ?: activity.getAttributeColor(R.attr.colorContentText) + ?: activity.attrColor(R.attr.colorContentText) } diff --git a/app/src/main/java/jp/juggler/subwaytooter/ColumnViewHolder.kt b/app/src/main/java/jp/juggler/subwaytooter/ColumnViewHolder.kt index e2c27503..d848b6ad 100644 --- a/app/src/main/java/jp/juggler/subwaytooter/ColumnViewHolder.kt +++ b/app/src/main/java/jp/juggler/subwaytooter/ColumnViewHolder.kt @@ -720,7 +720,7 @@ class ColumnViewHolder( val context = activity val announcementsBgColor = Pref.ipAnnouncementsBgColor(App1.pref).notZero() - ?: context.getAttributeColor(R.attr.colorSearchFormBackground) + ?: context.attrColor(R.attr.colorSearchFormBackground) btnAnnouncementsCutout.apply { color = announcementsBgColor @@ -733,7 +733,7 @@ class ColumnViewHolder( } val searchBgColor = Pref.ipSearchBgColor(App1.pref).notZero() - ?: context.getAttributeColor(R.attr.colorSearchFormBackground) + ?: context.attrColor(R.attr.colorSearchFormBackground) llSearch.apply { backgroundColor = searchBgColor @@ -1231,7 +1231,7 @@ class ColumnViewHolder( tvColumnContext.text = ac.nickname tvColumnContext.setTextColor( ac.color_fg.notZero() - ?: activity.getAttributeColor(R.attr.colorTimeSmall) + ?: activity.attrColor(R.attr.colorTimeSmall) ) tvColumnContext.setBackgroundColor(ac.color_bg) @@ -1585,10 +1585,10 @@ class ColumnViewHolder( if (insideColumnSetting) { svQuickFilter.setBackgroundColor(0) - val colorFg = activity.getAttributeColor(R.attr.colorContentText) + val colorFg = activity.attrColor(R.attr.colorContentText) val colorBgSelected = colorFg.applyAlphaMultiplier(0.25f) val colorFgList = ColorStateList.valueOf(colorFg) - val colorBg = activity.getAttributeColor(R.attr.colorColumnSettingBackground) + val colorBg = activity.attrColor(R.attr.colorColumnSettingBackground) showQuickFilterButton = { btn, iconId, selected -> btn.backgroundDrawable = getAdaptiveRippleDrawableRound( @@ -1720,7 +1720,7 @@ class ColumnViewHolder( gravity = Gravity.END startPadding = dip(4) endPadding = dip(4) - textColor = context.getAttributeColor(R.attr.colorColumnHeaderAcct) + textColor = context.attrColor(R.attr.colorColumnHeaderAcct) textSize = 12f }.lparams(0, wrapContent) { @@ -1729,7 +1729,7 @@ class ColumnViewHolder( tvColumnStatus = textView { gravity = Gravity.END - textColor = context.getAttributeColor(R.attr.colorColumnHeaderPageNumber) + textColor = context.attrColor(R.attr.colorColumnHeaderPageNumber) textSize = 12f }.lparams(wrapContent, wrapContent) { @@ -1738,7 +1738,7 @@ class ColumnViewHolder( tvColumnIndex = textView { gravity = Gravity.END - textColor = context.getAttributeColor(R.attr.colorColumnHeaderPageNumber) + textColor = context.attrColor(R.attr.colorColumnHeaderPageNumber) textSize = 12f }.lparams(wrapContent, wrapContent) { @@ -1842,7 +1842,7 @@ class ColumnViewHolder( val paint = Paint().apply { isAntiAlias = true color = - context.getAttributeColor(R.attr.colorColumnSettingBackground) + context.attrColor(R.attr.colorColumnSettingBackground) } val path = Path() addOutsideDrawer(this) { canvas, parent, view, left, top -> @@ -1908,7 +1908,7 @@ class ColumnViewHolder( maxHeight = dip(240) backgroundColor = - context.getAttributeColor(R.attr.colorColumnSettingBackground) + context.attrColor(R.attr.colorColumnSettingBackground) llColumnSettingInside = verticalLayout { lparams(matchParent, wrapContent) @@ -1923,7 +1923,7 @@ class ColumnViewHolder( label = textView { textColor = - context.getAttributeColor(R.attr.colorColumnHeaderPageNumber) + context.attrColor(R.attr.colorColumnHeaderPageNumber) text = context.getString(R.string.hashtag_extra_any) }.lparams(matchParent, wrapContent) @@ -1938,7 +1938,7 @@ class ColumnViewHolder( label = textView { textColor = - context.getAttributeColor(R.attr.colorColumnHeaderPageNumber) + context.attrColor(R.attr.colorColumnHeaderPageNumber) text = context.getString(R.string.hashtag_extra_all) }.lparams(matchParent, wrapContent) @@ -1953,7 +1953,7 @@ class ColumnViewHolder( label = textView { textColor = - context.getAttributeColor(R.attr.colorColumnHeaderPageNumber) + context.attrColor(R.attr.colorColumnHeaderPageNumber) text = context.getString(R.string.hashtag_extra_none) }.lparams(matchParent, wrapContent) @@ -2048,12 +2048,12 @@ class ColumnViewHolder( label = textView { textColor = - context.getAttributeColor(R.attr.colorColumnHeaderPageNumber) + context.attrColor(R.attr.colorColumnHeaderPageNumber) text = context.getString(R.string.regex_filter) }.lparams(wrapContent, wrapContent) tvRegexFilterError = textView { - textColor = context.getAttributeColor(R.attr.colorRegexFilterError) + textColor = context.attrColor(R.attr.colorRegexFilterError) }.lparams(0, wrapContent) { weight = 1f startMargin = dip(4) @@ -2219,7 +2219,7 @@ class ColumnViewHolder( contentDescription = context.getString(R.string.clear) imageResource = R.drawable.ic_close imageTintList = ColorStateList.valueOf( - context.getAttributeColor(R.attr.colorVectorDrawable) + context.attrColor(R.attr.colorVectorDrawable) ) }.lparams(dip(40), dip(40)) { startMargin = dip(4) @@ -2230,7 +2230,7 @@ class ColumnViewHolder( contentDescription = context.getString(R.string.search) imageResource = R.drawable.ic_search imageTintList = ColorStateList.valueOf( - context.getAttributeColor(R.attr.colorVectorDrawable) + context.attrColor(R.attr.colorVectorDrawable) ) }.lparams(dip(40), dip(40)) { startMargin = dip(4) @@ -2262,7 +2262,7 @@ class ColumnViewHolder( contentDescription = context.getString(R.string.add) imageResource = R.drawable.ic_add imageTintList = ColorStateList.valueOf( - context.getAttributeColor( + context.attrColor( R.attr.colorVectorDrawable ) ) @@ -2680,8 +2680,8 @@ class ColumnViewHolder( btn.background = if (reaction.me == true) { getAdaptiveRippleDrawableRound( actMain, - actMain.getAttributeColor(R.attr.colorButtonBgCw), - actMain.getAttributeColor(R.attr.colorRippleEffect) + actMain.attrColor(R.attr.colorButtonBgCw), + actMain.attrColor(R.attr.colorRippleEffect) ) } else { ContextCompat.getDrawable(actMain, R.drawable.btn_bg_transparent_round6dp) diff --git a/app/src/main/java/jp/juggler/subwaytooter/DlgContextMenu.kt b/app/src/main/java/jp/juggler/subwaytooter/DlgContextMenu.kt index ae82105f..ba495b4d 100644 --- a/app/src/main/java/jp/juggler/subwaytooter/DlgContextMenu.kt +++ b/app/src/main/java/jp/juggler/subwaytooter/DlgContextMenu.kt @@ -347,14 +347,14 @@ internal class DlgContextMenu( val colorButtonAccent = Pref.ipButtonFollowingColor(activity.pref).notZero() - ?: activity.getAttributeColor(R.attr.colorImageButtonAccent) + ?: activity.attrColor(R.attr.colorImageButtonAccent) val colorButtonError = Pref.ipButtonFollowRequestColor(activity.pref).notZero() - ?: activity.getAttributeColor(R.attr.colorRegexFilterError) + ?: activity.attrColor(R.attr.colorRegexFilterError) val colorButtonNormal = - activity.getAttributeColor(R.attr.colorImageButton) + activity.attrColor(R.attr.colorImageButton) fun showRelation(relation : UserRelation) { @@ -405,7 +405,7 @@ internal class DlgContextMenu( ivFollowedBy.vg(false) btnFollow.setImageResource(R.drawable.ic_follow_plus) btnFollow.imageTintList = - ColorStateList.valueOf(activity.getAttributeColor(R.attr.colorImageButton)) + ColorStateList.valueOf(activity.attrColor(R.attr.colorImageButton)) btnNotificationFrom.visibility = View.GONE } else { @@ -583,7 +583,7 @@ internal class DlgContextMenu( R.drawable.ic_arrow_drop_down } - val iconColor = activity.getAttributeColor(R.attr.colorTimeSmall) + val iconColor = activity.attrColor(R.attr.colorTimeSmall) val drawable = createColoredDrawable(activity, iconId, iconColor, 1f) btn.setCompoundDrawablesRelativeWithIntrinsicBounds(drawable, null, null, null) } diff --git a/app/src/main/java/jp/juggler/subwaytooter/ItemViewHolder.kt b/app/src/main/java/jp/juggler/subwaytooter/ItemViewHolder.kt index 1d8aa000..fc99261f 100644 --- a/app/src/main/java/jp/juggler/subwaytooter/ItemViewHolder.kt +++ b/app/src/main/java/jp/juggler/subwaytooter/ItemViewHolder.kt @@ -39,153 +39,153 @@ import org.jetbrains.anko.* import kotlin.math.max internal class ItemViewHolder( - val activity : ActMain + val activity: ActMain ) : View.OnClickListener, View.OnLongClickListener { - - companion object { - - private val log = LogCategory("ItemViewHolder") - var toot_color_unlisted : Int = 0 - var toot_color_follower : Int = 0 - var toot_color_direct_user : Int = 0 - var toot_color_direct_me : Int = 0 - - } - - val viewRoot : View - - private var bSimpleList : Boolean = false - - lateinit var column : Column - - internal lateinit var list_adapter : ItemListAdapter - - private lateinit var llBoosted : View - private lateinit var ivBoosted : ImageView - private lateinit var tvBoosted : TextView - private lateinit var tvBoostedAcct : TextView - private lateinit var tvBoostedTime : TextView - - private lateinit var llReply : View - private lateinit var ivReply : ImageView - private lateinit var tvReply : TextView - - private lateinit var llFollow : View - private lateinit var ivFollow : MyNetworkImageView - private lateinit var tvFollowerName : TextView - private lateinit var tvFollowerAcct : TextView - private lateinit var btnFollow : ImageButton - private lateinit var ivFollowedBy : ImageView - - private lateinit var llStatus : View - private lateinit var ivThumbnail : MyNetworkImageView - private lateinit var tvName : TextView - private lateinit var tvTime : TextView - private lateinit var tvAcct : TextView - - private lateinit var llContentWarning : View - private lateinit var tvContentWarning : MyTextView - private lateinit var btnContentWarning : Button - - private lateinit var llContents : View - private lateinit var tvMentions : MyTextView - internal lateinit var tvContent : MyTextView - - private lateinit var flMedia : View - private lateinit var llMedia : View - private lateinit var btnShowMedia : BlurhashView - private lateinit var ivMedia1 : MyNetworkImageView - private lateinit var ivMedia2 : MyNetworkImageView - private lateinit var ivMedia3 : MyNetworkImageView - private lateinit var ivMedia4 : MyNetworkImageView - private lateinit var btnHideMedia : ImageButton - - private lateinit var statusButtonsViewHolder : StatusButtonsViewHolder - private lateinit var llButtonBar : View - - private lateinit var llSearchTag : View - private lateinit var btnSearchTag : Button - private lateinit var btnGapHead : ImageButton - private lateinit var btnGapTail : ImageButton - private lateinit var llTrendTag : View - private lateinit var tvTrendTagName : TextView - private lateinit var tvTrendTagDesc : TextView - private lateinit var tvTrendTagCount : TextView - private lateinit var cvTagHistory : TagHistoryView - - private lateinit var llList : View - private lateinit var btnListTL : Button - private lateinit var btnListMore : ImageButton - - private lateinit var llFollowRequest : View - private lateinit var btnFollowRequestAccept : ImageButton - private lateinit var btnFollowRequestDeny : ImageButton - - private lateinit var llFilter : View - private lateinit var tvFilterPhrase : TextView - private lateinit var tvFilterDetail : TextView - - private lateinit var tvMediaDescription : TextView - - private lateinit var llCardOuter : View - private lateinit var tvCardText : MyTextView - private lateinit var flCardImage : View - private lateinit var llCardImage : View - private lateinit var ivCardImage : MyNetworkImageView - private lateinit var btnCardImageHide : ImageButton - private lateinit var btnCardImageShow : BlurhashView - - private lateinit var llExtra : LinearLayout - - private lateinit var llConversationIcons : View - private lateinit var ivConversationIcon1 : MyNetworkImageView - private lateinit var ivConversationIcon2 : MyNetworkImageView - private lateinit var ivConversationIcon3 : MyNetworkImageView - private lateinit var ivConversationIcon4 : MyNetworkImageView - private lateinit var tvConversationIconsMore : TextView - private lateinit var tvConversationParticipants : TextView - - private lateinit var tvApplication : TextView - - private lateinit var tvMessageHolder : TextView - - private lateinit var llOpenSticker : View - private lateinit var ivOpenSticker : MyNetworkImageView - private lateinit var tvOpenSticker : TextView - - private lateinit var tvLastStatusAt : TextView - - private lateinit var access_info : SavedAccount - - private var buttons_for_status : StatusButtons? = null - - private var item : TimelineItem? = null - - private var status_showing : TootStatus? = null - private var status_reply : TootStatus? = null - private var status_account : TootAccountRef? = null - private var boost_account : TootAccountRef? = null - private var follow_account : TootAccountRef? = null - - private var boost_time : Long = 0L - - private var content_color : Int = 0 - private var acct_color : Int = 0 - private var content_color_csl : ColorStateList = ColorStateList.valueOf(0) - - private val boost_invalidator : NetworkEmojiInvalidator - private val reply_invalidator : NetworkEmojiInvalidator - private val follow_invalidator : NetworkEmojiInvalidator - private val name_invalidator : NetworkEmojiInvalidator - private val content_invalidator : NetworkEmojiInvalidator - private val spoiler_invalidator : NetworkEmojiInvalidator - private val lastActive_invalidator : NetworkEmojiInvalidator - private val extra_invalidator_list = ArrayList() - - init { - this.viewRoot = inflate(activity) - - for(v in arrayOf( + + companion object { + + private val log = LogCategory("ItemViewHolder") + var toot_color_unlisted: Int = 0 + var toot_color_follower: Int = 0 + var toot_color_direct_user: Int = 0 + var toot_color_direct_me: Int = 0 + + } + + val viewRoot: View + + private var bSimpleList: Boolean = false + + lateinit var column: Column + + internal lateinit var list_adapter: ItemListAdapter + + private lateinit var llBoosted: View + private lateinit var ivBoosted: ImageView + private lateinit var tvBoosted: TextView + private lateinit var tvBoostedAcct: TextView + private lateinit var tvBoostedTime: TextView + + private lateinit var llReply: View + private lateinit var ivReply: ImageView + private lateinit var tvReply: TextView + + private lateinit var llFollow: View + private lateinit var ivFollow: MyNetworkImageView + private lateinit var tvFollowerName: TextView + private lateinit var tvFollowerAcct: TextView + private lateinit var btnFollow: ImageButton + private lateinit var ivFollowedBy: ImageView + + private lateinit var llStatus: View + private lateinit var ivThumbnail: MyNetworkImageView + private lateinit var tvName: TextView + private lateinit var tvTime: TextView + private lateinit var tvAcct: TextView + + private lateinit var llContentWarning: View + private lateinit var tvContentWarning: MyTextView + private lateinit var btnContentWarning: Button + + private lateinit var llContents: View + private lateinit var tvMentions: MyTextView + internal lateinit var tvContent: MyTextView + + private lateinit var flMedia: View + private lateinit var llMedia: View + private lateinit var btnShowMedia: BlurhashView + private lateinit var ivMedia1: MyNetworkImageView + private lateinit var ivMedia2: MyNetworkImageView + private lateinit var ivMedia3: MyNetworkImageView + private lateinit var ivMedia4: MyNetworkImageView + private lateinit var btnHideMedia: ImageButton + + private lateinit var statusButtonsViewHolder: StatusButtonsViewHolder + private lateinit var llButtonBar: View + + private lateinit var llSearchTag: View + private lateinit var btnSearchTag: Button + private lateinit var btnGapHead: ImageButton + private lateinit var btnGapTail: ImageButton + private lateinit var llTrendTag: View + private lateinit var tvTrendTagName: TextView + private lateinit var tvTrendTagDesc: TextView + private lateinit var tvTrendTagCount: TextView + private lateinit var cvTagHistory: TagHistoryView + + private lateinit var llList: View + private lateinit var btnListTL: Button + private lateinit var btnListMore: ImageButton + + private lateinit var llFollowRequest: View + private lateinit var btnFollowRequestAccept: ImageButton + private lateinit var btnFollowRequestDeny: ImageButton + + private lateinit var llFilter: View + private lateinit var tvFilterPhrase: TextView + private lateinit var tvFilterDetail: TextView + + private lateinit var tvMediaDescription: TextView + + private lateinit var llCardOuter: View + private lateinit var tvCardText: MyTextView + private lateinit var flCardImage: View + private lateinit var llCardImage: View + private lateinit var ivCardImage: MyNetworkImageView + private lateinit var btnCardImageHide: ImageButton + private lateinit var btnCardImageShow: BlurhashView + + private lateinit var llExtra: LinearLayout + + private lateinit var llConversationIcons: View + private lateinit var ivConversationIcon1: MyNetworkImageView + private lateinit var ivConversationIcon2: MyNetworkImageView + private lateinit var ivConversationIcon3: MyNetworkImageView + private lateinit var ivConversationIcon4: MyNetworkImageView + private lateinit var tvConversationIconsMore: TextView + private lateinit var tvConversationParticipants: TextView + + private lateinit var tvApplication: TextView + + private lateinit var tvMessageHolder: TextView + + private lateinit var llOpenSticker: View + private lateinit var ivOpenSticker: MyNetworkImageView + private lateinit var tvOpenSticker: TextView + + private lateinit var tvLastStatusAt: TextView + + private lateinit var access_info: SavedAccount + + private var buttons_for_status: StatusButtons? = null + + private var item: TimelineItem? = null + + private var status_showing: TootStatus? = null + private var status_reply: TootStatus? = null + private var status_account: TootAccountRef? = null + private var boost_account: TootAccountRef? = null + private var follow_account: TootAccountRef? = null + + private var boost_time: Long = 0L + + private var content_color: Int = 0 + private var acct_color: Int = 0 + private var content_color_csl: ColorStateList = ColorStateList.valueOf(0) + + private val boost_invalidator: NetworkEmojiInvalidator + private val reply_invalidator: NetworkEmojiInvalidator + private val follow_invalidator: NetworkEmojiInvalidator + private val name_invalidator: NetworkEmojiInvalidator + private val content_invalidator: NetworkEmojiInvalidator + private val spoiler_invalidator: NetworkEmojiInvalidator + private val lastActive_invalidator: NetworkEmojiInvalidator + private val extra_invalidator_list = ArrayList() + + init { + this.viewRoot = inflate(activity) + + for (v in arrayOf( btnListTL, btnListMore, btnSearchTag, @@ -212,10 +212,10 @@ internal class ItemViewHolder( llTrendTag, llFilter )) { - v.setOnClickListener(this) - } - - for(v in arrayOf( + v.setOnClickListener(this) + } + + for (v in arrayOf( btnSearchTag, btnFollow, ivCardImage, @@ -226,156 +226,156 @@ internal class ItemViewHolder( ivThumbnail, llTrendTag )) { - v.setOnLongClickListener(this) - } - - // - tvContent.movementMethod = MyLinkMovementMethod - tvMentions.movementMethod = MyLinkMovementMethod - tvContentWarning.movementMethod = MyLinkMovementMethod - tvMediaDescription.movementMethod = MyLinkMovementMethod - tvCardText.movementMethod = MyLinkMovementMethod - - var f : Float - - f = activity.timeline_font_size_sp - if(! f.isNaN()) { - tvFollowerName.textSize = f - tvName.textSize = f - tvMentions.textSize = f - tvContentWarning.textSize = f - tvContent.textSize = f - btnShowMedia.textSize = f - btnCardImageShow.textSize = f - tvApplication.textSize = f - tvMessageHolder.textSize = f - btnListTL.textSize = f - tvTrendTagName.textSize = f - tvTrendTagCount.textSize = f - tvFilterPhrase.textSize = f - tvMediaDescription.textSize = f - tvCardText.textSize = f - tvConversationIconsMore.textSize = f - tvConversationParticipants.textSize = f - } - - f = activity.notification_tl_font_size_sp - if(! f.isNaN()) { - tvBoosted.textSize = f - tvReply.textSize = f - } - - f = activity.acct_font_size_sp - if(! f.isNaN()) { - tvBoostedAcct.textSize = f - tvBoostedTime.textSize = f - tvFollowerAcct.textSize = f - tvLastStatusAt.textSize = f - tvAcct.textSize = f - tvTime.textSize = f - tvTrendTagDesc.textSize = f - tvFilterDetail.textSize = f - } - - val spacing = activity.timeline_spacing - if(spacing != null) { - tvFollowerName.setLineSpacing(0f, spacing) - tvName.setLineSpacing(0f, spacing) - tvMentions.setLineSpacing(0f, spacing) - tvContentWarning.setLineSpacing(0f, spacing) - tvContent.setLineSpacing(0f, spacing) - btnShowMedia.setLineSpacing(0f, spacing) - btnCardImageShow.setLineSpacing(0f, spacing) - tvApplication.setLineSpacing(0f, spacing) - tvMessageHolder.setLineSpacing(0f, spacing) - btnListTL.setLineSpacing(0f, spacing) - tvTrendTagName.setLineSpacing(0f, spacing) - tvTrendTagCount.setLineSpacing(0f, spacing) - tvFilterPhrase.setLineSpacing(0f, spacing) - tvMediaDescription.setLineSpacing(0f, spacing) - tvCardText.setLineSpacing(0f, spacing) - tvConversationIconsMore.setLineSpacing(0f, spacing) - tvConversationParticipants.setLineSpacing(0f, spacing) - tvBoosted.setLineSpacing(0f, spacing) - tvReply.setLineSpacing(0f, spacing) - tvLastStatusAt.setLineSpacing(0f, spacing) - } - - var s = activity.avatarIconSize - ivThumbnail.layoutParams.height = s - ivThumbnail.layoutParams.width = s - ivFollow.layoutParams.width = s - ivBoosted.layoutParams.width = s - - s = ActMain.replyIconSize + (activity.density * 8).toInt() - ivReply.layoutParams.width = s - ivReply.layoutParams.height = s - - s = activity.notificationTlIconSize - ivBoosted.layoutParams.height = s - - this.content_invalidator = NetworkEmojiInvalidator(activity.handler, tvContent) - this.spoiler_invalidator = NetworkEmojiInvalidator(activity.handler, tvContentWarning) - this.boost_invalidator = NetworkEmojiInvalidator(activity.handler, tvBoosted) - this.reply_invalidator = NetworkEmojiInvalidator(activity.handler, tvReply) - this.follow_invalidator = NetworkEmojiInvalidator(activity.handler, tvFollowerName) - this.name_invalidator = NetworkEmojiInvalidator(activity.handler, tvName) - this.lastActive_invalidator = NetworkEmojiInvalidator(activity.handler, tvLastStatusAt) - - val cardBackground = llCardOuter.background - if(cardBackground is PreviewCardBorder) { - val density = activity.density - cardBackground.round = (density * 8f) - cardBackground.width = (density * 1f) - } - - val textShowMedia = SpannableString(activity.getString(R.string.tap_to_show)) - .apply { - val colorBg = activity.getAttributeColor(R.attr.colorShowMediaBackground) - .applyAlphaMultiplier(0.5f) - setSpan( + v.setOnLongClickListener(this) + } + + // + tvContent.movementMethod = MyLinkMovementMethod + tvMentions.movementMethod = MyLinkMovementMethod + tvContentWarning.movementMethod = MyLinkMovementMethod + tvMediaDescription.movementMethod = MyLinkMovementMethod + tvCardText.movementMethod = MyLinkMovementMethod + + var f: Float + + f = activity.timeline_font_size_sp + if (!f.isNaN()) { + tvFollowerName.textSize = f + tvName.textSize = f + tvMentions.textSize = f + tvContentWarning.textSize = f + tvContent.textSize = f + btnShowMedia.textSize = f + btnCardImageShow.textSize = f + tvApplication.textSize = f + tvMessageHolder.textSize = f + btnListTL.textSize = f + tvTrendTagName.textSize = f + tvTrendTagCount.textSize = f + tvFilterPhrase.textSize = f + tvMediaDescription.textSize = f + tvCardText.textSize = f + tvConversationIconsMore.textSize = f + tvConversationParticipants.textSize = f + } + + f = activity.notification_tl_font_size_sp + if (!f.isNaN()) { + tvBoosted.textSize = f + tvReply.textSize = f + } + + f = activity.acct_font_size_sp + if (!f.isNaN()) { + tvBoostedAcct.textSize = f + tvBoostedTime.textSize = f + tvFollowerAcct.textSize = f + tvLastStatusAt.textSize = f + tvAcct.textSize = f + tvTime.textSize = f + tvTrendTagDesc.textSize = f + tvFilterDetail.textSize = f + } + + val spacing = activity.timeline_spacing + if (spacing != null) { + tvFollowerName.setLineSpacing(0f, spacing) + tvName.setLineSpacing(0f, spacing) + tvMentions.setLineSpacing(0f, spacing) + tvContentWarning.setLineSpacing(0f, spacing) + tvContent.setLineSpacing(0f, spacing) + btnShowMedia.setLineSpacing(0f, spacing) + btnCardImageShow.setLineSpacing(0f, spacing) + tvApplication.setLineSpacing(0f, spacing) + tvMessageHolder.setLineSpacing(0f, spacing) + btnListTL.setLineSpacing(0f, spacing) + tvTrendTagName.setLineSpacing(0f, spacing) + tvTrendTagCount.setLineSpacing(0f, spacing) + tvFilterPhrase.setLineSpacing(0f, spacing) + tvMediaDescription.setLineSpacing(0f, spacing) + tvCardText.setLineSpacing(0f, spacing) + tvConversationIconsMore.setLineSpacing(0f, spacing) + tvConversationParticipants.setLineSpacing(0f, spacing) + tvBoosted.setLineSpacing(0f, spacing) + tvReply.setLineSpacing(0f, spacing) + tvLastStatusAt.setLineSpacing(0f, spacing) + } + + var s = activity.avatarIconSize + ivThumbnail.layoutParams.height = s + ivThumbnail.layoutParams.width = s + ivFollow.layoutParams.width = s + ivBoosted.layoutParams.width = s + + s = ActMain.replyIconSize + (activity.density * 8).toInt() + ivReply.layoutParams.width = s + ivReply.layoutParams.height = s + + s = activity.notificationTlIconSize + ivBoosted.layoutParams.height = s + + this.content_invalidator = NetworkEmojiInvalidator(activity.handler, tvContent) + this.spoiler_invalidator = NetworkEmojiInvalidator(activity.handler, tvContentWarning) + this.boost_invalidator = NetworkEmojiInvalidator(activity.handler, tvBoosted) + this.reply_invalidator = NetworkEmojiInvalidator(activity.handler, tvReply) + this.follow_invalidator = NetworkEmojiInvalidator(activity.handler, tvFollowerName) + this.name_invalidator = NetworkEmojiInvalidator(activity.handler, tvName) + this.lastActive_invalidator = NetworkEmojiInvalidator(activity.handler, tvLastStatusAt) + + val cardBackground = llCardOuter.background + if (cardBackground is PreviewCardBorder) { + val density = activity.density + cardBackground.round = (density * 8f) + cardBackground.width = (density * 1f) + } + + val textShowMedia = SpannableString(activity.getString(R.string.tap_to_show)) + .apply { + val colorBg = activity.attrColor(R.attr.colorShowMediaBackground) + .applyAlphaMultiplier(0.5f) + setSpan( BackgroundColorSpan(colorBg), 0, this.length, Spannable.SPAN_EXCLUSIVE_EXCLUSIVE ) - } - - btnShowMedia.text = textShowMedia - btnCardImageShow.text = textShowMedia - } - - fun onViewRecycled() { - - } - - @SuppressLint("ClickableViewAccessibility") - fun bind( - list_adapter : ItemListAdapter, - column : Column, - bSimpleList : Boolean, - item : TimelineItem + } + + btnShowMedia.text = textShowMedia + btnCardImageShow.text = textShowMedia + } + + fun onViewRecycled() { + + } + + @SuppressLint("ClickableViewAccessibility") + fun bind( + list_adapter: ItemListAdapter, + column: Column, + bSimpleList: Boolean, + item: TimelineItem ) { - val b = Benchmark(log, "Item-bind", 40L) - - this.list_adapter = list_adapter - this.column = column - this.bSimpleList = bSimpleList - - this.access_info = column.access_info - - val font_bold = ActMain.timeline_font_bold - val font_normal = ActMain.timeline_font - viewRoot.scan { v -> - try { - when(v) { - // ボタンは太字なので触らない + val b = Benchmark(log, "Item-bind", 40L) + + this.list_adapter = list_adapter + this.column = column + this.bSimpleList = bSimpleList + + this.access_info = column.access_info + + val font_bold = ActMain.timeline_font_bold + val font_normal = ActMain.timeline_font + viewRoot.scan { v -> + try { + when (v) { + // ボタンは太字なので触らない is CountImageButton -> { } - // ボタンは太字なので触らない + // ボタンは太字なので触らない is Button -> { } - + is TextView -> v.typeface = when { v === tvName || v === tvFollowerName || @@ -388,142 +388,142 @@ internal class ItemViewHolder( v === tvFilterPhrase -> font_bold else -> font_normal } - } - } catch(ex : Throwable) { - log.trace(ex) - } - } - - if(bSimpleList) { - - viewRoot.setOnTouchListener { _, ev -> - // ポップアップを閉じた時にクリックでリストを触ったことになってしまう不具合の回避 - val now = SystemClock.elapsedRealtime() - // ポップアップを閉じた直後はタッチダウンを無視する - if(now - StatusButtonsPopup.last_popup_close >= 30L) { - false - } else { - val action = ev.action - log.d("onTouchEvent action=$action") - true - } - } - - viewRoot.setOnClickListener { viewClicked -> - activity.closeListItemPopup() - status_showing?.let { status -> - val popup = - StatusButtonsPopup(activity, column, bSimpleList, this@ItemViewHolder) - activity.listItemPopup = popup - popup.show( + } + } catch (ex: Throwable) { + log.trace(ex) + } + } + + if (bSimpleList) { + + viewRoot.setOnTouchListener { _, ev -> + // ポップアップを閉じた時にクリックでリストを触ったことになってしまう不具合の回避 + val now = SystemClock.elapsedRealtime() + // ポップアップを閉じた直後はタッチダウンを無視する + if (now - StatusButtonsPopup.last_popup_close >= 30L) { + false + } else { + val action = ev.action + log.d("onTouchEvent action=$action") + true + } + } + + viewRoot.setOnClickListener { viewClicked -> + activity.closeListItemPopup() + status_showing?.let { status -> + val popup = + StatusButtonsPopup(activity, column, bSimpleList, this@ItemViewHolder) + activity.listItemPopup = popup + popup.show( list_adapter.columnVh.listView, viewClicked, status, item as? TootNotification ) - } - } - llButtonBar.visibility = View.GONE - this.buttons_for_status = null - } else { - viewRoot.isClickable = false - llButtonBar.visibility = View.VISIBLE - this.buttons_for_status = StatusButtons( + } + } + llButtonBar.visibility = View.GONE + this.buttons_for_status = null + } else { + viewRoot.isClickable = false + llButtonBar.visibility = View.VISIBLE + this.buttons_for_status = StatusButtons( activity, column, false, statusButtonsViewHolder, this ) - } - - this.status_showing = null - this.status_reply = null - this.status_account = null - this.boost_account = null - this.follow_account = null - this.boost_time = 0L - this.viewRoot.setBackgroundColor(0) - this.boostedAction = defaultBoostedAction - - llOpenSticker.visibility = View.GONE - llBoosted.visibility = View.GONE - llReply.visibility = View.GONE - llFollow.visibility = View.GONE - llStatus.visibility = View.GONE - llSearchTag.visibility = View.GONE - btnGapHead.visibility = View.GONE - btnGapTail.visibility = View.GONE - llList.visibility = View.GONE - llFollowRequest.visibility = View.GONE - tvMessageHolder.visibility = View.GONE - llTrendTag.visibility = View.GONE - llFilter.visibility = View.GONE - tvMediaDescription.visibility = View.GONE - llCardOuter.visibility = View.GONE - tvCardText.visibility = View.GONE - flCardImage.visibility = View.GONE - llConversationIcons.visibility = View.GONE - - removeExtraView() - - var c : Int - c = column.getContentColor() - this.content_color = c - this.content_color_csl = ColorStateList.valueOf(c) - - tvBoosted.setTextColor(c) - tvReply.setTextColor(c) - tvFollowerName.setTextColor(c) - tvName.setTextColor(c) - tvMentions.setTextColor(c) - tvContentWarning.setTextColor(c) - tvContent.setTextColor(c) - //NSFWは文字色固定 btnShowMedia.setTextColor( c ); - tvApplication.setTextColor(c) - tvMessageHolder.setTextColor(c) - tvTrendTagName.setTextColor(c) - tvTrendTagCount.setTextColor(c) - cvTagHistory.setColor(c) - tvFilterPhrase.setTextColor(c) - tvMediaDescription.setTextColor(c) - tvCardText.setTextColor(c) - tvConversationIconsMore.setTextColor(c) - tvConversationParticipants.setTextColor(c) - - (llCardOuter.background as? PreviewCardBorder)?.let { - val rgb = c and 0xffffff - val alpha = max(1, c ushr (24 + 1)) // 本来の値の半分にする - it.color = rgb or (alpha shl 24) - } - - c = column.getAcctColor() - this.acct_color = c - tvBoostedTime.setTextColor(c) - tvTime.setTextColor(c) - tvTrendTagDesc.setTextColor(c) - tvFilterDetail.setTextColor(c) - tvFilterPhrase.setTextColor(c) - - // 以下のビューの文字色はsetAcct() で設定される - // tvBoostedAcct.setTextColor(c) - // tvFollowerAcct.setTextColor(c) - // tvAcct.setTextColor(c) - - this.item = item - when(item) { + } + + this.status_showing = null + this.status_reply = null + this.status_account = null + this.boost_account = null + this.follow_account = null + this.boost_time = 0L + this.viewRoot.setBackgroundColor(0) + this.boostedAction = defaultBoostedAction + + llOpenSticker.visibility = View.GONE + llBoosted.visibility = View.GONE + llReply.visibility = View.GONE + llFollow.visibility = View.GONE + llStatus.visibility = View.GONE + llSearchTag.visibility = View.GONE + btnGapHead.visibility = View.GONE + btnGapTail.visibility = View.GONE + llList.visibility = View.GONE + llFollowRequest.visibility = View.GONE + tvMessageHolder.visibility = View.GONE + llTrendTag.visibility = View.GONE + llFilter.visibility = View.GONE + tvMediaDescription.visibility = View.GONE + llCardOuter.visibility = View.GONE + tvCardText.visibility = View.GONE + flCardImage.visibility = View.GONE + llConversationIcons.visibility = View.GONE + + removeExtraView() + + var c: Int + c = column.getContentColor() + this.content_color = c + this.content_color_csl = ColorStateList.valueOf(c) + + tvBoosted.setTextColor(c) + tvReply.setTextColor(c) + tvFollowerName.setTextColor(c) + tvName.setTextColor(c) + tvMentions.setTextColor(c) + tvContentWarning.setTextColor(c) + tvContent.setTextColor(c) + //NSFWは文字色固定 btnShowMedia.setTextColor( c ); + tvApplication.setTextColor(c) + tvMessageHolder.setTextColor(c) + tvTrendTagName.setTextColor(c) + tvTrendTagCount.setTextColor(c) + cvTagHistory.setColor(c) + tvFilterPhrase.setTextColor(c) + tvMediaDescription.setTextColor(c) + tvCardText.setTextColor(c) + tvConversationIconsMore.setTextColor(c) + tvConversationParticipants.setTextColor(c) + + (llCardOuter.background as? PreviewCardBorder)?.let { + val rgb = c and 0xffffff + val alpha = max(1, c ushr (24 + 1)) // 本来の値の半分にする + it.color = rgb or (alpha shl 24) + } + + c = column.getAcctColor() + this.acct_color = c + tvBoostedTime.setTextColor(c) + tvTime.setTextColor(c) + tvTrendTagDesc.setTextColor(c) + tvFilterDetail.setTextColor(c) + tvFilterPhrase.setTextColor(c) + + // 以下のビューの文字色はsetAcct() で設定される + // tvBoostedAcct.setTextColor(c) + // tvFollowerAcct.setTextColor(c) + // tvAcct.setTextColor(c) + + this.item = item + when (item) { is TootStatus -> { val reblog = item.reblog when { reblog == null -> showStatusOrReply(item) - + item.isQuoteToot -> { // 引用Renote val colorBg = Pref.ipEventBgColorBoost(activity.pref) showReply(reblog, R.drawable.ic_repeat, R.string.quote_to) showStatus(item, colorBg) } - + else -> { // 引用なしブースト val colorBg = Pref.ipEventBgColorBoost(activity.pref) @@ -538,323 +538,323 @@ internal class ItemViewHolder( } } } - + is TootAccountRef -> showAccount(item) - + is TootNotification -> showNotification(item) - + is TootGap -> showGap() is TootSearchGap -> showSearchGap(item) is TootDomainBlock -> showDomainBlock(item) is TootList -> showList(item) is MisskeyAntenna -> showAntenna(item) - + is TootMessageHolder -> showMessageHolder(item) - + is TootTag -> showSearchTag(item) - + is TootFilter -> showFilter(item) - + is TootConversationSummary -> { showStatusOrReply(item.last_status) showConversationIcons(item) } - + is TootScheduled -> { showScheduled(item) } - - else -> { - } - } - b.report() - } - - private fun showScheduled(item : TootScheduled) { - try { - - llStatus.visibility = View.VISIBLE - - this.viewRoot.setBackgroundColor(0) - - showStatusTimeScheduled(activity, tvTime, item) - - val who = column.who_account !!.get() - val whoRef = TootAccountRef(TootParser(activity, access_info), who) - this.status_account = whoRef - - setAcct(tvAcct, access_info, who) - - tvName.text = whoRef.decoded_display_name - name_invalidator.register(whoRef.decoded_display_name) - ivThumbnail.setImageUrl( + + else -> { + } + } + b.report() + } + + private fun showScheduled(item: TootScheduled) { + try { + + llStatus.visibility = View.VISIBLE + + this.viewRoot.setBackgroundColor(0) + + showStatusTimeScheduled(activity, tvTime, item) + + val who = column.who_account!!.get() + val whoRef = TootAccountRef(TootParser(activity, access_info), who) + this.status_account = whoRef + + setAcct(tvAcct, access_info, who) + + tvName.text = whoRef.decoded_display_name + name_invalidator.register(whoRef.decoded_display_name) + ivThumbnail.setImageUrl( activity.pref, Styler.calcIconRound(ivThumbnail.layoutParams), access_info.supplyBaseUrl(who.avatar_static), access_info.supplyBaseUrl(who.avatar) ) - - val content = SpannableString(item.text ?: "") - - tvMentions.visibility = View.GONE - - tvContent.text = content - content_invalidator.register(content) - - tvContent.minLines = - 1 - - val decoded_spoiler_text = SpannableString(item.spoiler_text ?: "") - when { - decoded_spoiler_text.isNotEmpty() -> { - // 元データに含まれるContent Warning を使う - llContentWarning.visibility = View.VISIBLE - tvContentWarning.text = decoded_spoiler_text - spoiler_invalidator.register(decoded_spoiler_text) - val cw_shown = ContentWarning.isShown(item.uri, access_info.expand_cw) - showContent(cw_shown) - } - - else -> { - // CWしない - llContentWarning.visibility = View.GONE - llContents.visibility = View.VISIBLE - } - } - - val media_attachments = item.media_attachments - if(media_attachments?.isEmpty() != false) { - flMedia.visibility = View.GONE - llMedia.visibility = View.GONE - btnShowMedia.visibility = View.GONE - } else { - flMedia.visibility = View.VISIBLE - - // hide sensitive media - val default_shown = when { - column.hide_media_default -> false - access_info.dont_hide_nsfw -> true - else -> ! item.sensitive - } - val is_shown = MediaShown.isShown(item.uri, default_shown) - - btnShowMedia.visibility = if(! is_shown) View.VISIBLE else View.GONE - llMedia.visibility = if(! is_shown) View.GONE else View.VISIBLE - val sb = StringBuilder() - setMedia(media_attachments, sb, ivMedia1, 0) - setMedia(media_attachments, sb, ivMedia2, 1) - setMedia(media_attachments, sb, ivMedia3, 2) - setMedia(media_attachments, sb, ivMedia4, 3) - if(sb.isNotEmpty()) { - tvMediaDescription.visibility = View.VISIBLE - tvMediaDescription.text = sb - } - - setIconDrawableId( + + val content = SpannableString(item.text ?: "") + + tvMentions.visibility = View.GONE + + tvContent.text = content + content_invalidator.register(content) + + tvContent.minLines = -1 + + val decoded_spoiler_text = SpannableString(item.spoiler_text ?: "") + when { + decoded_spoiler_text.isNotEmpty() -> { + // 元データに含まれるContent Warning を使う + llContentWarning.visibility = View.VISIBLE + tvContentWarning.text = decoded_spoiler_text + spoiler_invalidator.register(decoded_spoiler_text) + val cw_shown = ContentWarning.isShown(item.uri, access_info.expand_cw) + showContent(cw_shown) + } + + else -> { + // CWしない + llContentWarning.visibility = View.GONE + llContents.visibility = View.VISIBLE + } + } + + val media_attachments = item.media_attachments + if (media_attachments?.isEmpty() != false) { + flMedia.visibility = View.GONE + llMedia.visibility = View.GONE + btnShowMedia.visibility = View.GONE + } else { + flMedia.visibility = View.VISIBLE + + // hide sensitive media + val default_shown = when { + column.hide_media_default -> false + access_info.dont_hide_nsfw -> true + else -> !item.sensitive + } + val is_shown = MediaShown.isShown(item.uri, default_shown) + + btnShowMedia.visibility = if (!is_shown) View.VISIBLE else View.GONE + llMedia.visibility = if (!is_shown) View.GONE else View.VISIBLE + val sb = StringBuilder() + setMedia(media_attachments, sb, ivMedia1, 0) + setMedia(media_attachments, sb, ivMedia2, 1) + setMedia(media_attachments, sb, ivMedia3, 2) + setMedia(media_attachments, sb, ivMedia4, 3) + if (sb.isNotEmpty()) { + tvMediaDescription.visibility = View.VISIBLE + tvMediaDescription.text = sb + } + + setIconDrawableId( activity, btnHideMedia, R.drawable.ic_close, color = content_color, alphaMultiplier = Styler.boost_alpha ) - } - - buttons_for_status?.hide() - - tvApplication.visibility = View.GONE - - } catch(ex : Throwable) { - - } - llSearchTag.visibility = View.VISIBLE - btnSearchTag.text = activity.getString(R.string.scheduled_status) + " " + - TootStatus.formatTime( + } + + buttons_for_status?.hide() + + tvApplication.visibility = View.GONE + + } catch (ex: Throwable) { + + } + llSearchTag.visibility = View.VISIBLE + btnSearchTag.text = activity.getString(R.string.scheduled_status) + " " + + TootStatus.formatTime( activity, item.timeScheduledAt, true ) - } - - private fun removeExtraView() { - llExtra.scan { v -> - if(v is MyNetworkImageView) { - v.cancelLoading() - } - } - llExtra.removeAllViews() - - for(invalidator in extra_invalidator_list) { - invalidator.register(null) - } - extra_invalidator_list.clear() - - } - - private fun showConversationIcons(cs : TootConversationSummary) { - - val last_account_id = cs.last_status.account.id - - val accountsOther = cs.accounts.filter { it.get().id != last_account_id } - if(accountsOther.isNotEmpty()) { - llConversationIcons.visibility = View.VISIBLE - - val size = accountsOther.size - - tvConversationParticipants.text = if(size <= 1) { - activity.getString(R.string.conversation_to) - } else { - activity.getString(R.string.participants) - } - - fun showIcon(iv : MyNetworkImageView, idx : Int) { - val bShown = idx < size - iv.visibility = if(bShown) View.VISIBLE else View.GONE - if(! bShown) return - - val who = accountsOther[idx].get() - iv.setImageUrl( + } + + private fun removeExtraView() { + llExtra.scan { v -> + if (v is MyNetworkImageView) { + v.cancelLoading() + } + } + llExtra.removeAllViews() + + for (invalidator in extra_invalidator_list) { + invalidator.register(null) + } + extra_invalidator_list.clear() + + } + + private fun showConversationIcons(cs: TootConversationSummary) { + + val last_account_id = cs.last_status.account.id + + val accountsOther = cs.accounts.filter { it.get().id != last_account_id } + if (accountsOther.isNotEmpty()) { + llConversationIcons.visibility = View.VISIBLE + + val size = accountsOther.size + + tvConversationParticipants.text = if (size <= 1) { + activity.getString(R.string.conversation_to) + } else { + activity.getString(R.string.participants) + } + + fun showIcon(iv: MyNetworkImageView, idx: Int) { + val bShown = idx < size + iv.visibility = if (bShown) View.VISIBLE else View.GONE + if (!bShown) return + + val who = accountsOther[idx].get() + iv.setImageUrl( activity.pref, Styler.calcIconRound(iv.layoutParams), access_info.supplyBaseUrl(who.avatar_static), access_info.supplyBaseUrl(who.avatar) ) - } - showIcon(ivConversationIcon1, 0) - showIcon(ivConversationIcon2, 1) - showIcon(ivConversationIcon3, 2) - showIcon(ivConversationIcon4, 3) - - tvConversationIconsMore.text = when { - size <= 4 -> "" - else -> activity.getString(R.string.participants_and_more) - } - } - - if(cs.last_status.in_reply_to_id != null) { - llSearchTag.visibility = View.VISIBLE - btnSearchTag.text = activity.getString(R.string.show_conversation) - } - } - - private fun openConversationSummary() { - val cs = item as? TootConversationSummary ?: return - - if(cs.unread) { - cs.unread = false - // 表示の更新 - list_adapter.notifyChange( + } + showIcon(ivConversationIcon1, 0) + showIcon(ivConversationIcon2, 1) + showIcon(ivConversationIcon3, 2) + showIcon(ivConversationIcon4, 3) + + tvConversationIconsMore.text = when { + size <= 4 -> "" + else -> activity.getString(R.string.participants_and_more) + } + } + + if (cs.last_status.in_reply_to_id != null) { + llSearchTag.visibility = View.VISIBLE + btnSearchTag.text = activity.getString(R.string.show_conversation) + } + } + + private fun openConversationSummary() { + val cs = item as? TootConversationSummary ?: return + + if (cs.unread) { + cs.unread = false + // 表示の更新 + list_adapter.notifyChange( reason = "ConversationSummary reset unread", reset = true ) - // 未読フラグのクリアをサーバに送る - Action_Toot.clearConversationUnread(activity, access_info, cs) - } - - Action_Toot.conversation( + // 未読フラグのクリアをサーバに送る + Action_Toot.clearConversationUnread(activity, access_info, cs) + } + + Action_Toot.conversation( activity, activity.nextPosition(column), access_info, cs.last_status ) - } - - private fun showStatusOrReply(item : TootStatus, colorBgArg : Int = 0) { - var colorBg = colorBgArg - val reply = item.reply - val in_reply_to_id = item.in_reply_to_id - val in_reply_to_account_id = item.in_reply_to_account_id - when { - reply != null -> { - showReply(reply, R.drawable.ic_reply, R.string.reply_to) - if(colorBgArg == 0) colorBg = Pref.ipEventBgColorMention(activity.pref) - } - - in_reply_to_id != null && in_reply_to_account_id != null -> { - showReply(item, in_reply_to_account_id) - if(colorBgArg == 0) colorBg = Pref.ipEventBgColorMention(activity.pref) - } - } - showStatus(item, colorBg) - } - - private fun showMessageHolder(item : TootMessageHolder) { - tvMessageHolder.visibility = View.VISIBLE - tvMessageHolder.text = item.text - tvMessageHolder.gravity = item.gravity - } - - private fun showNotification(n : TootNotification) { - val n_status = n.status - val n_accountRef = n.accountRef - val n_account = n_accountRef?.get() - - fun showNotificationStatus(item : TootStatus, colorBgDefault : Int) { - val reblog = item.reblog - when { - reblog == null -> showStatusOrReply(item, colorBgDefault) - - item.isQuoteToot -> { - // 引用Renote - showReply(reblog, R.drawable.ic_repeat, R.string.quote_to) - showStatus(item, Pref.ipEventBgColorQuote(activity.pref)) - } - - else -> { - // 通常のブースト。引用なしブースト。 - // ブースト表示は通知イベントと被るのでしない - showStatusOrReply(reblog, Pref.ipEventBgColorBoost(activity.pref)) - } - - } - } - - when(n.type) { - + } + + private fun showStatusOrReply(item: TootStatus, colorBgArg: Int = 0) { + var colorBg = colorBgArg + val reply = item.reply + val in_reply_to_id = item.in_reply_to_id + val in_reply_to_account_id = item.in_reply_to_account_id + when { + reply != null -> { + showReply(reply, R.drawable.ic_reply, R.string.reply_to) + if (colorBgArg == 0) colorBg = Pref.ipEventBgColorMention(activity.pref) + } + + in_reply_to_id != null && in_reply_to_account_id != null -> { + showReply(item, in_reply_to_account_id) + if (colorBgArg == 0) colorBg = Pref.ipEventBgColorMention(activity.pref) + } + } + showStatus(item, colorBg) + } + + private fun showMessageHolder(item: TootMessageHolder) { + tvMessageHolder.visibility = View.VISIBLE + tvMessageHolder.text = item.text + tvMessageHolder.gravity = item.gravity + } + + private fun showNotification(n: TootNotification) { + val n_status = n.status + val n_accountRef = n.accountRef + val n_account = n_accountRef?.get() + + fun showNotificationStatus(item: TootStatus, colorBgDefault: Int) { + val reblog = item.reblog + when { + reblog == null -> showStatusOrReply(item, colorBgDefault) + + item.isQuoteToot -> { + // 引用Renote + showReply(reblog, R.drawable.ic_repeat, R.string.quote_to) + showStatus(item, Pref.ipEventBgColorQuote(activity.pref)) + } + + else -> { + // 通常のブースト。引用なしブースト。 + // ブースト表示は通知イベントと被るのでしない + showStatusOrReply(reblog, Pref.ipEventBgColorBoost(activity.pref)) + } + + } + } + + when (n.type) { + TootNotification.TYPE_FAVOURITE -> { val colorBg = Pref.ipEventBgColorFavourite(activity.pref) - if(n_account != null) showBoost( + if (n_account != null) showBoost( n_accountRef, n.time_created_at, - if(access_info.isNicoru(n_account)) R.drawable.ic_nicoru else R.drawable.ic_star, + if (access_info.isNicoru(n_account)) R.drawable.ic_nicoru else R.drawable.ic_star, R.string.display_name_favourited_by ) - if(n_status != null) { + if (n_status != null) { showNotificationStatus(n_status, colorBg) } } - + TootNotification.TYPE_REBLOG -> { val colorBg = Pref.ipEventBgColorBoost(activity.pref) - if(n_account != null) showBoost( + if (n_account != null) showBoost( n_accountRef, n.time_created_at, R.drawable.ic_repeat, R.string.display_name_boosted_by, boost_status = n_status ) - if(n_status != null) { + if (n_status != null) { showNotificationStatus(n_status, colorBg) } - + } - + TootNotification.TYPE_RENOTE -> { // 引用のないreblog val colorBg = Pref.ipEventBgColorBoost(activity.pref) - if(n_account != null) showBoost( + if (n_account != null) showBoost( n_accountRef, n.time_created_at, R.drawable.ic_repeat, R.string.display_name_boosted_by, boost_status = n_status ) - if(n_status != null) { + if (n_status != null) { showNotificationStatus(n_status, colorBg) } } - + TootNotification.TYPE_FOLLOW -> { val colorBg = Pref.ipEventBgColorFollow(activity.pref) - if(n_account != null) { + if (n_account != null) { showBoost( n_accountRef, n.time_created_at, @@ -862,13 +862,13 @@ internal class ItemViewHolder( R.string.display_name_followed_by ) showAccount(n_accountRef) - if(colorBg != 0) this.viewRoot.backgroundColor = colorBg + if (colorBg != 0) this.viewRoot.backgroundColor = colorBg } } - + TootNotification.TYPE_UNFOLLOW -> { val colorBg = Pref.ipEventBgColorUnfollow(activity.pref) - if(n_account != null) { + if (n_account != null) { showBoost( n_accountRef, n.time_created_at, @@ -876,24 +876,24 @@ internal class ItemViewHolder( R.string.display_name_unfollowed_by ) showAccount(n_accountRef) - if(colorBg != 0) this.viewRoot.backgroundColor = colorBg + if (colorBg != 0) this.viewRoot.backgroundColor = colorBg } } - + TootNotification.TYPE_MENTION, TootNotification.TYPE_REPLY -> { val colorBg = Pref.ipEventBgColorMention(activity.pref) - if(! bSimpleList && ! access_info.isMisskey) { + if (!bSimpleList && !access_info.isMisskey) { when { n_account == null -> { - + } - + n_status?.in_reply_to_id != null || n_status?.reply != null -> { // トゥート内部に「~への返信」を表示するので、 // 通知イベントの「~からの返信」は表示しない } - + else -> // 返信ではなくメンションの場合は「~からの返信」を表示する showBoost( n_accountRef, @@ -903,66 +903,66 @@ internal class ItemViewHolder( ) } } - if(n_status != null) { + if (n_status != null) { showNotificationStatus(n_status, colorBg) } } - + TootNotification.TYPE_REACTION -> { val colorBg = Pref.ipEventBgColorReaction(activity.pref) - if(n_account != null) showBoost( + if (n_account != null) showBoost( n_accountRef, n.time_created_at, R.drawable.ic_face, R.string.display_name_reaction_by, misskeyReaction = n.reaction ?: "?" ) - if(n_status != null) { + if (n_status != null) { showNotificationStatus(n_status, colorBg) } } - + TootNotification.TYPE_QUOTE -> { val colorBg = Pref.ipEventBgColorQuote(activity.pref) - if(n_account != null) showBoost( + if (n_account != null) showBoost( n_accountRef, n.time_created_at, R.drawable.ic_repeat, R.string.display_name_quoted_by ) - if(n_status != null) { + if (n_status != null) { showNotificationStatus(n_status, colorBg) } } - + TootNotification.TYPE_STATUS -> { val colorBg = Pref.ipEventBgColorStatus(activity.pref) - if(n_account != null) showBoost( + if (n_account != null) showBoost( n_accountRef, n.time_created_at, - if(n_status == null) { + if (n_status == null) { R.drawable.ic_question } else { Styler.getVisibilityIconId(access_info.isMisskey, n_status.visibility) }, R.string.display_name_posted_by ) - if(n_status != null) { + if (n_status != null) { showNotificationStatus(n_status, colorBg) } } - + TootNotification.TYPE_FOLLOW_REQUEST, TootNotification.TYPE_FOLLOW_REQUEST_MISSKEY -> { val colorBg = Pref.ipEventBgColorFollowRequest(activity.pref) - if(n_account != null) { + if (n_account != null) { showBoost( n_accountRef, n.time_created_at, R.drawable.ic_follow_wait, R.string.display_name_follow_request_by ) - if(colorBg != 0) this.viewRoot.backgroundColor = colorBg + if (colorBg != 0) this.viewRoot.backgroundColor = colorBg boostedAction = { activity.addColumn( activity.nextPosition(column), access_info, ColumnType.FOLLOW_REQUESTS @@ -970,10 +970,10 @@ internal class ItemViewHolder( } } } - + TootNotification.TYPE_FOLLOW_REQUEST_ACCEPTED_MISSKEY -> { val colorBg = Pref.ipEventBgColorFollow(activity.pref) - if(n_account != null) { + if (n_account != null) { showBoost( n_accountRef, n.time_created_at, @@ -981,198 +981,198 @@ internal class ItemViewHolder( R.string.display_name_follow_request_accepted_by ) showAccount(n_accountRef) - if(colorBg != 0) this.viewRoot.backgroundColor = colorBg + if (colorBg != 0) this.viewRoot.backgroundColor = colorBg } } - + TootNotification.TYPE_VOTE, TootNotification.TYPE_POLL_VOTE_MISSKEY -> { val colorBg = Pref.ipEventBgColorVote(activity.pref) - if(n_account != null) showBoost( + if (n_account != null) showBoost( n_accountRef, n.time_created_at, R.drawable.ic_vote, R.string.display_name_voted_by ) - if(n_status != null) { + if (n_status != null) { showNotificationStatus(n_status, colorBg) } } - + TootNotification.TYPE_POLL -> { val colorBg = 0 - if(n_account != null) showBoost( + if (n_account != null) showBoost( n_accountRef, n.time_created_at, R.drawable.ic_vote, R.string.end_of_polling_from ) - if(n_status != null) { + if (n_status != null) { showNotificationStatus(n_status, colorBg) } } - - else -> { - val colorBg = 0 - if(n_account != null) showBoost( + + else -> { + val colorBg = 0 + if (n_account != null) showBoost( n_accountRef, n.time_created_at, R.drawable.ic_question, R.string.unknown_notification_from ) - if(n_status != null) { - showNotificationStatus(n_status, colorBg) - } - tvMessageHolder.visibility = View.VISIBLE - tvMessageHolder.text = "notification type is ${n.type}" - tvMessageHolder.gravity = Gravity.CENTER - } - } - } - - private fun showList(list : TootList) { - llList.visibility = View.VISIBLE - btnListTL.text = list.title - btnListTL.textColor = content_color - btnListMore.imageTintList = content_color_csl - } - - private fun showAntenna(a : MisskeyAntenna) { - llList.visibility = View.VISIBLE - btnListTL.text = a.name - btnListTL.textColor = content_color - btnListMore.imageTintList = content_color_csl - } - - private fun showDomainBlock(domain_block : TootDomainBlock) { - llSearchTag.visibility = View.VISIBLE - btnSearchTag.text = domain_block.domain.pretty - } - - private fun showFilter(filter : TootFilter) { - llFilter.visibility = View.VISIBLE - tvFilterPhrase.text = filter.phrase - - val sb = StringBuffer() - // - sb.append(activity.getString(R.string.filter_context)) - .append(": ") - .append(filter.getContextNames(activity).joinToString("/")) - // - val flags = ArrayList() - if(filter.irreversible) flags.add(activity.getString(R.string.filter_irreversible)) - if(filter.whole_word) flags.add(activity.getString(R.string.filter_word_match)) - if(flags.isNotEmpty()) { - sb.append('\n') - .append(flags.joinToString(", ")) - } - // - if(filter.time_expires_at != 0L) { - sb.append('\n') - .append(activity.getString(R.string.filter_expires_at)) - .append(": ") - .append(TootStatus.formatTime(activity, filter.time_expires_at, false)) - } - - tvFilterDetail.text = sb.toString() - } - - private fun showSearchTag(tag : TootTag) { - if(tag.history?.isNotEmpty() == true) { - llTrendTag.visibility = View.VISIBLE - tvTrendTagName.text = "#${tag.name}" - tvTrendTagDesc.text = - activity.getString(R.string.people_talking, tag.accountDaily, tag.accountWeekly) - tvTrendTagCount.text = "${tag.countDaily}(${tag.countWeekly})" - cvTagHistory.setHistory(tag.history) - } else { - llSearchTag.visibility = View.VISIBLE - btnSearchTag.text = "#" + tag.name - - } - } - - private fun showGap() { - llSearchTag.visibility = View.VISIBLE - btnSearchTag.text = activity.getString(R.string.read_gap) - - btnGapHead.vg(column.type.gapDirection(column, true)) - ?.imageTintList = content_color_csl - - btnGapTail.vg(column.type.gapDirection(column, false)) - ?.imageTintList = content_color_csl - - val c = Pref.ipEventBgColorGap(App1.pref) - if(c != 0) this.viewRoot.backgroundColor = c - } - - private fun showSearchGap(item : TootSearchGap) { - llSearchTag.visibility = View.VISIBLE - btnSearchTag.text = activity.getString( - when(item.type) { + if (n_status != null) { + showNotificationStatus(n_status, colorBg) + } + tvMessageHolder.visibility = View.VISIBLE + tvMessageHolder.text = "notification type is ${n.type}" + tvMessageHolder.gravity = Gravity.CENTER + } + } + } + + private fun showList(list: TootList) { + llList.visibility = View.VISIBLE + btnListTL.text = list.title + btnListTL.textColor = content_color + btnListMore.imageTintList = content_color_csl + } + + private fun showAntenna(a: MisskeyAntenna) { + llList.visibility = View.VISIBLE + btnListTL.text = a.name + btnListTL.textColor = content_color + btnListMore.imageTintList = content_color_csl + } + + private fun showDomainBlock(domain_block: TootDomainBlock) { + llSearchTag.visibility = View.VISIBLE + btnSearchTag.text = domain_block.domain.pretty + } + + private fun showFilter(filter: TootFilter) { + llFilter.visibility = View.VISIBLE + tvFilterPhrase.text = filter.phrase + + val sb = StringBuffer() + // + sb.append(activity.getString(R.string.filter_context)) + .append(": ") + .append(filter.getContextNames(activity).joinToString("/")) + // + val flags = ArrayList() + if (filter.irreversible) flags.add(activity.getString(R.string.filter_irreversible)) + if (filter.whole_word) flags.add(activity.getString(R.string.filter_word_match)) + if (flags.isNotEmpty()) { + sb.append('\n') + .append(flags.joinToString(", ")) + } + // + if (filter.time_expires_at != 0L) { + sb.append('\n') + .append(activity.getString(R.string.filter_expires_at)) + .append(": ") + .append(TootStatus.formatTime(activity, filter.time_expires_at, false)) + } + + tvFilterDetail.text = sb.toString() + } + + private fun showSearchTag(tag: TootTag) { + if (tag.history?.isNotEmpty() == true) { + llTrendTag.visibility = View.VISIBLE + tvTrendTagName.text = "#${tag.name}" + tvTrendTagDesc.text = + activity.getString(R.string.people_talking, tag.accountDaily, tag.accountWeekly) + tvTrendTagCount.text = "${tag.countDaily}(${tag.countWeekly})" + cvTagHistory.setHistory(tag.history) + } else { + llSearchTag.visibility = View.VISIBLE + btnSearchTag.text = "#" + tag.name + + } + } + + private fun showGap() { + llSearchTag.visibility = View.VISIBLE + btnSearchTag.text = activity.getString(R.string.read_gap) + + btnGapHead.vg(column.type.gapDirection(column, true)) + ?.imageTintList = content_color_csl + + btnGapTail.vg(column.type.gapDirection(column, false)) + ?.imageTintList = content_color_csl + + val c = Pref.ipEventBgColorGap(App1.pref) + if (c != 0) this.viewRoot.backgroundColor = c + } + + private fun showSearchGap(item: TootSearchGap) { + llSearchTag.visibility = View.VISIBLE + btnSearchTag.text = activity.getString( + when (item.type) { TootSearchGap.SearchType.Hashtag -> R.string.read_more_hashtag TootSearchGap.SearchType.Account -> R.string.read_more_account TootSearchGap.SearchType.Status -> R.string.read_more_status } ) - } - - private fun showReply(iconId : Int, text : Spannable) { - - llReply.visibility = View.VISIBLE - - - setIconDrawableId( + } + + private fun showReply(iconId: Int, text: Spannable) { + + llReply.visibility = View.VISIBLE + + + setIconDrawableId( activity, ivReply, iconId, color = content_color, alphaMultiplier = Styler.boost_alpha ) - - tvReply.text = text - reply_invalidator.register(text) - } - - private fun showReply(reply : TootStatus, iconId : Int, stringId : Int) { - status_reply = reply - showReply( + + tvReply.text = text + reply_invalidator.register(text) + } + + private fun showReply(reply: TootStatus, iconId: Int, stringId: Int) { + status_reply = reply + showReply( iconId, reply.accountRef.decoded_display_name.intoStringResource(activity, stringId) ) - } - - private fun showReply(reply : TootStatus, accountId : EntityId) { - val name = if(accountId == reply.account.id) { - // 自己レスなら - AcctColor.getNicknameWithColor(access_info, reply.account) - } else { - val m = reply.mentions?.find { it.id == accountId } - if(m != null) { - AcctColor.getNicknameWithColor(access_info.getFullAcct(m.acct)) - } else { - SpannableString("ID(${accountId})") - } - } - - val text = name.intoStringResource(activity, R.string.reply_to) - showReply(R.drawable.ic_reply, text) - - // tootsearchはreplyオブジェクトがなくin_reply_toだけが提供される場合があるが - // tootsearchではどのタンスから読んだか分からないのでin_reply_toのIDも信用できない - } - - private fun showBoost( - whoRef : TootAccountRef, - time : Long, - iconId : Int, - string_id : Int, - misskeyReaction : String? = null, - boost_status : TootStatus? = null - ) { - boost_account = whoRef + } - setIconDrawableId( + private fun showReply(reply: TootStatus, accountId: EntityId) { + val name = if (accountId == reply.account.id) { + // 自己レスなら + AcctColor.getNicknameWithColor(access_info, reply.account) + } else { + val m = reply.mentions?.find { it.id == accountId } + if (m != null) { + AcctColor.getNicknameWithColor(access_info.getFullAcct(m.acct)) + } else { + SpannableString("ID(${accountId})") + } + } + + val text = name.intoStringResource(activity, R.string.reply_to) + showReply(R.drawable.ic_reply, text) + + // tootsearchはreplyオブジェクトがなくin_reply_toだけが提供される場合があるが + // tootsearchではどのタンスから読んだか分からないのでin_reply_toのIDも信用できない + } + + private fun showBoost( + whoRef: TootAccountRef, + time: Long, + iconId: Int, + string_id: Int, + misskeyReaction: String? = null, + boost_status: TootStatus? = null + ) { + boost_account = whoRef + + setIconDrawableId( activity, ivBoosted, iconId, @@ -1180,55 +1180,55 @@ internal class ItemViewHolder( alphaMultiplier = Styler.boost_alpha ) - val who = whoRef.get() + val who = whoRef.get() - // フォローの場合 decoded_display_name が2箇所で表示に使われるのを避ける必要がある - val text : Spannable = if( misskeyReaction != null){ - val options = DecodeOptions( + // フォローの場合 decoded_display_name が2箇所で表示に使われるのを避ける必要がある + val text: Spannable = if (misskeyReaction != null) { + val options = DecodeOptions( activity, access_info, decodeEmoji = true, enlargeEmoji = 1.5f, enlargeCustomEmoji = 1.5f ) - val ssb = MisskeyReaction.toSpannableStringBuilder(misskeyReaction,options,boost_status) - ssb.append(" ") - ssb.append(who.decodeDisplayName(activity) + val ssb = MisskeyReaction.toSpannableStringBuilder(misskeyReaction, options, boost_status) + ssb.append(" ") + ssb.append(who.decodeDisplayName(activity) .intoStringResource(activity, string_id)) - } else { - who.decodeDisplayName(activity) - .intoStringResource(activity, string_id) - } + } else { + who.decodeDisplayName(activity) + .intoStringResource(activity, string_id) + } - boost_time = time - llBoosted.visibility = View.VISIBLE - showStatusTime(activity, tvBoostedTime, who, time = time, status = boost_status) - tvBoosted.text = text - boost_invalidator.register(text) - setAcct(tvBoostedAcct, access_info, who) - } - - private fun showAccount(whoRef : TootAccountRef) { - - follow_account = whoRef - val who = whoRef.get() - llFollow.visibility = View.VISIBLE - ivFollow.setImageUrl( + boost_time = time + llBoosted.visibility = View.VISIBLE + showStatusTime(activity, tvBoostedTime, who, time = time, status = boost_status) + tvBoosted.text = text + boost_invalidator.register(text) + setAcct(tvBoostedAcct, access_info, who) + } + + private fun showAccount(whoRef: TootAccountRef) { + + follow_account = whoRef + val who = whoRef.get() + llFollow.visibility = View.VISIBLE + ivFollow.setImageUrl( activity.pref, Styler.calcIconRound(ivFollow.layoutParams), access_info.supplyBaseUrl(who.avatar_static), access_info.supplyBaseUrl(who.avatar) ) - - tvFollowerName.text = whoRef.decoded_display_name - follow_invalidator.register(whoRef.decoded_display_name) - - setAcct(tvFollowerAcct, access_info, who) - - who.setAccountExtra(access_info, tvLastStatusAt, lastActive_invalidator) - - val relation = UserRelation.load(access_info.db_id, who.id) - Styler.setFollowIcon( + + tvFollowerName.text = whoRef.decoded_display_name + follow_invalidator.register(whoRef.decoded_display_name) + + setAcct(tvFollowerAcct, access_info, who) + + who.setAccountExtra(access_info, tvLastStatusAt, lastActive_invalidator) + + val relation = UserRelation.load(access_info.db_id, who.id) + Styler.setFollowIcon( activity, btnFollow, ivFollowedBy, @@ -1237,354 +1237,354 @@ internal class ItemViewHolder( content_color, alphaMultiplier = Styler.boost_alpha ) - - if(column.type == ColumnType.FOLLOW_REQUESTS) { - llFollowRequest.visibility = View.VISIBLE - btnFollowRequestAccept.imageTintList = content_color_csl - btnFollowRequestDeny.imageTintList = content_color_csl - } - } - - private fun showStatus(status : TootStatus, colorBg : Int = 0) { - - val filteredWord = status.filteredWord - if(filteredWord != null) { - showMessageHolder( + + if (column.type == ColumnType.FOLLOW_REQUESTS) { + llFollowRequest.visibility = View.VISIBLE + btnFollowRequestAccept.imageTintList = content_color_csl + btnFollowRequestDeny.imageTintList = content_color_csl + } + } + + private fun showStatus(status: TootStatus, colorBg: Int = 0) { + + val filteredWord = status.filteredWord + if (filteredWord != null) { + showMessageHolder( TootMessageHolder( - if(Pref.bpShowFilteredWord(activity.pref)) { + if (Pref.bpShowFilteredWord(activity.pref)) { "${activity.getString(R.string.filtered)} / $filteredWord" } else { activity.getString(R.string.filtered) } ) ) - return - } - - this.status_showing = status - llStatus.visibility = View.VISIBLE - - if(status.conversation_main) { - - val conversationMainBgColor = - Pref.ipConversationMainTootBgColor(activity.pref).notZero() - ?: (activity.getAttributeColor(R.attr.colorImageButtonAccent) and 0xffffff) or 0x20000000 - - this.viewRoot.setBackgroundColor(conversationMainBgColor) - - } else { - val c = colorBg.notZero() - - ?: when(status.bookmarked) { + return + } + + this.status_showing = status + llStatus.visibility = View.VISIBLE + + if (status.conversation_main) { + + val conversationMainBgColor = + Pref.ipConversationMainTootBgColor(activity.pref).notZero() + ?: (activity.attrColor(R.attr.colorImageButtonAccent) and 0xffffff) or 0x20000000 + + this.viewRoot.setBackgroundColor(conversationMainBgColor) + + } else { + val c = colorBg.notZero() + + ?: when (status.bookmarked) { true -> Pref.ipEventBgColorBookmark(App1.pref) false -> 0 - }.notZero() - - ?: when(status.getBackgroundColorType(access_info)) { + }.notZero() + + ?: when (status.getBackgroundColorType(access_info)) { TootVisibility.UnlistedHome -> toot_color_unlisted TootVisibility.PrivateFollowers -> toot_color_follower TootVisibility.DirectSpecified -> toot_color_direct_user TootVisibility.DirectPrivate -> toot_color_direct_me - else -> 0 - } - - if(c != 0) { - this.viewRoot.backgroundColor = c - } - } - - showStatusTime(activity, tvTime, who = status.account, status = status) - - val whoRef = status.accountRef - val who = whoRef.get() - this.status_account = whoRef - - setAcct(tvAcct, access_info, who) - - // if(who == null) { - // tvName.text = "?" - // name_invalidator.register(null) - // ivThumbnail.setImageUrl(activity.pref, 16f, null, null) - // } else { - tvName.text = whoRef.decoded_display_name - name_invalidator.register(whoRef.decoded_display_name) - ivThumbnail.setImageUrl( + else -> 0 + } + + if (c != 0) { + this.viewRoot.backgroundColor = c + } + } + + showStatusTime(activity, tvTime, who = status.account, status = status) + + val whoRef = status.accountRef + val who = whoRef.get() + this.status_account = whoRef + + setAcct(tvAcct, access_info, who) + + // if(who == null) { + // tvName.text = "?" + // name_invalidator.register(null) + // ivThumbnail.setImageUrl(activity.pref, 16f, null, null) + // } else { + tvName.text = whoRef.decoded_display_name + name_invalidator.register(whoRef.decoded_display_name) + ivThumbnail.setImageUrl( activity.pref, Styler.calcIconRound(ivThumbnail.layoutParams), access_info.supplyBaseUrl(who.avatar_static), access_info.supplyBaseUrl(who.avatar) ) - // } - - showOpenSticker(who) - - var content = status.decoded_content - - // ニコフレのアンケートの表示 - val enquete = status.enquete - when { - enquete == null -> { - } - - enquete.pollType == TootPollsType.FriendsNico && enquete.type != TootPolls.TYPE_ENQUETE -> { - // フレニコの投票の結果表示は普通にテキストを表示するだけでよい - } - - else -> { - - // アンケートの本文を上書きする - val question = enquete.decoded_question - if(question.isNotBlank()) content = question - - showEnqueteItems(status, enquete) - - } - } - - showPreviewCard(status) - - // if( status.decoded_tags == null ){ - // tvTags.setVisibility( View.GONE ); - // }else{ - // tvTags.setVisibility( View.VISIBLE ); - // tvTags.setText( status.decoded_tags ); - // } - - if(status.decoded_mentions.isEmpty()) { - tvMentions.visibility = View.GONE - } else { - tvMentions.visibility = View.VISIBLE - tvMentions.text = status.decoded_mentions - } - - if(status.time_deleted_at > 0L) { - val s = SpannableStringBuilder() - .append('(') - .append( + // } + + showOpenSticker(who) + + var content = status.decoded_content + + // ニコフレのアンケートの表示 + val enquete = status.enquete + when { + enquete == null -> { + } + + enquete.pollType == TootPollsType.FriendsNico && enquete.type != TootPolls.TYPE_ENQUETE -> { + // フレニコの投票の結果表示は普通にテキストを表示するだけでよい + } + + else -> { + + // アンケートの本文を上書きする + val question = enquete.decoded_question + if (question.isNotBlank()) content = question + + showEnqueteItems(status, enquete) + + } + } + + showPreviewCard(status) + + // if( status.decoded_tags == null ){ + // tvTags.setVisibility( View.GONE ); + // }else{ + // tvTags.setVisibility( View.VISIBLE ); + // tvTags.setText( status.decoded_tags ); + // } + + if (status.decoded_mentions.isEmpty()) { + tvMentions.visibility = View.GONE + } else { + tvMentions.visibility = View.VISIBLE + tvMentions.text = status.decoded_mentions + } + + if (status.time_deleted_at > 0L) { + val s = SpannableStringBuilder() + .append('(') + .append( activity.getString( R.string.deleted_at, TootStatus.formatTime(activity, status.time_deleted_at, true) ) ) - .append(')') - content = s - } - - tvContent.text = content - content_invalidator.register(content) - - activity.checkAutoCW(status, content) - val r = status.auto_cw - - tvContent.minLines = r?.originalLineCount ?: - 1 - - val decoded_spoiler_text = status.decoded_spoiler_text - when { - decoded_spoiler_text.isNotEmpty() -> { - // 元データに含まれるContent Warning を使う - llContentWarning.visibility = View.VISIBLE - tvContentWarning.text = status.decoded_spoiler_text - spoiler_invalidator.register(status.decoded_spoiler_text) - val cw_shown = ContentWarning.isShown(status, access_info.expand_cw) - showContent(cw_shown) - } - - r?.decoded_spoiler_text != null -> { - // 自動CW - llContentWarning.visibility = View.VISIBLE - tvContentWarning.text = r.decoded_spoiler_text - spoiler_invalidator.register(r.decoded_spoiler_text) - val cw_shown = ContentWarning.isShown(status, access_info.expand_cw) - showContent(cw_shown) - } - - else -> { - // CWしない - llContentWarning.visibility = View.GONE - llContents.visibility = View.VISIBLE - } - } - - val media_attachments = status.media_attachments - if(media_attachments == null || media_attachments.isEmpty()) { - flMedia.visibility = View.GONE - llMedia.visibility = View.GONE - btnShowMedia.visibility = View.GONE - } else { - flMedia.visibility = View.VISIBLE - - // hide sensitive media - val default_shown = when { - column.hide_media_default -> false - access_info.dont_hide_nsfw -> true - else -> ! status.sensitive - } - val is_shown = MediaShown.isShown(status, default_shown) - - btnShowMedia.visibility = if(! is_shown) View.VISIBLE else View.GONE - llMedia.visibility = if(! is_shown) View.GONE else View.VISIBLE - val sb = StringBuilder() - setMedia(media_attachments, sb, ivMedia1, 0) - setMedia(media_attachments, sb, ivMedia2, 1) - setMedia(media_attachments, sb, ivMedia3, 2) - setMedia(media_attachments, sb, ivMedia4, 3) - - val m0 = - if(media_attachments.isEmpty()) null else media_attachments[0] as? TootAttachment - btnShowMedia.blurhash = m0?.blurhash - - if(sb.isNotEmpty()) { - tvMediaDescription.visibility = View.VISIBLE - tvMediaDescription.text = sb - } - - setIconDrawableId( + .append(')') + content = s + } + + tvContent.text = content + content_invalidator.register(content) + + activity.checkAutoCW(status, content) + val r = status.auto_cw + + tvContent.minLines = r?.originalLineCount ?: -1 + + val decoded_spoiler_text = status.decoded_spoiler_text + when { + decoded_spoiler_text.isNotEmpty() -> { + // 元データに含まれるContent Warning を使う + llContentWarning.visibility = View.VISIBLE + tvContentWarning.text = status.decoded_spoiler_text + spoiler_invalidator.register(status.decoded_spoiler_text) + val cw_shown = ContentWarning.isShown(status, access_info.expand_cw) + showContent(cw_shown) + } + + r?.decoded_spoiler_text != null -> { + // 自動CW + llContentWarning.visibility = View.VISIBLE + tvContentWarning.text = r.decoded_spoiler_text + spoiler_invalidator.register(r.decoded_spoiler_text) + val cw_shown = ContentWarning.isShown(status, access_info.expand_cw) + showContent(cw_shown) + } + + else -> { + // CWしない + llContentWarning.visibility = View.GONE + llContents.visibility = View.VISIBLE + } + } + + val media_attachments = status.media_attachments + if (media_attachments == null || media_attachments.isEmpty()) { + flMedia.visibility = View.GONE + llMedia.visibility = View.GONE + btnShowMedia.visibility = View.GONE + } else { + flMedia.visibility = View.VISIBLE + + // hide sensitive media + val default_shown = when { + column.hide_media_default -> false + access_info.dont_hide_nsfw -> true + else -> !status.sensitive + } + val is_shown = MediaShown.isShown(status, default_shown) + + btnShowMedia.visibility = if (!is_shown) View.VISIBLE else View.GONE + llMedia.visibility = if (!is_shown) View.GONE else View.VISIBLE + val sb = StringBuilder() + setMedia(media_attachments, sb, ivMedia1, 0) + setMedia(media_attachments, sb, ivMedia2, 1) + setMedia(media_attachments, sb, ivMedia3, 2) + setMedia(media_attachments, sb, ivMedia4, 3) + + val m0 = + if (media_attachments.isEmpty()) null else media_attachments[0] as? TootAttachment + btnShowMedia.blurhash = m0?.blurhash + + if (sb.isNotEmpty()) { + tvMediaDescription.visibility = View.VISIBLE + tvMediaDescription.text = sb + } + + setIconDrawableId( activity, btnHideMedia, R.drawable.ic_close, color = content_color, alphaMultiplier = Styler.boost_alpha ) - } - - makeReactionsView(status) - - buttons_for_status?.bind(status, (item as? TootNotification)) - - var sb : StringBuilder? = null - - fun prepareSb() : StringBuilder = - sb?.append(", ") ?: StringBuilder().also { sb = it } - - val application = status.application - if(application != null && - (column.type == ColumnType.CONVERSATION || Pref.bpShowAppName(activity.pref)) - ) { - prepareSb().append(activity.getString(R.string.application_is, application.name ?: "")) - } - - val language = status.language - if(language != null && - (column.type == ColumnType.CONVERSATION || Pref.bpShowLanguage(activity.pref)) - ) { - prepareSb().append(activity.getString(R.string.language_is, language)) - } - - tvApplication.vg(sb != null)?.text = sb - } - - private fun showOpenSticker(who : TootAccount) { - try { - if(! Column.showOpenSticker) return - - val host = who.apDomain - - // LTLでホスト名が同じならTickerを表示しない - when(column.type) { + } + + makeReactionsView(status) + + buttons_for_status?.bind(status, (item as? TootNotification)) + + var sb: StringBuilder? = null + + fun prepareSb(): StringBuilder = + sb?.append(", ") ?: StringBuilder().also { sb = it } + + val application = status.application + if (application != null && + (column.type == ColumnType.CONVERSATION || Pref.bpShowAppName(activity.pref)) + ) { + prepareSb().append(activity.getString(R.string.application_is, application.name ?: "")) + } + + val language = status.language + if (language != null && + (column.type == ColumnType.CONVERSATION || Pref.bpShowLanguage(activity.pref)) + ) { + prepareSb().append(activity.getString(R.string.language_is, language)) + } + + tvApplication.vg(sb != null)?.text = sb + } + + private fun showOpenSticker(who: TootAccount) { + try { + if (!Column.showOpenSticker) return + + val host = who.apDomain + + // LTLでホスト名が同じならTickerを表示しない + when (column.type) { ColumnType.LOCAL, ColumnType.LOCAL_AROUND -> { - if(host == access_info.apDomain) return + if (host == access_info.apDomain) return } - - else -> { - - } - } - - val item = OpenSticker.lastList[host.ascii] ?: return - - tvOpenSticker.text = item.name - tvOpenSticker.textColor = item.fontColor - - val density = activity.density - - val lp = ivOpenSticker.layoutParams - lp.height = (density * 16f + 0.5f).toInt() - lp.width = (density * item.imageWidth + 0.5f).toInt() - - ivOpenSticker.layoutParams = lp - ivOpenSticker.setImageUrl(activity.pref, 0f, item.favicon) - val colorBg = item.bgColor - when(colorBg.size) { + + else -> { + + } + } + + val item = OpenSticker.lastList[host.ascii] ?: return + + tvOpenSticker.text = item.name + tvOpenSticker.textColor = item.fontColor + + val density = activity.density + + val lp = ivOpenSticker.layoutParams + lp.height = (density * 16f + 0.5f).toInt() + lp.width = (density * item.imageWidth + 0.5f).toInt() + + ivOpenSticker.layoutParams = lp + ivOpenSticker.setImageUrl(activity.pref, 0f, item.favicon) + val colorBg = item.bgColor + when (colorBg.size) { 1 -> { val c = colorBg.first() tvOpenSticker.setBackgroundColor(c) ivOpenSticker.setBackgroundColor(c) } - - else -> { - ivOpenSticker.setBackgroundColor(colorBg.last()) - tvOpenSticker.background = colorBg.getGradation() - } - } - llOpenSticker.visibility = View.VISIBLE - llOpenSticker.requestLayout() - - } catch(ex : Throwable) { - log.trace(ex) - } - } - - private fun showStatusTime( - activity : ActMain, - tv : TextView, - @Suppress("UNUSED_PARAMETER") who : TootAccount, - status : TootStatus? = null, - time : Long? = null + + else -> { + ivOpenSticker.setBackgroundColor(colorBg.last()) + tvOpenSticker.background = colorBg.getGradation() + } + } + llOpenSticker.visibility = View.VISIBLE + llOpenSticker.requestLayout() + + } catch (ex: Throwable) { + log.trace(ex) + } + } + + private fun showStatusTime( + activity: ActMain, + tv: TextView, + @Suppress("UNUSED_PARAMETER") who: TootAccount, + status: TootStatus? = null, + time: Long? = null ) { - val sb = SpannableStringBuilder() - - if(status != null) { - - if(status.account.isAdmin) { - if(sb.isNotEmpty()) sb.append('\u200B') - sb.appendColorShadeIcon(activity, R.drawable.ic_shield, "admin") - } - - if(status.account.isPro) { - if(sb.isNotEmpty()) sb.append('\u200B') - sb.appendColorShadeIcon(activity, R.drawable.ic_authorized, "pro") - } - - if(status.account.isCat) { - if(sb.isNotEmpty()) sb.append('\u200B') - sb.appendColorShadeIcon(activity, R.drawable.ic_cat, "cat") - } - - // botマーク - if(status.account.bot) { - if(sb.isNotEmpty()) sb.append('\u200B') - sb.appendColorShadeIcon(activity, R.drawable.ic_bot, "bot") - } + val sb = SpannableStringBuilder() - if(status.account.suspended) { - if(sb.isNotEmpty()) sb.append('\u200B') - sb.appendColorShadeIcon(activity, R.drawable.ic_delete, "suspended") - } + if (status != null) { - // mobileマーク - if(status.viaMobile) { - if(sb.isNotEmpty()) sb.append('\u200B') - sb.appendColorShadeIcon(activity, R.drawable.ic_mobile, "mobile") - } - - // mobileマーク - if(status.bookmarked) { - if(sb.isNotEmpty()) sb.append('\u200B') - sb.appendColorShadeIcon(activity, R.drawable.ic_bookmark, "bookmarked") - } - - // NSFWマーク - if(status.hasMedia() && status.sensitive) { - if(sb.isNotEmpty()) sb.append('\u200B') - sb.appendColorShadeIcon(activity, R.drawable.ic_eye_off, "NSFW") - } - - // visibility - val visIconId = - Styler.getVisibilityIconId(access_info.isMisskey, status.visibility) - if(R.drawable.ic_public != visIconId) { - if(sb.isNotEmpty()) sb.append('\u200B') - sb.appendColorShadeIcon( + if (status.account.isAdmin) { + if (sb.isNotEmpty()) sb.append('\u200B') + sb.appendColorShadeIcon(activity, R.drawable.ic_shield, "admin") + } + + if (status.account.isPro) { + if (sb.isNotEmpty()) sb.append('\u200B') + sb.appendColorShadeIcon(activity, R.drawable.ic_authorized, "pro") + } + + if (status.account.isCat) { + if (sb.isNotEmpty()) sb.append('\u200B') + sb.appendColorShadeIcon(activity, R.drawable.ic_cat, "cat") + } + + // botマーク + if (status.account.bot) { + if (sb.isNotEmpty()) sb.append('\u200B') + sb.appendColorShadeIcon(activity, R.drawable.ic_bot, "bot") + } + + if (status.account.suspended) { + if (sb.isNotEmpty()) sb.append('\u200B') + sb.appendColorShadeIcon(activity, R.drawable.ic_delete, "suspended") + } + + // mobileマーク + if (status.viaMobile) { + if (sb.isNotEmpty()) sb.append('\u200B') + sb.appendColorShadeIcon(activity, R.drawable.ic_mobile, "mobile") + } + + // mobileマーク + if (status.bookmarked) { + if (sb.isNotEmpty()) sb.append('\u200B') + sb.appendColorShadeIcon(activity, R.drawable.ic_bookmark, "bookmarked") + } + + // NSFWマーク + if (status.hasMedia() && status.sensitive) { + if (sb.isNotEmpty()) sb.append('\u200B') + sb.appendColorShadeIcon(activity, R.drawable.ic_eye_off, "NSFW") + } + + // visibility + val visIconId = + Styler.getVisibilityIconId(access_info.isMisskey, status.visibility) + if (R.drawable.ic_public != visIconId) { + if (sb.isNotEmpty()) sb.append('\u200B') + sb.appendColorShadeIcon( activity, visIconId, Styler.getVisibilityString( @@ -1593,50 +1593,50 @@ internal class ItemViewHolder( status.visibility ) ) - } - - // pinned - if(status.pinned) { - if(sb.isNotEmpty()) sb.append('\u200B') - sb.appendColorShadeIcon(activity, R.drawable.ic_pin, "pinned") - - // val start = sb.length - // sb.append("pinned") - // val end = sb.length - // val icon_id = Styler.getAttributeResourceId(activity, R.attr.ic_pin) - // sb.setSpan( - // EmojiImageSpan(activity, icon_id), - // start, - // end, - // Spanned.SPAN_EXCLUSIVE_EXCLUSIVE - // ) - } - - // unread - if(status.conversationSummary?.unread == true) { - if(sb.isNotEmpty()) sb.append('\u200B') - - sb.appendColorShadeIcon( + } + + // pinned + if (status.pinned) { + if (sb.isNotEmpty()) sb.append('\u200B') + sb.appendColorShadeIcon(activity, R.drawable.ic_pin, "pinned") + + // val start = sb.length + // sb.append("pinned") + // val end = sb.length + // val icon_id = Styler.getAttributeResourceId(activity, R.attr.ic_pin) + // sb.setSpan( + // EmojiImageSpan(activity, icon_id), + // start, + // end, + // Spanned.SPAN_EXCLUSIVE_EXCLUSIVE + // ) + } + + // unread + if (status.conversationSummary?.unread == true) { + if (sb.isNotEmpty()) sb.append('\u200B') + + sb.appendColorShadeIcon( activity, R.drawable.ic_unread, "unread", color = MyClickableSpan.defaultLinkColor ) - } - - if(status.isPromoted) { - if(sb.isNotEmpty()) sb.append(' ') - sb.append(activity.getString(R.string.promoted)) - } - - if(status.isFeatured) { - if(sb.isNotEmpty()) sb.append(' ') - sb.append(activity.getString(R.string.featured)) - } - } - - if(sb.isNotEmpty()) sb.append(' ') - sb.append( + } + + if (status.isPromoted) { + if (sb.isNotEmpty()) sb.append(' ') + sb.append(activity.getString(R.string.promoted)) + } + + if (status.isFeatured) { + if (sb.isNotEmpty()) sb.append(' ') + sb.append(activity.getString(R.string.featured)) + } + } + + if (sb.isNotEmpty()) sb.append(' ') + sb.append( when { time != null -> TootStatus.formatTime( activity, @@ -1651,29 +1651,29 @@ internal class ItemViewHolder( else -> "?" } ) - - tv.text = sb - } - - private fun showStatusTimeScheduled( - activity : ActMain, - tv : TextView, - item : TootScheduled + + tv.text = sb + } + + private fun showStatusTimeScheduled( + activity: ActMain, + tv: TextView, + item: TootScheduled ) { - val sb = SpannableStringBuilder() - - // NSFWマーク - if(item.hasMedia() && item.sensitive) { - if(sb.isNotEmpty()) sb.append('\u200B') - sb.appendColorShadeIcon(activity, R.drawable.ic_eye_off, "NSFW") - } - - // visibility - val visIconId = - Styler.getVisibilityIconId(access_info.isMisskey, item.visibility) - if(R.drawable.ic_public != visIconId) { - if(sb.isNotEmpty()) sb.append('\u200B') - sb.appendColorShadeIcon( + val sb = SpannableStringBuilder() + + // NSFWマーク + if (item.hasMedia() && item.sensitive) { + if (sb.isNotEmpty()) sb.append('\u200B') + sb.appendColorShadeIcon(activity, R.drawable.ic_eye_off, "NSFW") + } + + // visibility + val visIconId = + Styler.getVisibilityIconId(access_info.isMisskey, item.visibility) + if (R.drawable.ic_public != visIconId) { + if (sb.isNotEmpty()) sb.append('\u200B') + sb.appendColorShadeIcon( activity, visIconId, Styler.getVisibilityString( @@ -1682,174 +1682,174 @@ internal class ItemViewHolder( item.visibility ) ) - } - - - if(sb.isNotEmpty()) sb.append(' ') - sb.append( + } + + + if (sb.isNotEmpty()) sb.append(' ') + sb.append( TootStatus.formatTime( activity, item.timeScheduledAt, column.type != ColumnType.CONVERSATION ) ) - - tv.text = sb - } - // fun updateRelativeTime() { - // val boost_time = this.boost_time - // if(boost_time != 0L) { - // tvBoostedTime.text = TootStatus.formatTime(tvBoostedTime.context, boost_time, true) - // } - // val status_showing = this.status_showing - // if(status_showing != null) { - // showStatusTime(activity, status_showing) - // } - // } - - private fun setAcct(tv : TextView, accessInfo : SavedAccount, who : TootAccount) { - val ac = AcctColor.load(accessInfo, who) - tv.text = when { - AcctColor.hasNickname(ac) -> ac.nickname - Pref.bpShortAcctLocalUser(App1.pref) -> "@${who.acct.pretty}" - else -> "@${ac.nickname}" - } - tv.textColor = ac.color_fg.notZero() ?: this.acct_color - - tv.setBackgroundColor(ac.color_bg) // may 0 - tv.setPaddingRelative(activity.acct_pad_lr, 0, activity.acct_pad_lr, 0) - - } - - private fun showContent(shown : Boolean) { - llContents.visibility = if(shown) View.VISIBLE else View.GONE - btnContentWarning.setText(if(shown) R.string.hide else R.string.show) - status_showing?.let { status -> - val r = status.auto_cw - tvContent.minLines = r?.originalLineCount ?: - 1 - if(r?.decoded_spoiler_text != null) { - // 自動CWの場合はContentWarningのテキストを切り替える - tvContentWarning.text = - if(shown) activity.getString(R.string.auto_cw_prefix) else r.decoded_spoiler_text - } - } - } - - private fun setMedia( - media_attachments : ArrayList, - sbDesc : StringBuilder, - iv : MyNetworkImageView, - idx : Int + + tv.text = sb + } + // fun updateRelativeTime() { + // val boost_time = this.boost_time + // if(boost_time != 0L) { + // tvBoostedTime.text = TootStatus.formatTime(tvBoostedTime.context, boost_time, true) + // } + // val status_showing = this.status_showing + // if(status_showing != null) { + // showStatusTime(activity, status_showing) + // } + // } + + private fun setAcct(tv: TextView, accessInfo: SavedAccount, who: TootAccount) { + val ac = AcctColor.load(accessInfo, who) + tv.text = when { + AcctColor.hasNickname(ac) -> ac.nickname + Pref.bpShortAcctLocalUser(App1.pref) -> "@${who.acct.pretty}" + else -> "@${ac.nickname}" + } + tv.textColor = ac.color_fg.notZero() ?: this.acct_color + + tv.setBackgroundColor(ac.color_bg) // may 0 + tv.setPaddingRelative(activity.acct_pad_lr, 0, activity.acct_pad_lr, 0) + + } + + private fun showContent(shown: Boolean) { + llContents.visibility = if (shown) View.VISIBLE else View.GONE + btnContentWarning.setText(if (shown) R.string.hide else R.string.show) + status_showing?.let { status -> + val r = status.auto_cw + tvContent.minLines = r?.originalLineCount ?: -1 + if (r?.decoded_spoiler_text != null) { + // 自動CWの場合はContentWarningのテキストを切り替える + tvContentWarning.text = + if (shown) activity.getString(R.string.auto_cw_prefix) else r.decoded_spoiler_text + } + } + } + + private fun setMedia( + media_attachments: ArrayList, + sbDesc: StringBuilder, + iv: MyNetworkImageView, + idx: Int ) { - val ta = if(idx < media_attachments.size) media_attachments[idx] else null - if(ta == null) { - iv.visibility = View.GONE - return - } - - iv.visibility = View.VISIBLE - - iv.setFocusPoint(ta.focusX, ta.focusY) - - if(Pref.bpDontCropMediaThumb(App1.pref)) { - iv.scaleType = ImageView.ScaleType.FIT_CENTER - } else { - iv.setScaleTypeForMedia() - } - - val showUrl : Boolean - - when(ta.type) { + val ta = if (idx < media_attachments.size) media_attachments[idx] else null + if (ta == null) { + iv.visibility = View.GONE + return + } + + iv.visibility = View.VISIBLE + + iv.setFocusPoint(ta.focusX, ta.focusY) + + if (Pref.bpDontCropMediaThumb(App1.pref)) { + iv.scaleType = ImageView.ScaleType.FIT_CENTER + } else { + iv.setScaleTypeForMedia() + } + + val showUrl: Boolean + + when (ta.type) { TootAttachmentType.Audio -> { iv.setMediaType(0) iv.setDefaultImage(defaultColorIcon(activity, R.drawable.wide_music)) iv.setImageUrl(activity.pref, 0f, ta.urlForThumbnail(activity.pref)) showUrl = true } - + TootAttachmentType.Unknown -> { iv.setMediaType(0) iv.setDefaultImage(defaultColorIcon(activity, R.drawable.wide_question)) iv.setImageUrl(activity.pref, 0f, null) showUrl = true } - - else -> when(val urlThumbnail = ta.urlForThumbnail(activity.pref)) { + + else -> when (val urlThumbnail = ta.urlForThumbnail(activity.pref)) { null, "" -> { iv.setMediaType(0) iv.setDefaultImage(defaultColorIcon(activity, R.drawable.wide_question)) iv.setImageUrl(activity.pref, 0f, null) showUrl = true } - - else -> { - iv.setMediaType( - when(ta.type) { + + else -> { + iv.setMediaType( + when (ta.type) { TootAttachmentType.Video -> R.drawable.media_type_video TootAttachmentType.GIFV -> R.drawable.media_type_gifv else -> 0 } ) - iv.setDefaultImage(null) - iv.setImageUrl( + iv.setDefaultImage(null) + iv.setImageUrl( activity.pref, 0f, access_info.supplyBaseUrl(urlThumbnail), access_info.supplyBaseUrl(urlThumbnail) ) - showUrl = false - } - } - - } - - fun appendDescription(s : String) { - // val lp = LinearLayout.LayoutParams( - // LinearLayout.LayoutParams.MATCH_PARENT, - // LinearLayout.LayoutParams.WRAP_CONTENT - // ) - // lp.topMargin = (0.5f + activity.density * 3f).toInt() - // - // val tv = MyTextView(activity) - // tv.layoutParams = lp - // // - // tv.movementMethod = MyLinkMovementMethod - // if(! activity.timeline_font_size_sp.isNaN()) { - // tv.textSize = activity.timeline_font_size_sp - // } - // tv.setTextColor(content_color) - - if(sbDesc.isNotEmpty()) sbDesc.append("\n") - val desc = activity.getString(R.string.media_description, idx + 1, s) - sbDesc.append(desc) - } - - when(val description = ta.description.notEmpty()) { - null -> if(showUrl) ta.urlForDescription.notEmpty()?.let { appendDescription(it) } - else -> appendDescription(description) - } - } - - private val defaultBoostedAction : () -> Unit = { - val pos = activity.nextPosition(column) - val notification = (item as? TootNotification) - boost_account?.let { whoRef -> - if(access_info.isPseudo) { - DlgContextMenu(activity, column, whoRef, null, notification, tvContent).show() - } else { - Action_User.profileLocal(activity, pos, access_info, whoRef.get()) - } - } - } - private var boostedAction : () -> Unit = defaultBoostedAction - - override fun onClick(v : View) { - - val pos = activity.nextPosition(column) - val item = this.item - val notification = (item as? TootNotification) - when(v) { - + showUrl = false + } + } + + } + + fun appendDescription(s: String) { + // val lp = LinearLayout.LayoutParams( + // LinearLayout.LayoutParams.MATCH_PARENT, + // LinearLayout.LayoutParams.WRAP_CONTENT + // ) + // lp.topMargin = (0.5f + activity.density * 3f).toInt() + // + // val tv = MyTextView(activity) + // tv.layoutParams = lp + // // + // tv.movementMethod = MyLinkMovementMethod + // if(! activity.timeline_font_size_sp.isNaN()) { + // tv.textSize = activity.timeline_font_size_sp + // } + // tv.setTextColor(content_color) + + if (sbDesc.isNotEmpty()) sbDesc.append("\n") + val desc = activity.getString(R.string.media_description, idx + 1, s) + sbDesc.append(desc) + } + + when (val description = ta.description.notEmpty()) { + null -> if (showUrl) ta.urlForDescription.notEmpty()?.let { appendDescription(it) } + else -> appendDescription(description) + } + } + + private val defaultBoostedAction: () -> Unit = { + val pos = activity.nextPosition(column) + val notification = (item as? TootNotification) + boost_account?.let { whoRef -> + if (access_info.isPseudo) { + DlgContextMenu(activity, column, whoRef, null, notification, tvContent).show() + } else { + Action_User.profileLocal(activity, pos, access_info, whoRef.get()) + } + } + } + private var boostedAction: () -> Unit = defaultBoostedAction + + override fun onClick(v: View) { + + val pos = activity.nextPosition(column) + val item = this.item + val notification = (item as? TootNotification) + when (v) { + btnHideMedia, btnCardImageHide -> { fun hideViews() { llMedia.visibility = View.GONE @@ -1861,12 +1861,12 @@ internal class ItemViewHolder( MediaShown.save(status, false) hideViews() } - if(item is TootScheduled) { + if (item is TootScheduled) { MediaShown.save(item.uri, false) hideViews() } } - + btnShowMedia, btnCardImageShow -> { fun showViews() { llMedia.visibility = View.VISIBLE @@ -1878,35 +1878,35 @@ internal class ItemViewHolder( MediaShown.save(status, true) showViews() } - if(item is TootScheduled) { + if (item is TootScheduled) { MediaShown.save(item.uri, true) showViews() } } - + ivMedia1 -> clickMedia(0) ivMedia2 -> clickMedia(1) ivMedia3 -> clickMedia(2) ivMedia4 -> clickMedia(3) - + btnContentWarning -> { status_showing?.let { status -> val new_shown = llContents.visibility == View.GONE ContentWarning.save(status, new_shown) - + // 1個だけ開閉するのではなく、例えば通知TLにある複数の要素をまとめて開閉するなどある list_adapter.notifyChange(reason = "ContentWarning onClick", reset = true) - + } - if(item is TootScheduled) { + if (item is TootScheduled) { val new_shown = llContents.visibility == View.GONE ContentWarning.save(item.uri, new_shown) - + // 1個だけ開閉するのではなく、例えば通知TLにある複数の要素をまとめて開閉するなどある list_adapter.notifyChange(reason = "ContentWarning onClick", reset = true) } } - + ivThumbnail -> status_account?.let { whoRef -> when { access_info.isNA -> DlgContextMenu( @@ -1917,9 +1917,9 @@ internal class ItemViewHolder( notification, tvContent ).show() - + // 2018/12/26 疑似アカウントでもプロフカラムを表示する https://github.com/tootsuite/mastodon/commit/108b2139cd87321f6c0aec63ef93db85ce30bfec - + else -> Action_User.profileLocal( activity, pos, @@ -1928,66 +1928,66 @@ internal class ItemViewHolder( ) } } - + llBoosted -> boostedAction() - + llReply -> { val s = status_reply - + when { s != null -> Action_Toot.conversation(activity, pos, access_info, s) - + // tootsearchは返信元のIDを取得するのにひと手間必要 column.type == ColumnType.SEARCH_TS || column.type == ColumnType.SEARCH_NOTESTOCK -> Action_Toot.showReplyTootsearch(activity, pos, status_showing) - + else -> { val id = status_showing?.in_reply_to_id - if(id != null) { + if (id != null) { Action_Toot.conversationLocal(activity, pos, access_info, id) } } } } - + llFollow -> follow_account?.let { whoRef -> - if(access_info.isPseudo) { + if (access_info.isPseudo) { DlgContextMenu(activity, column, whoRef, null, notification, tvContent).show() } else { Action_User.profileLocal(activity, pos, access_info, whoRef.get()) } } - + btnFollow -> follow_account?.let { who -> DlgContextMenu(activity, column, who, null, notification, tvContent).show() } - - btnGapHead -> when(item) { + + btnGapHead -> when (item) { is TootGap -> column.startGap(item, isHead = true) } - - btnGapTail -> when(item) { + + btnGapTail -> when (item) { is TootGap -> column.startGap(item, isHead = false) } - - btnSearchTag, llTrendTag -> when(item) { - + + btnSearchTag, llTrendTag -> when (item) { + is TootConversationSummary -> openConversationSummary() - + is TootGap -> when { column.type.gapDirection(column, true) -> column.startGap(item, isHead = true) - + column.type.gapDirection(column, false) -> column.startGap(item, isHead = false) - + else -> activity.showToast(true, "This column can't support gap reading.") } - + is TootSearchGap -> column.startGap(item, isHead = true) - + is TootDomainBlock -> { AlertDialog.Builder(activity) .setMessage( @@ -2007,7 +2007,7 @@ internal class ItemViewHolder( } .show() } - + is TootTag -> { Action_HashTag.timeline( activity, @@ -2016,7 +2016,7 @@ internal class ItemViewHolder( item.name // #を含まない ) } - + is TootScheduled -> { ActionsDialog() .addAction(activity.getString(R.string.edit)) { @@ -2031,15 +2031,15 @@ internal class ItemViewHolder( .show(activity) } } - - btnListTL -> if(item is TootList) { + + btnListTL -> if (item is TootList) { activity.addColumn(pos, access_info, ColumnType.LIST_TL, item.id) - } else if(item is MisskeyAntenna) { + } else if (item is MisskeyAntenna) { // TODO activity.addColumn(pos, access_info, ColumnType.MISSKEY_ANTENNA_TL, item.id) } - - btnListMore -> when(item) { + + btnListMore -> when (item) { is TootList -> { ActionsDialog() .addAction(activity.getString(R.string.list_timeline)) { @@ -2062,12 +2062,12 @@ internal class ItemViewHolder( } .show(activity, item.title) } - + is MisskeyAntenna -> { // TODO } } - + btnFollowRequestAccept -> follow_account?.let { whoRef -> val who = whoRef.get() DlgConfirm.openSimple( @@ -2080,7 +2080,7 @@ internal class ItemViewHolder( Action_Follow.authorizeFollowRequest(activity, access_info, whoRef, true) } } - + btnFollowRequestDeny -> follow_account?.let { whoRef -> val who = whoRef.get() DlgConfirm.openSimple( @@ -2093,14 +2093,14 @@ internal class ItemViewHolder( Action_Follow.authorizeFollowRequest(activity, access_info, whoRef, false) } } - - llFilter -> if(item is TootFilter) { + + llFilter -> if (item is TootFilter) { openFilterMenu(item) } - + ivCardImage -> status_showing?.card?.let { card -> val originalStatus = card.originalStatus - if(originalStatus != null) { + if (originalStatus != null) { Action_Toot.conversation( activity, activity.nextPosition(column), @@ -2109,7 +2109,7 @@ internal class ItemViewHolder( ) } else { val url = card.url - if(url?.isNotEmpty() == true) { + if (url?.isNotEmpty() == true) { openCustomTab( activity, pos, @@ -2119,17 +2119,17 @@ internal class ItemViewHolder( } } } - + llConversationIcons -> openConversationSummary() - } - } - - override fun onLongClick(v : View) : Boolean { - - val notification = (item as? TootNotification) - - when(v) { - + } + } + + override fun onLongClick(v: View): Boolean { + + val notification = (item as? TootNotification) + + when (v) { + ivThumbnail -> { status_account?.let { who -> DlgContextMenu( @@ -2143,7 +2143,7 @@ internal class ItemViewHolder( } return true } - + llBoosted -> { boost_account?.let { who -> DlgContextMenu( @@ -2157,11 +2157,11 @@ internal class ItemViewHolder( } return true } - + llReply -> { val s = status_reply when { - + // 返信元のstatusがあるならコンテキストメニュー s != null -> DlgContextMenu( activity, @@ -2171,9 +2171,9 @@ internal class ItemViewHolder( notification, tvContent ).show() - + // それ以外はコンテキストメニューではなく会話を開く - + // tootsearchは返信元のIDを取得するのにひと手間必要 column.type == ColumnType.SEARCH_TS || column.type == ColumnType.SEARCH_NOTESTOCK -> @@ -2182,10 +2182,10 @@ internal class ItemViewHolder( activity.nextPosition(column), status_showing ) - + else -> { val id = status_showing?.in_reply_to_id - if(id != null) { + if (id != null) { Action_Toot.conversationLocal( activity, activity.nextPosition(column), @@ -2196,7 +2196,7 @@ internal class ItemViewHolder( } } } - + llFollow -> { follow_account?.let { whoRef -> DlgContextMenu( @@ -2209,7 +2209,7 @@ internal class ItemViewHolder( } return true } - + btnFollow -> { follow_account?.let { whoRef -> Action_Follow.followFromAnotherAccount( @@ -2221,15 +2221,15 @@ internal class ItemViewHolder( } return true } - + ivCardImage -> Action_Toot.conversationOtherInstance( activity, activity.nextPosition(column), status_showing?.card?.originalStatus ) - + btnSearchTag, llTrendTag -> { - when(val item = this.item) { + when (val item = this.item) { // is TootGap -> column.startGap(item) // // is TootDomainBlock -> { @@ -2240,7 +2240,7 @@ internal class ItemViewHolder( // .setPositiveButton(R.string.ok) { _, _ -> Action_Instance.blockDomain(activity, access_info, domain, false) } // .show() // } - + is TootTag -> { // search_tag は#を含まない val tagEncoded = item.name.encodePercent() @@ -2253,22 +2253,22 @@ internal class ItemViewHolder( tag_without_sharp = item.name ) } - + } return true } - } - - return false - } - - private fun clickMedia(i : Int) { - try { - val media_attachments = - status_showing?.media_attachments ?: (item as? TootScheduled)?.media_attachments - ?: return - - when(val item = if(i < media_attachments.size) media_attachments[i] else return) { + } + + return false + } + + private fun clickMedia(i: Int) { + try { + val media_attachments = + status_showing?.media_attachments ?: (item as? TootScheduled)?.media_attachments + ?: return + + when (val item = if (i < media_attachments.size) media_attachments[i] else return) { is TootAttachmentMSP -> { // マストドン検索ポータルのデータではmedia_attachmentsが簡略化されている // 会話の流れを表示する @@ -2278,172 +2278,172 @@ internal class ItemViewHolder( status_showing ) } - + is TootAttachment -> when { - + // unknownが1枚だけなら内蔵ビューアを使わずにインテントを投げる item.type == TootAttachmentType.Unknown && media_attachments.size == 1 -> { // https://github.com/tateisu/SubwayTooter/pull/119 // メディアタイプがunknownの場合、そのほとんどはリモートから来たURLである // Pref.bpPriorLocalURL の状態に関わらずリモートURLがあればそれをブラウザで開く - when(val remoteUrl = item.remote_url.notEmpty()) { + when (val remoteUrl = item.remote_url.notEmpty()) { null -> activity.openCustomTab(item) else -> activity.openCustomTab(remoteUrl) } } - + // 内蔵メディアビューアを使う Pref.bpUseInternalMediaViewer(App1.pref) -> ActMediaViewer.open( activity, - when(access_info.isMisskey) { + when (access_info.isMisskey) { true -> ServiceType.MISSKEY else -> ServiceType.MASTODON }, media_attachments, i ) - + // ブラウザで開く else -> activity.openCustomTab(item) } - } - } catch(ex : Throwable) { - log.trace(ex) - } - } - - private fun showPreviewCard(status : TootStatus) { - - if(Pref.bpDontShowPreviewCard(activity.pref)) return - - val card = status.card ?: return - - // 会話カラムで返信ステータスなら捏造したカードを表示しない - if(column.type == ColumnType.CONVERSATION - && card.originalStatus != null - && status.reply != null - ) { - return - } - - var bShowOuter = false - - val sb = StringBuilder() - fun showString() { - if(sb.isNotEmpty()) { - val text = DecodeOptions( + } + } catch (ex: Throwable) { + log.trace(ex) + } + } + + private fun showPreviewCard(status: TootStatus) { + + if (Pref.bpDontShowPreviewCard(activity.pref)) return + + val card = status.card ?: return + + // 会話カラムで返信ステータスなら捏造したカードを表示しない + if (column.type == ColumnType.CONVERSATION + && card.originalStatus != null + && status.reply != null + ) { + return + } + + var bShowOuter = false + + val sb = StringBuilder() + fun showString() { + if (sb.isNotEmpty()) { + val text = DecodeOptions( activity, access_info, forceHtml = true, mentionDefaultHostDomain = status.account ).decodeHTML(sb.toString()) - if(text.isNotEmpty()) { - tvCardText.visibility = View.VISIBLE - tvCardText.text = text - bShowOuter = true - } - } - } - - if(status.reblog?.quote_muted == true) { - addLinkAndCaption( + if (text.isNotEmpty()) { + tvCardText.visibility = View.VISIBLE + tvCardText.text = text + bShowOuter = true + } + } + } + + if (status.reblog?.quote_muted == true) { + addLinkAndCaption( sb, null, card.url, activity.getString(R.string.muted_quote) ) - showString() - } else { - addLinkAndCaption( + showString() + } else { + addLinkAndCaption( sb, activity.getString(R.string.card_header_card), card.url, card.title ) - - addLinkAndCaption( + + addLinkAndCaption( sb, activity.getString(R.string.card_header_author), card.author_url, card.author_name ) - - addLinkAndCaption( + + addLinkAndCaption( sb, activity.getString(R.string.card_header_provider), card.provider_url, card.provider_name ) - - val description = card.description - if(description != null && description.isNotEmpty()) { - if(sb.isNotEmpty()) sb.append("
") - - val limit = Pref.spCardDescriptionLength.toInt(activity.pref) - - sb.append( + + val description = card.description + if (description != null && description.isNotEmpty()) { + if (sb.isNotEmpty()) sb.append("
") + + val limit = Pref.spCardDescriptionLength.toInt(activity.pref) + + sb.append( HTMLDecoder.encodeEntity( ellipsize( description, - if(limit <= 0) 64 else limit + if (limit <= 0) 64 else limit ) ) ) - } - - showString() - - val image = card.image - if(flCardImage.vg(image?.isNotEmpty() == true) != null) { - - flCardImage.layoutParams.height = if(card.originalStatus != null) { - activity.avatarIconSize - } else { - activity.app_state.media_thumb_height - } - - val imageUrl = access_info.supplyBaseUrl(image) - ivCardImage.setImageUrl(activity.pref, 0f, imageUrl, imageUrl) - - btnCardImageShow.blurhash = card.blurhash - - // show about card outer - bShowOuter = true - - // show about image content - val default_shown = when { - column.hide_media_default -> false - access_info.dont_hide_nsfw -> true - else -> ! status.sensitive - } - val is_shown = MediaShown.isShown(status, default_shown) - llCardImage.vg(is_shown) - btnCardImageShow.vg(! is_shown) - } - } - - if(bShowOuter) llCardOuter.visibility = View.VISIBLE - } - - private fun addLinkAndCaption( - sb : StringBuilder, - header : String?, - url : String?, - caption : String? + } + + showString() + + val image = card.image + if (flCardImage.vg(image?.isNotEmpty() == true) != null) { + + flCardImage.layoutParams.height = if (card.originalStatus != null) { + activity.avatarIconSize + } else { + activity.app_state.media_thumb_height + } + + val imageUrl = access_info.supplyBaseUrl(image) + ivCardImage.setImageUrl(activity.pref, 0f, imageUrl, imageUrl) + + btnCardImageShow.blurhash = card.blurhash + + // show about card outer + bShowOuter = true + + // show about image content + val default_shown = when { + column.hide_media_default -> false + access_info.dont_hide_nsfw -> true + else -> !status.sensitive + } + val is_shown = MediaShown.isShown(status, default_shown) + llCardImage.vg(is_shown) + btnCardImageShow.vg(!is_shown) + } + } + + if (bShowOuter) llCardOuter.visibility = View.VISIBLE + } + + private fun addLinkAndCaption( + sb: StringBuilder, + header: String?, + url: String?, + caption: String? ) { - - if(url.isNullOrEmpty() && caption.isNullOrEmpty()) return - - if(sb.isNotEmpty()) sb.append("
") - - if(header?.isNotEmpty() == true) { - sb.append(HTMLDecoder.encodeEntity(header)).append(": ") - } - - if(url != null && url.isNotEmpty()) { - sb.append("") - } - sb.append( + + if (url.isNullOrEmpty() && caption.isNullOrEmpty()) return + + if (sb.isNotEmpty()) sb.append("
") + + if (header?.isNotEmpty() == true) { + sb.append(HTMLDecoder.encodeEntity(header)).append(": ") + } + + if (url != null && url.isNotEmpty()) { + sb.append("
") + } + sb.append( HTMLDecoder.encodeEntity( when { caption != null && caption.isNotEmpty() -> caption @@ -2452,248 +2452,253 @@ internal class ItemViewHolder( } ) ) - - if(url != null && url.isNotEmpty()) { - sb.append("") - } - - } - - private fun makeReactionsView(status : TootStatus) { - if(! access_info.isMisskey) return - - val reactionsCount = status.reactionCounts - - val density = activity.density - - val buttonHeight = ActMain.boostButtonSize - val marginBetween = (buttonHeight.toFloat() * 0.05f + 0.5f).toInt() - - val paddingH = (buttonHeight.toFloat() * 0.1f + 0.5f).toInt() - val paddingV = (buttonHeight.toFloat() * 0.1f + 0.5f).toInt() - - val box = FlexboxLayout(activity).apply { - flexWrap = FlexWrap.WRAP - justifyContent = JustifyContent.FLEX_START - layoutParams = LinearLayout.LayoutParams( + + if (url != null && url.isNotEmpty()) { + sb.append("") + } + + } + + private fun makeReactionsView(status: TootStatus) { + if (!access_info.isMisskey) return + + val reactionsCount = status.reactionCounts + + val density = activity.density + + val buttonHeight = ActMain.boostButtonSize + val marginBetween = (buttonHeight.toFloat() * 0.05f + 0.5f).toInt() + + val paddingH = (buttonHeight.toFloat() * 0.1f + 0.5f).toInt() + val paddingV = (buttonHeight.toFloat() * 0.1f + 0.5f).toInt() + + val act = this@ItemViewHolder.activity // not Button(View).getActivity() + + val box = FlexboxLayout(activity).apply { + flexWrap = FlexWrap.WRAP + justifyContent = JustifyContent.FLEX_START + layoutParams = LinearLayout.LayoutParams( LinearLayout.LayoutParams.MATCH_PARENT, LinearLayout.LayoutParams.WRAP_CONTENT ).apply { - topMargin = (0.5f + density * 3f).toInt() - } - } - - // +ボタン - run { - val b = ImageButton(activity) - val blp = FlexboxLayout.LayoutParams( - buttonHeight, - buttonHeight - ) - blp.endMargin = marginBetween - b.layoutParams = blp - b.background = ContextCompat.getDrawable( - activity, - R.drawable.btn_bg_transparent_round6dp - ) - - val hasMyReaction = status.myReaction?.isNotEmpty() == true - b.contentDescription = - activity.getString(if(hasMyReaction) R.string.reaction_remove else R.string.reaction_add) - b.scaleType = ImageView.ScaleType.FIT_CENTER - b.padding = paddingV - b.setOnClickListener { - if(hasMyReaction) { - removeReaction(status, false) - } else { - addReaction(status, null) - } - } - - b.setOnLongClickListener { - Action_Toot.reactionFromAnotherAccount( - activity, - access_info, - status_showing - ) - true - } - - setIconDrawableId( - activity, - b, - if(hasMyReaction) R.drawable.ic_remove else R.drawable.ic_add, - color = content_color, - alphaMultiplier = Styler.boost_alpha - ) - - box.addView(b) - } - - if(reactionsCount != null) { - - var lastButton : View? = null - - val options = DecodeOptions( - activity, + topMargin = (0.5f + density * 3f).toInt() + } + } + + // +ボタン + val b = ImageButton(act) + val blp = FlexboxLayout.LayoutParams( + buttonHeight, + buttonHeight + ) + blp.endMargin = marginBetween + b.layoutParams = blp + b.background = ContextCompat.getDrawable( + activity, + R.drawable.btn_bg_transparent_round6dp + ) + + val hasMyReaction = status.myReaction?.isNotEmpty() == true + b.contentDescription = + activity.getString(if (hasMyReaction) R.string.reaction_remove else R.string.reaction_add) + b.scaleType = ImageView.ScaleType.FIT_CENTER + b.padding = paddingV + b.setOnClickListener { + if (hasMyReaction) { + removeReaction(status, false) + } else { + addReaction(status, null) + } + } + + b.setOnLongClickListener { + Action_Toot.reactionFromAnotherAccount( + activity, + access_info, + status_showing + ) + true + } + + setIconDrawableId( + act, + b, + if (hasMyReaction) R.drawable.ic_remove else R.drawable.ic_add, + color = content_color, + alphaMultiplier = Styler.boost_alpha + ) + + box.addView(b) + + if (reactionsCount != null) { + + var lastButton: View? = null + + val options = DecodeOptions( + act, access_info, decodeEmoji = true, enlargeEmoji = 1.5f, enlargeCustomEmoji = 1.5f ) - for(entry in reactionsCount.entries) { - val key = entry.key - val count = entry.value - if(count <= 0) continue - val ssb = MisskeyReaction.toSpannableStringBuilder(key,options,status) - .also{ it.append(" $count")} + for (entry in reactionsCount.entries) { + val key = entry.key + val count = entry.value + if (count <= 0) continue + val ssb = MisskeyReaction.toSpannableStringBuilder(key, options, status) + .also { it.append(" $count") } - val b = Button(activity).apply { - layoutParams = FlexboxLayout.LayoutParams( + val b = Button(act).apply { + layoutParams = FlexboxLayout.LayoutParams( FlexboxLayout.LayoutParams.WRAP_CONTENT, buttonHeight ).apply { - endMargin = marginBetween - } - minWidthCompat = buttonHeight - background = ContextCompat.getDrawable( - this@ItemViewHolder.activity, - R.drawable.btn_bg_transparent_round6dp - ) - // TODO 自分がリアクションしたやつは背景を変える - setTextColor(content_color) - setPadding(paddingH, paddingV, paddingH, paddingV) + endMargin = marginBetween + } + minWidthCompat = buttonHeight - text =ssb + background = if (MisskeyReaction.equals(status.myReaction, key)) { + // 自分がリアクションしたやつは背景を変える + getAdaptiveRippleDrawableRound( + act, + act.attrColor(R.attr.colorImageButtonAccent), + act.attrColor(R.attr.colorRippleEffect), + roundNormal = true + ) + } else { + ContextCompat.getDrawable( + act, + R.drawable.btn_bg_transparent_round6dp + ) + } - allCaps = false - tag = key - setOnClickListener { - addReaction(status, it.tag as? String) - } - setOnLongClickListener { - Action_Toot.reactionFromAnotherAccount( + setTextColor(content_color) + setPadding(paddingH, paddingV, paddingH, paddingV) + + text = ssb + + allCaps = false + tag = key + setOnClickListener { + val code = it.tag as? String + if( MisskeyReaction.equals(status.myReaction, code)){ + removeReaction(status, false) + }else{ + addReaction(status,code) + } + } + + setOnLongClickListener { + Action_Toot.reactionFromAnotherAccount( this@ItemViewHolder.activity, access_info, status_showing, it.tag as? String ) - true - } - // カスタム絵文字の場合、アニメーション等のコールバックを処理する必要がある - val invalidator = NetworkEmojiInvalidator(this@ItemViewHolder.activity.handler, this) - invalidator.register(ssb) - extra_invalidator_list.add(invalidator) - } - box.addView(b) - lastButton = b - } - - lastButton - ?.layoutParams - ?.cast() - ?.endMargin = 0 - } - - llExtra.addView(box) - } - - private fun addReaction(status : TootStatus, code : String?) { - - if(status.myReaction?.isNotEmpty() == true) { - activity.showToast(false, R.string.already_reactioned) - return - } - - if(access_info.isPseudo || ! access_info.isMisskey) return - - if(code == null) { - EmojiPicker(activity, access_info,closeOnSelected = true) { name, instance, _, _, _ -> - val item = EmojiMap.sShortNameToEmojiInfo[name] - val code = if(item == null || instance != null) { - ":$name:" - } else { - item.unified - } - addReaction(status, code) - }.show() -// val ad = ActionsDialog() -// for(mr in MisskeyReaction.values()) { -// val newCode = mr.shortcode -// val sb = SpannableStringBuilder() -// .appendMisskeyReaction(activity, mr.emojiUtf16, " ") -// .append(' ') -// .append(mr.shortcode) -// ad.addAction(sb) { -// addReaction(status, newCode) -// } -// } -// ad.show(activity) - return - } + true + } + // カスタム絵文字の場合、アニメーション等のコールバックを処理する必要がある + val invalidator = NetworkEmojiInvalidator(this@ItemViewHolder.activity.handler, this) + invalidator.register(ssb) + extra_invalidator_list.add(invalidator) + } + box.addView(b) + lastButton = b + } - TootTaskRunner(activity, progress_style = TootTaskRunner.PROGRESS_NONE).run(access_info, + lastButton + ?.layoutParams + ?.cast() + ?.endMargin = 0 + } + + llExtra.addView(box) + } + + private fun addReaction(status: TootStatus, code: String?) { + + if (status.myReaction?.isNotEmpty() == true) { + activity.showToast(false, R.string.already_reactioned) + return + } + + if (access_info.isPseudo || !access_info.isMisskey) return + + if (code == null) { + EmojiPicker(activity, access_info, closeOnSelected = true) { name, instance, _, _, _ -> + val item = EmojiMap.sShortNameToEmojiInfo[name] + val newCode = if (item == null || instance != null) { + ":$name:" + } else { + item.unified + } + addReaction(status, newCode) + }.show() + return + } + + TootTaskRunner(activity, progress_style = TootTaskRunner.PROGRESS_NONE).run(access_info, object : TootTask { - override suspend fun background(client : TootApiClient) : TootApiResult? { + override suspend fun background(client: TootApiClient): TootApiResult? { val params = access_info.putMisskeyApiToken().apply { put("noteId", status.id.toString()) put("reaction", code) } - + // 成功すると204 no content return client.request("/api/notes/reactions/create", params.toPostRequestBuilder()) } - - override suspend fun handleResult(result : TootApiResult?) { + + override suspend fun handleResult(result: TootApiResult?) { result ?: return - + val error = result.error - if(error != null) { + if (error != null) { activity.showToast(false, error) return } - when( val resCode = result.response?.code){ - in 200 until 300 ->{ - if(status.increaseReaction(code, true, "addReaction")) { + when (val resCode = result.response?.code) { + in 200 until 300 -> { + if (status.increaseReaction(code, true, "addReaction")) { // 1個だけ描画更新するのではなく、TLにある複数の要素をまとめて更新する list_adapter.notifyChange(reason = "addReaction complete", reset = true) } } - else-> activity.showToast(false, "HTTP error $resCode") + else -> activity.showToast(false, "HTTP error $resCode") } } - + }) - } - - private fun removeReaction(status : TootStatus, confirmed : Boolean = false) { - - val reaction = status.myReaction - - if(reaction?.isNotEmpty() != true) { - activity.showToast(false, R.string.not_reactioned) - return - } - - if(access_info.isPseudo || ! access_info.isMisskey) return - - if(! confirmed) { - AlertDialog.Builder(activity) - .setMessage(activity.getString(R.string.reaction_remove_confirm, reaction)) - .setNegativeButton(R.string.cancel, null) - .setPositiveButton(R.string.ok) { _, _ -> - removeReaction(status, confirmed = true) - } - .show() - return - } - - TootTaskRunner(activity, progress_style = TootTaskRunner.PROGRESS_NONE).run(access_info, + } + + private fun removeReaction(status: TootStatus, confirmed: Boolean = false) { + + val reaction = status.myReaction + + if (reaction?.isNotEmpty() != true) { + activity.showToast(false, R.string.not_reactioned) + return + } + + if (access_info.isPseudo || !access_info.isMisskey) return + + if (!confirmed) { + AlertDialog.Builder(activity) + .setMessage(activity.getString(R.string.reaction_remove_confirm, reaction)) + .setNegativeButton(R.string.cancel, null) + .setPositiveButton(R.string.ok) { _, _ -> + removeReaction(status, confirmed = true) + } + .show() + return + } + + TootTaskRunner(activity, progress_style = TootTaskRunner.PROGRESS_NONE).run(access_info, object : TootTask { - override suspend fun background(client : TootApiClient) : TootApiResult? = + override suspend fun background(client: TootApiClient): TootApiResult? = // 成功すると204 no content client.request( "/api/notes/reactions/delete", @@ -2702,18 +2707,18 @@ internal class ItemViewHolder( } .toPostRequestBuilder() ) - - override suspend fun handleResult(result : TootApiResult?) { + + override suspend fun handleResult(result: TootApiResult?) { result ?: return - + val error = result.error - if(error != null) { + if (error != null) { activity.showToast(false, error) return } - - if((result.response?.code ?: - 1) in 200 until 300) { - if(status.decreaseReaction(reaction, true, "removeReaction")) { + + if ((result.response?.code ?: -1) in 200 until 300) { + if (status.decreaseReaction(reaction, true, "removeReaction")) { // 1個だけ描画更新するのではなく、TLにある複数の要素をまとめて更新する list_adapter.notifyChange( reason = "removeReaction complete", @@ -2723,81 +2728,81 @@ internal class ItemViewHolder( } } }) - } - - private fun showEnqueteItems(status : TootStatus, enquete : TootPolls) { - val items = enquete.items ?: return - - val now = System.currentTimeMillis() - - val canVote = when(enquete.pollType) { + } + + private fun showEnqueteItems(status: TootStatus, enquete: TootPolls) { + val items = enquete.items ?: return + + val now = System.currentTimeMillis() + + val canVote = when (enquete.pollType) { TootPollsType.Mastodon -> when { enquete.expired -> false now >= enquete.expired_at -> false enquete.ownVoted -> false else -> true } - + TootPollsType.FriendsNico -> { val remain = enquete.time_start + TootPolls.ENQUETE_EXPIRE - now - remain > 0L && ! enquete.ownVoted + remain > 0L && !enquete.ownVoted } - - TootPollsType.Misskey -> ! enquete.ownVoted + + TootPollsType.Misskey -> !enquete.ownVoted TootPollsType.Notestock -> false - } - - items.forEachIndexed { index, choice -> - makeEnqueteChoiceView(status, enquete, canVote, index, choice) - } - - when(enquete.pollType) { - TootPollsType.Mastodon,TootPollsType.Notestock -> + } + + items.forEachIndexed { index, choice -> + makeEnqueteChoiceView(status, enquete, canVote, index, choice) + } + + when (enquete.pollType) { + TootPollsType.Mastodon, TootPollsType.Notestock -> makeEnqueteFooterMastodon(status, enquete, canVote) - + TootPollsType.FriendsNico -> makeEnqueteFooterFriendsNico(enquete) - + TootPollsType.Misskey -> { // no footer? } - } - } - - private fun makeEnqueteChoiceView( - status : TootStatus, - enquete : TootPolls, - canVote : Boolean, - i : Int, - item : TootPollsChoice + } + } + + private fun makeEnqueteChoiceView( + status: TootStatus, + enquete: TootPolls, + canVote: Boolean, + i: Int, + item: TootPollsChoice ) { - - val text = when(enquete.pollType) { + + val text = when (enquete.pollType) { TootPollsType.Misskey -> { val sb = SpannableStringBuilder() .append(item.decoded_text) - - if(enquete.ownVoted) { + + if (enquete.ownVoted) { sb.append(" / ") sb.append(activity.getString(R.string.vote_count_text, item.votes)) - if(item.isVoted) sb.append(' ').append(0x2713.toChar()) + if (item.isVoted) sb.append(' ').append(0x2713.toChar()) } sb } - + TootPollsType.FriendsNico -> { item.decoded_text } - - TootPollsType.Mastodon,TootPollsType.Notestock -> if(canVote) { + + TootPollsType.Mastodon, TootPollsType.Notestock -> if (canVote) { item.decoded_text } else { val sb = SpannableStringBuilder() .append(item.decoded_text) - if(! canVote) { + if (!canVote) { val v = item.votes - + sb.append(" / ") sb.append( when { @@ -2808,223 +2813,223 @@ internal class ItemViewHolder( activity.getString(R.string.vote_count_text, v) } ) - if(item.isVoted) sb.append(' ').append(0x2713.toChar()) + if (item.isVoted) sb.append(' ').append(0x2713.toChar()) } sb } - } - - // 投票ボタンの表示 - val lp = LinearLayout.LayoutParams( + } + + // 投票ボタンの表示 + val lp = LinearLayout.LayoutParams( LinearLayout.LayoutParams.MATCH_PARENT, LinearLayout.LayoutParams.WRAP_CONTENT ).apply { - if(i == 0) topMargin = (0.5f + activity.density * 3f).toInt() - } - - if(! canVote) { - - val b = TextView(activity) - b.layoutParams = lp - - b.text = text - val invalidator = NetworkEmojiInvalidator(activity.handler, b) - extra_invalidator_list.add(invalidator) - invalidator.register(text) - - b.padding = (activity.density * 3f + 0.5f).toInt() - - val ratio = when(enquete.pollType) { + if (i == 0) topMargin = (0.5f + activity.density * 3f).toInt() + } + + if (!canVote) { + + val b = TextView(activity) + b.layoutParams = lp + + b.text = text + val invalidator = NetworkEmojiInvalidator(activity.handler, b) + extra_invalidator_list.add(invalidator) + invalidator.register(text) + + b.padding = (activity.density * 3f + 0.5f).toInt() + + val ratio = when (enquete.pollType) { TootPollsType.Mastodon -> { val votesCount = enquete.votes_count ?: 0 val max = enquete.maxVotesCount ?: 0 - if(max > 0 && votesCount > 0) { + if (max > 0 && votesCount > 0) { (item.votes ?: 0).toFloat() / votesCount.toFloat() } else { null } } - - else -> { - val ratios = enquete.ratios - if(ratios != null && i <= ratios.size) { - ratios[i] - } else { - null - } - } - } - - if(ratio != null) { - b.backgroundDrawable = PollPlotDrawable( + + else -> { + val ratios = enquete.ratios + if (ratios != null && i <= ratios.size) { + ratios[i] + } else { + null + } + } + } + + if (ratio != null) { + b.backgroundDrawable = PollPlotDrawable( color = (content_color and 0xFFFFFF) or 0x20000000, ratio = ratio, isRtl = b.layoutDirection == View.LAYOUT_DIRECTION_RTL, startWidth = (activity.density * 2f + 0.5f).toInt() ) - } - - llExtra.addView(b) - - } else if(enquete.multiple) { - // 複数選択なのでチェックボックス - val b = CheckBox(activity) - b.layoutParams = lp - b.isAllCaps = false - b.text = text - val invalidator = NetworkEmojiInvalidator(activity.handler, b) - extra_invalidator_list.add(invalidator) - invalidator.register(text) - if(! canVote) { - b.isEnabled = false - } else { - b.isChecked = item.checked - b.setOnCheckedChangeListener { _, checked -> - item.checked = checked - } - } - llExtra.addView(b) - - } else { - val b = Button(activity) - b.layoutParams = lp - b.isAllCaps = false - b.text = text - val invalidator = NetworkEmojiInvalidator(activity.handler, b) - extra_invalidator_list.add(invalidator) - invalidator.register(text) - if(! canVote) { - b.isEnabled = false - } else { - val accessInfo = this@ItemViewHolder.access_info - b.setOnClickListener { view -> - val context = view.context ?: return@setOnClickListener - onClickEnqueteChoice(status, enquete, context, accessInfo, i) - } - } - llExtra.addView(b) - } - } - - private fun makeEnqueteFooterFriendsNico(enquete : TootPolls) { - val density = activity.density - val height = (0.5f + 6 * density).toInt() - val view = EnqueteTimerView(activity) - view.layoutParams = - LinearLayout.LayoutParams(LinearLayout.LayoutParams.MATCH_PARENT, height) - view.setParams(enquete.time_start, TootPolls.ENQUETE_EXPIRE) - llExtra.addView(view) - } - - private fun makeEnqueteFooterMastodon( - status : TootStatus, - enquete : TootPolls, - canVote : Boolean + } + + llExtra.addView(b) + + } else if (enquete.multiple) { + // 複数選択なのでチェックボックス + val b = CheckBox(activity) + b.layoutParams = lp + b.isAllCaps = false + b.text = text + val invalidator = NetworkEmojiInvalidator(activity.handler, b) + extra_invalidator_list.add(invalidator) + invalidator.register(text) + if (!canVote) { + b.isEnabled = false + } else { + b.isChecked = item.checked + b.setOnCheckedChangeListener { _, checked -> + item.checked = checked + } + } + llExtra.addView(b) + + } else { + val b = Button(activity) + b.layoutParams = lp + b.isAllCaps = false + b.text = text + val invalidator = NetworkEmojiInvalidator(activity.handler, b) + extra_invalidator_list.add(invalidator) + invalidator.register(text) + if (!canVote) { + b.isEnabled = false + } else { + val accessInfo = this@ItemViewHolder.access_info + b.setOnClickListener { view -> + val context = view.context ?: return@setOnClickListener + onClickEnqueteChoice(status, enquete, context, accessInfo, i) + } + } + llExtra.addView(b) + } + } + + private fun makeEnqueteFooterFriendsNico(enquete: TootPolls) { + val density = activity.density + val height = (0.5f + 6 * density).toInt() + val view = EnqueteTimerView(activity) + view.layoutParams = + LinearLayout.LayoutParams(LinearLayout.LayoutParams.MATCH_PARENT, height) + view.setParams(enquete.time_start, TootPolls.ENQUETE_EXPIRE) + llExtra.addView(view) + } + + private fun makeEnqueteFooterMastodon( + status: TootStatus, + enquete: TootPolls, + canVote: Boolean ) { - - val density = activity.density - - if(canVote && enquete.multiple) { - // 複数選択の投票ボタン - val lp = LinearLayout.LayoutParams( + + val density = activity.density + + if (canVote && enquete.multiple) { + // 複数選択の投票ボタン + val lp = LinearLayout.LayoutParams( LinearLayout.LayoutParams.MATCH_PARENT, LinearLayout.LayoutParams.WRAP_CONTENT ).apply { - topMargin = (0.5f + density * 3f).toInt() - } - - val b = Button(activity) - b.layoutParams = lp - b.isAllCaps = false - b.text = activity.getString(R.string.vote_button) - val accessInfo = this@ItemViewHolder.access_info - b.setOnClickListener { view -> - val context = view.context ?: return@setOnClickListener - sendMultiple(status, enquete, context, accessInfo) - } - llExtra.addView(b) - } - - val tv = TextView(activity) - val lp = LinearLayout.LayoutParams( + topMargin = (0.5f + density * 3f).toInt() + } + + val b = Button(activity) + b.layoutParams = lp + b.isAllCaps = false + b.text = activity.getString(R.string.vote_button) + val accessInfo = this@ItemViewHolder.access_info + b.setOnClickListener { view -> + val context = view.context ?: return@setOnClickListener + sendMultiple(status, enquete, context, accessInfo) + } + llExtra.addView(b) + } + + val tv = TextView(activity) + val lp = LinearLayout.LayoutParams( LinearLayout.LayoutParams.MATCH_PARENT, LinearLayout.LayoutParams.WRAP_CONTENT ) - lp.topMargin = (0.5f + 3 * density).toInt() - tv.layoutParams = lp - - val sb = StringBuilder() - - val votes_count = enquete.votes_count ?: 0 - when { - votes_count == 1 -> sb.append(activity.getString(R.string.vote_1)) - votes_count > 1 -> sb.append(activity.getString(R.string.vote_2, votes_count)) - } - - when(val t = enquete.expired_at) { - + lp.topMargin = (0.5f + 3 * density).toInt() + tv.layoutParams = lp + + val sb = StringBuilder() + + val votes_count = enquete.votes_count ?: 0 + when { + votes_count == 1 -> sb.append(activity.getString(R.string.vote_1)) + votes_count > 1 -> sb.append(activity.getString(R.string.vote_2, votes_count)) + } + + when (val t = enquete.expired_at) { + Long.MAX_VALUE -> { } - - else -> { - if(sb.isNotEmpty()) sb.append(" ") - sb.append( + + else -> { + if (sb.isNotEmpty()) sb.append(" ") + sb.append( activity.getString( R.string.vote_expire_at, TootStatus.formatTime(activity, t, false) ) ) - } - } - - tv.text = sb.toString() - - llExtra.addView(tv) - } - - private fun onClickEnqueteChoice( - status : TootStatus, - enquete : TootPolls, - context : Context, - accessInfo : SavedAccount, - idx : Int + } + } + + tv.text = sb.toString() + + llExtra.addView(tv) + } + + private fun onClickEnqueteChoice( + status: TootStatus, + enquete: TootPolls, + context: Context, + accessInfo: SavedAccount, + idx: Int ) { - if(enquete.ownVoted) { - context.showToast(false, R.string.already_voted) - return - } - - val now = System.currentTimeMillis() - - when(enquete.pollType) { + if (enquete.ownVoted) { + context.showToast(false, R.string.already_voted) + return + } + + val now = System.currentTimeMillis() + + when (enquete.pollType) { TootPollsType.Misskey -> { // Misskeyのアンケートには期限がない? } - + TootPollsType.FriendsNico -> { val remain = enquete.time_start + TootPolls.ENQUETE_EXPIRE - now - if(remain <= 0L) { + if (remain <= 0L) { context.showToast(false, R.string.enquete_was_end) return } } - - TootPollsType.Mastodon,TootPollsType.Notestock -> { - if(enquete.expired || now >= enquete.expired_at) { + + TootPollsType.Mastodon, TootPollsType.Notestock -> { + if (enquete.expired || now >= enquete.expired_at) { context.showToast(false, R.string.enquete_was_end) return } } - } - - TootTaskRunner(context).run(accessInfo, object : TootTask { - override suspend fun background(client : TootApiClient) = when(enquete.pollType) { + } + + TootTaskRunner(context).run(accessInfo, object : TootTask { + override suspend fun background(client: TootApiClient) = when (enquete.pollType) { TootPollsType.Misskey -> client.request( "/api/notes/polls/vote", accessInfo.putMisskeyApiToken().apply { put("noteId", enquete.status_id.toString()) put("choice", idx) - + }.toPostRequestBuilder() ) TootPollsType.Mastodon -> client.request( @@ -3039,22 +3044,22 @@ internal class ItemViewHolder( put("item_index", idx.toString()) }.toPostRequestBuilder() ) - TootPollsType.Notestock-> TootApiResult("can't vote on pseudo account column.") + TootPollsType.Notestock -> TootApiResult("can't vote on pseudo account column.") } - - override suspend fun handleResult(result : TootApiResult?) { + + override suspend fun handleResult(result: TootApiResult?) { result ?: return // cancelled. - + val data = result.jsonObject - if(data != null) { - when(enquete.pollType) { - TootPollsType.Misskey -> if(enquete.increaseVote(activity, idx, true)) { + if (data != null) { + when (enquete.pollType) { + TootPollsType.Misskey -> if (enquete.increaseVote(activity, idx, true)) { context.showToast(false, R.string.enquete_voted) - + // 1個だけ開閉するのではなく、例えば通知TLにある複数の要素をまとめて開閉するなどある list_adapter.notifyChange(reason = "onClickEnqueteChoice", reset = true) } - + TootPollsType.Mastodon -> { val newPoll = TootPolls.parse( TootParser(activity, accessInfo), @@ -3063,22 +3068,22 @@ internal class ItemViewHolder( status.media_attachments, data, ) - if(newPoll != null) { + if (newPoll != null) { status.enquete = newPoll // 1個だけ開閉するのではなく、例えば通知TLにある複数の要素をまとめて開閉するなどある list_adapter.notifyChange( reason = "onClickEnqueteChoice", reset = true ) - } else if(result.error != null) { + } else if (result.error != null) { context.showToast(true, "response parse error") } } - + TootPollsType.FriendsNico -> { val message = data.string("message") ?: "?" val valid = data.optBoolean("valid") - if(valid) { + if (valid) { context.showToast(false, R.string.enquete_voted) } else { context.showToast(true, R.string.enquete_vote_failed, message) @@ -3089,45 +3094,45 @@ internal class ItemViewHolder( } else { context.showToast(true, result.error) } - + } }) - } - - private fun sendMultiple( - status : TootStatus, - enquete : TootPolls, - context : Context, - accessInfo : SavedAccount + } + + private fun sendMultiple( + status: TootStatus, + enquete: TootPolls, + context: Context, + accessInfo: SavedAccount ) { - val now = System.currentTimeMillis() - if(now >= enquete.expired_at) { - context.showToast(false, R.string.enquete_was_end) - return - } - - if(enquete.items?.find { it.checked } == null) { - context.showToast(false, R.string.polls_choice_not_selected) - return - } - - TootTaskRunner(context).run(accessInfo, object : TootTask { - - var newPoll : TootPolls? = null - - override suspend fun background(client : TootApiClient) : TootApiResult? { + val now = System.currentTimeMillis() + if (now >= enquete.expired_at) { + context.showToast(false, R.string.enquete_was_end) + return + } + + if (enquete.items?.find { it.checked } == null) { + context.showToast(false, R.string.polls_choice_not_selected) + return + } + + TootTaskRunner(context).run(accessInfo, object : TootTask { + + var newPoll: TootPolls? = null + + override suspend fun background(client: TootApiClient): TootApiResult? { return client.request( "/api/v1/polls/${enquete.pollId}/votes", jsonObject { put("choices", jsonArray { enquete.items.forEachIndexed { index, choice -> - if(choice.checked) add(index) + if (choice.checked) add(index) } }) }.toPostRequestBuilder() )?.also { result -> val data = result.jsonObject - if(data != null) { + if (data != null) { newPoll = TootPolls.parse( TootParser(activity, accessInfo), TootPollsType.Mastodon, @@ -3135,775 +3140,773 @@ internal class ItemViewHolder( status.media_attachments, data, ) - if(newPoll == null) result.setError("response parse error") + if (newPoll == null) result.setError("response parse error") } } } - - override suspend fun handleResult(result : TootApiResult?) { + + override suspend fun handleResult(result: TootApiResult?) { result ?: return // cancelled. - + val newPoll = this.newPoll - if(newPoll != null) { + if (newPoll != null) { status.enquete = newPoll // 1個だけ開閉するのではなく、例えば通知TLにある複数の要素をまとめて開閉するなどある list_adapter.notifyChange(reason = "onClickEnqueteChoice", reset = true) - } else if(result.error != null) { + } else if (result.error != null) { context.showToast(true, result.error) } } }) - } - - private fun openFilterMenu(item : TootFilter) { - val ad = ActionsDialog() - ad.addAction(activity.getString(R.string.edit)) { - ActKeywordFilter.open(activity, access_info, item.id) - } - ad.addAction(activity.getString(R.string.delete)) { - Action_Filter.delete(activity, access_info, item) - } - ad.show(activity, activity.getString(R.string.filter_of, item.phrase)) - } - - internal fun getAccount() = status_account ?: boost_account ?: follow_account - - ///////////////////////////////////////////////////////////////////// - - private fun inflate(activity : ActMain) = with(activity.UI {}) { - val b = Benchmark(log, "Item-Inflate", 40L) - val rv = verticalLayout { - // トップレベルのViewGroupのlparamsはイニシャライザ内部に置くしかないみたい - layoutParams = - androidx.recyclerview.widget.RecyclerView.LayoutParams(matchParent, wrapContent) - .apply { - marginStart = dip(8) - marginEnd = dip(8) - topMargin = dip(2f) - bottomMargin = dip(1f) - } - - setPaddingRelative(dip(4), dip(1f), dip(4), dip(2f)) - - descendantFocusability = ViewGroup.FOCUS_BLOCK_DESCENDANTS - - llBoosted = linearLayout { - lparams(matchParent, wrapContent) { - bottomMargin = dip(6) - } - backgroundResource = R.drawable.btn_bg_transparent_round6dp - gravity = Gravity.CENTER_VERTICAL - - ivBoosted = imageView { - scaleType = ImageView.ScaleType.FIT_END - importantForAccessibility = View.IMPORTANT_FOR_ACCESSIBILITY_NO - }.lparams(dip(48), dip(32)) { - endMargin = dip(4) - } - - verticalLayout { - lparams(dip(0), wrapContent) { - weight = 1f - } - - linearLayout { - lparams(matchParent, wrapContent) - - tvBoostedAcct = textView { - ellipsize = TextUtils.TruncateAt.END - gravity = Gravity.END - maxLines = 1 - textSize = 12f // textSize の単位はSP - // tools:text ="who@hoge" - }.lparams(dip(0), wrapContent) { - weight = 1f - } - - tvBoostedTime = textView { - - startPadding = dip(2) - - gravity = Gravity.END - textSize = 12f // textSize の単位はSP - // tools:ignore="RtlSymmetry" - // tools:text="2017-04-16 09:37:14" - }.lparams(wrapContent, wrapContent) - - } - - tvBoosted = textView { - // tools:text = "~にブーストされました" - }.lparams(matchParent, wrapContent) - } - } - - llFollow = linearLayout { - lparams(matchParent, wrapContent) - - background = - ContextCompat.getDrawable(context, R.drawable.btn_bg_transparent_round6dp) - gravity = Gravity.CENTER_VERTICAL - - ivFollow = myNetworkImageView { - contentDescription = context.getString(R.string.thumbnail) - scaleType = ImageView.ScaleType.FIT_END - }.lparams(dip(48), dip(40)) { - endMargin = dip(4) - } - - verticalLayout { - - lparams(dip(0), wrapContent) { - weight = 1f - } - - tvFollowerName = textView { - // tools:text="Follower Name" - }.lparams(matchParent, wrapContent) - - tvFollowerAcct = textView { - setPaddingStartEnd(dip(4), dip(4)) - textSize = 12f // SP - }.lparams(matchParent, wrapContent) - - tvLastStatusAt = myTextView { - setPaddingStartEnd(dip(4), dip(4)) - textSize = 12f // SP - }.lparams(matchParent, wrapContent) - } - - frameLayout { - lparams(dip(40), dip(40)) { - startMargin = dip(4) - } - - btnFollow = imageButton { - background = - ContextCompat.getDrawable( + } + + private fun openFilterMenu(item: TootFilter) { + val ad = ActionsDialog() + ad.addAction(activity.getString(R.string.edit)) { + ActKeywordFilter.open(activity, access_info, item.id) + } + ad.addAction(activity.getString(R.string.delete)) { + Action_Filter.delete(activity, access_info, item) + } + ad.show(activity, activity.getString(R.string.filter_of, item.phrase)) + } + + internal fun getAccount() = status_account ?: boost_account ?: follow_account + + ///////////////////////////////////////////////////////////////////// + + private fun inflate(activity: ActMain) = with(activity.UI {}) { + val b = Benchmark(log, "Item-Inflate", 40L) + val rv = verticalLayout { + // トップレベルのViewGroupのlparamsはイニシャライザ内部に置くしかないみたい + layoutParams = + androidx.recyclerview.widget.RecyclerView.LayoutParams(matchParent, wrapContent) + .apply { + marginStart = dip(8) + marginEnd = dip(8) + topMargin = dip(2f) + bottomMargin = dip(1f) + } + + setPaddingRelative(dip(4), dip(1f), dip(4), dip(2f)) + + descendantFocusability = ViewGroup.FOCUS_BLOCK_DESCENDANTS + + llBoosted = linearLayout { + lparams(matchParent, wrapContent) { + bottomMargin = dip(6) + } + backgroundResource = R.drawable.btn_bg_transparent_round6dp + gravity = Gravity.CENTER_VERTICAL + + ivBoosted = imageView { + scaleType = ImageView.ScaleType.FIT_END + importantForAccessibility = View.IMPORTANT_FOR_ACCESSIBILITY_NO + }.lparams(dip(48), dip(32)) { + endMargin = dip(4) + } + + verticalLayout { + lparams(dip(0), wrapContent) { + weight = 1f + } + + linearLayout { + lparams(matchParent, wrapContent) + + tvBoostedAcct = textView { + ellipsize = TextUtils.TruncateAt.END + gravity = Gravity.END + maxLines = 1 + textSize = 12f // textSize の単位はSP + // tools:text ="who@hoge" + }.lparams(dip(0), wrapContent) { + weight = 1f + } + + tvBoostedTime = textView { + + startPadding = dip(2) + + gravity = Gravity.END + textSize = 12f // textSize の単位はSP + // tools:ignore="RtlSymmetry" + // tools:text="2017-04-16 09:37:14" + }.lparams(wrapContent, wrapContent) + + } + + tvBoosted = textView { + // tools:text = "~にブーストされました" + }.lparams(matchParent, wrapContent) + } + } + + llFollow = linearLayout { + lparams(matchParent, wrapContent) + + background = + ContextCompat.getDrawable(context, R.drawable.btn_bg_transparent_round6dp) + gravity = Gravity.CENTER_VERTICAL + + ivFollow = myNetworkImageView { + contentDescription = context.getString(R.string.thumbnail) + scaleType = ImageView.ScaleType.FIT_END + }.lparams(dip(48), dip(40)) { + endMargin = dip(4) + } + + verticalLayout { + + lparams(dip(0), wrapContent) { + weight = 1f + } + + tvFollowerName = textView { + // tools:text="Follower Name" + }.lparams(matchParent, wrapContent) + + tvFollowerAcct = textView { + setPaddingStartEnd(dip(4), dip(4)) + textSize = 12f // SP + }.lparams(matchParent, wrapContent) + + tvLastStatusAt = myTextView { + setPaddingStartEnd(dip(4), dip(4)) + textSize = 12f // SP + }.lparams(matchParent, wrapContent) + } + + frameLayout { + lparams(dip(40), dip(40)) { + startMargin = dip(4) + } + + btnFollow = imageButton { + background = + ContextCompat.getDrawable( context, R.drawable.btn_bg_transparent_round6dp ) - contentDescription = context.getString(R.string.follow) - scaleType = ImageView.ScaleType.CENTER - // tools:src="?attr/ic_follow_plus" - }.lparams(matchParent, matchParent) - - ivFollowedBy = imageView { - scaleType = ImageView.ScaleType.CENTER - // tools:src="?attr/ic_followed_by" - importantForAccessibility = View.IMPORTANT_FOR_ACCESSIBILITY_NO - }.lparams(matchParent, matchParent) - - } - } - - - llStatus = verticalLayout { - lparams(matchParent, wrapContent) - - linearLayout { - lparams(matchParent, wrapContent) - - tvAcct = textView { - ellipsize = TextUtils.TruncateAt.END - gravity = Gravity.END - maxLines = 1 - textSize = 12f // SP - // tools:text="who@hoge" - }.lparams(dip(0), wrapContent) { - weight = 1f - } - - tvTime = textView { - gravity = Gravity.END - startPadding = dip(2) - textSize = 12f // SP - // tools:ignore="RtlSymmetry" - // tools:text="2017-04-16 09:37:14" - }.lparams(wrapContent, wrapContent) - - } - - linearLayout { - lparams(matchParent, wrapContent) - - ivThumbnail = myNetworkImageView { - background = - ContextCompat.getDrawable( + contentDescription = context.getString(R.string.follow) + scaleType = ImageView.ScaleType.CENTER + // tools:src="?attr/ic_follow_plus" + }.lparams(matchParent, matchParent) + + ivFollowedBy = imageView { + scaleType = ImageView.ScaleType.CENTER + // tools:src="?attr/ic_followed_by" + importantForAccessibility = View.IMPORTANT_FOR_ACCESSIBILITY_NO + }.lparams(matchParent, matchParent) + + } + } + + + llStatus = verticalLayout { + lparams(matchParent, wrapContent) + + linearLayout { + lparams(matchParent, wrapContent) + + tvAcct = textView { + ellipsize = TextUtils.TruncateAt.END + gravity = Gravity.END + maxLines = 1 + textSize = 12f // SP + // tools:text="who@hoge" + }.lparams(dip(0), wrapContent) { + weight = 1f + } + + tvTime = textView { + gravity = Gravity.END + startPadding = dip(2) + textSize = 12f // SP + // tools:ignore="RtlSymmetry" + // tools:text="2017-04-16 09:37:14" + }.lparams(wrapContent, wrapContent) + + } + + linearLayout { + lparams(matchParent, wrapContent) + + ivThumbnail = myNetworkImageView { + background = + ContextCompat.getDrawable( context, R.drawable.btn_bg_transparent_round6dp ) - contentDescription = context.getString(R.string.thumbnail) - scaleType = ImageView.ScaleType.CENTER_CROP - }.lparams(dip(48), dip(48)) { - topMargin = dip(4) - endMargin = dip(4) - } - - verticalLayout { - lparams(dip(0), wrapContent) { - weight = 1f - } - - tvName = textView { - }.lparams(matchParent, wrapContent) - - llOpenSticker = linearLayout { - lparams(matchParent, wrapContent) - - ivOpenSticker = myNetworkImageView { - }.lparams(dip(16), dip(16)) { - isBaselineAligned = false - } - - tvOpenSticker = textView { - setTextSize(TypedValue.COMPLEX_UNIT_DIP, 10f) - gravity = Gravity.CENTER_VERTICAL - setPaddingStartEnd(dip(4f), dip(4f)) - }.lparams(0, dip(16)) { - isBaselineAligned = false - weight = 1f - } - } - - llReply = linearLayout { - lparams(matchParent, wrapContent) { - bottomMargin = dip(3) - } - - background = - ContextCompat.getDrawable( + contentDescription = context.getString(R.string.thumbnail) + scaleType = ImageView.ScaleType.CENTER_CROP + }.lparams(dip(48), dip(48)) { + topMargin = dip(4) + endMargin = dip(4) + } + + verticalLayout { + lparams(dip(0), wrapContent) { + weight = 1f + } + + tvName = textView { + }.lparams(matchParent, wrapContent) + + llOpenSticker = linearLayout { + lparams(matchParent, wrapContent) + + ivOpenSticker = myNetworkImageView { + }.lparams(dip(16), dip(16)) { + isBaselineAligned = false + } + + tvOpenSticker = textView { + setTextSize(TypedValue.COMPLEX_UNIT_DIP, 10f) + gravity = Gravity.CENTER_VERTICAL + setPaddingStartEnd(dip(4f), dip(4f)) + }.lparams(0, dip(16)) { + isBaselineAligned = false + weight = 1f + } + } + + llReply = linearLayout { + lparams(matchParent, wrapContent) { + bottomMargin = dip(3) + } + + background = + ContextCompat.getDrawable( context, R.drawable.btn_bg_transparent_round6dp ) - gravity = Gravity.CENTER_VERTICAL - - ivReply = imageView { - scaleType = ImageView.ScaleType.FIT_END - importantForAccessibility = View.IMPORTANT_FOR_ACCESSIBILITY_NO - padding = dip(4) - }.lparams(dip(32), dip(32)) { - endMargin = dip(4) - } - - tvReply = textView { - }.lparams(dip(0), wrapContent) { - weight = 1f - } - } - - llContentWarning = linearLayout { - lparams(matchParent, wrapContent) { - topMargin = dip(3) - isBaselineAligned = false - } - gravity = Gravity.CENTER_VERTICAL - - btnContentWarning = button { - - backgroundDrawable = - ContextCompat.getDrawable(context, R.drawable.bg_button_cw) - minWidthCompat = dip(40) - padding = dip(4) - //tools:text="見る" - }.lparams(wrapContent, dip(40)) { - endMargin = dip(8) - } - - verticalLayout { - lparams(dip(0), wrapContent) { - weight = 1f - } - - tvMentions = myTextView { - }.lparams(matchParent, wrapContent) - - tvContentWarning = myTextView { - }.lparams(matchParent, wrapContent) { - topMargin = dip(3) - } - - } - - } - - llContents = verticalLayout { - lparams(matchParent, wrapContent) - - tvContent = myTextView { - setLineSpacing(lineSpacingExtra, 1.1f) - // tools:text="Contents\nContents" - }.lparams(matchParent, wrapContent) { - topMargin = dip(3) - } - - val thumbnailHeight = activity.app_state.media_thumb_height - val verticalArrangeThumbnails = - Pref.bpVerticalArrangeThumbnails(activity.pref) - - flMedia = if(verticalArrangeThumbnails) { - frameLayout { - lparams(matchParent, wrapContent) { - topMargin = dip(3) - } - llMedia = verticalLayout { - lparams(matchParent, matchParent) - - btnHideMedia = imageButton { - - background = ContextCompat.getDrawable( + gravity = Gravity.CENTER_VERTICAL + + ivReply = imageView { + scaleType = ImageView.ScaleType.FIT_END + importantForAccessibility = View.IMPORTANT_FOR_ACCESSIBILITY_NO + padding = dip(4) + }.lparams(dip(32), dip(32)) { + endMargin = dip(4) + } + + tvReply = textView { + }.lparams(dip(0), wrapContent) { + weight = 1f + } + } + + llContentWarning = linearLayout { + lparams(matchParent, wrapContent) { + topMargin = dip(3) + isBaselineAligned = false + } + gravity = Gravity.CENTER_VERTICAL + + btnContentWarning = button { + + backgroundDrawable = + ContextCompat.getDrawable(context, R.drawable.bg_button_cw) + minWidthCompat = dip(40) + padding = dip(4) + //tools:text="見る" + }.lparams(wrapContent, dip(40)) { + endMargin = dip(8) + } + + verticalLayout { + lparams(dip(0), wrapContent) { + weight = 1f + } + + tvMentions = myTextView { + }.lparams(matchParent, wrapContent) + + tvContentWarning = myTextView { + }.lparams(matchParent, wrapContent) { + topMargin = dip(3) + } + + } + + } + + llContents = verticalLayout { + lparams(matchParent, wrapContent) + + tvContent = myTextView { + setLineSpacing(lineSpacingExtra, 1.1f) + // tools:text="Contents\nContents" + }.lparams(matchParent, wrapContent) { + topMargin = dip(3) + } + + val thumbnailHeight = activity.app_state.media_thumb_height + val verticalArrangeThumbnails = + Pref.bpVerticalArrangeThumbnails(activity.pref) + + flMedia = if (verticalArrangeThumbnails) { + frameLayout { + lparams(matchParent, wrapContent) { + topMargin = dip(3) + } + llMedia = verticalLayout { + lparams(matchParent, matchParent) + + btnHideMedia = imageButton { + + background = ContextCompat.getDrawable( context, R.drawable.btn_bg_transparent_round6dp ) - contentDescription = context.getString(R.string.hide) - imageResource = R.drawable.ic_close - }.lparams(dip(32), dip(32)) { - gravity = Gravity.END - } - - ivMedia1 = myNetworkImageView { - - background = ContextCompat.getDrawable( + contentDescription = context.getString(R.string.hide) + imageResource = R.drawable.ic_close + }.lparams(dip(32), dip(32)) { + gravity = Gravity.END + } + + ivMedia1 = myNetworkImageView { + + background = ContextCompat.getDrawable( context, R.drawable.bg_thumbnail ) - contentDescription = - context.getString(R.string.thumbnail) - scaleType = ImageView.ScaleType.CENTER_CROP - - }.lparams(matchParent, thumbnailHeight) { - topMargin = dip(3) - } - - ivMedia2 = myNetworkImageView { - - background = ContextCompat.getDrawable( + contentDescription = + context.getString(R.string.thumbnail) + scaleType = ImageView.ScaleType.CENTER_CROP + + }.lparams(matchParent, thumbnailHeight) { + topMargin = dip(3) + } + + ivMedia2 = myNetworkImageView { + + background = ContextCompat.getDrawable( context, R.drawable.bg_thumbnail ) - contentDescription = - context.getString(R.string.thumbnail) - scaleType = ImageView.ScaleType.CENTER_CROP - - }.lparams(matchParent, thumbnailHeight) { - topMargin = dip(3) - } - - ivMedia3 = myNetworkImageView { - - background = ContextCompat.getDrawable( + contentDescription = + context.getString(R.string.thumbnail) + scaleType = ImageView.ScaleType.CENTER_CROP + + }.lparams(matchParent, thumbnailHeight) { + topMargin = dip(3) + } + + ivMedia3 = myNetworkImageView { + + background = ContextCompat.getDrawable( context, R.drawable.bg_thumbnail ) - contentDescription = - context.getString(R.string.thumbnail) - scaleType = ImageView.ScaleType.CENTER_CROP - - }.lparams(matchParent, thumbnailHeight) { - topMargin = dip(3) - } - - ivMedia4 = myNetworkImageView { - - background = ContextCompat.getDrawable( + contentDescription = + context.getString(R.string.thumbnail) + scaleType = ImageView.ScaleType.CENTER_CROP + + }.lparams(matchParent, thumbnailHeight) { + topMargin = dip(3) + } + + ivMedia4 = myNetworkImageView { + + background = ContextCompat.getDrawable( context, R.drawable.bg_thumbnail ) - contentDescription = - context.getString(R.string.thumbnail) - scaleType = ImageView.ScaleType.CENTER_CROP - - }.lparams(matchParent, thumbnailHeight) { - topMargin = dip(3) - } - } - - btnShowMedia = blurhashView { - - errorColor = context.getAttributeColor( - + contentDescription = + context.getString(R.string.thumbnail) + scaleType = ImageView.ScaleType.CENTER_CROP + + }.lparams(matchParent, thumbnailHeight) { + topMargin = dip(3) + } + } + + btnShowMedia = blurhashView { + + errorColor = context.attrColor( R.attr.colorShowMediaBackground ) - gravity = Gravity.CENTER - - textColor = context.getAttributeColor( - + gravity = Gravity.CENTER + + textColor = context.attrColor( R.attr.colorShowMediaText ) - - minHeightCompat = dip(48) - - }.lparams(matchParent, thumbnailHeight) - - } - } else { - frameLayout { - lparams(matchParent, thumbnailHeight) { - topMargin = dip(3) - } - llMedia = linearLayout { - lparams(matchParent, matchParent) - - ivMedia1 = myNetworkImageView { - - background = ContextCompat.getDrawable( + + minHeightCompat = dip(48) + + }.lparams(matchParent, thumbnailHeight) + + } + } else { + frameLayout { + lparams(matchParent, thumbnailHeight) { + topMargin = dip(3) + } + llMedia = linearLayout { + lparams(matchParent, matchParent) + + ivMedia1 = myNetworkImageView { + + background = ContextCompat.getDrawable( context, R.drawable.bg_thumbnail ) - contentDescription = - context.getString(R.string.thumbnail) - scaleType = ImageView.ScaleType.CENTER_CROP - - }.lparams(0, matchParent) { - weight = 1f - } - - ivMedia2 = myNetworkImageView { - - background = ContextCompat.getDrawable( + contentDescription = + context.getString(R.string.thumbnail) + scaleType = ImageView.ScaleType.CENTER_CROP + + }.lparams(0, matchParent) { + weight = 1f + } + + ivMedia2 = myNetworkImageView { + + background = ContextCompat.getDrawable( context, R.drawable.bg_thumbnail ) - contentDescription = - context.getString(R.string.thumbnail) - scaleType = ImageView.ScaleType.CENTER_CROP - - }.lparams(0, matchParent) { - startMargin = dip(8) - weight = 1f - } - - ivMedia3 = myNetworkImageView { - - background = ContextCompat.getDrawable( + contentDescription = + context.getString(R.string.thumbnail) + scaleType = ImageView.ScaleType.CENTER_CROP + + }.lparams(0, matchParent) { + startMargin = dip(8) + weight = 1f + } + + ivMedia3 = myNetworkImageView { + + background = ContextCompat.getDrawable( context, R.drawable.bg_thumbnail ) - contentDescription = - context.getString(R.string.thumbnail) - scaleType = ImageView.ScaleType.CENTER_CROP - - }.lparams(0, matchParent) { - startMargin = dip(8) - weight = 1f - } - - ivMedia4 = myNetworkImageView { - - background = ContextCompat.getDrawable( + contentDescription = + context.getString(R.string.thumbnail) + scaleType = ImageView.ScaleType.CENTER_CROP + + }.lparams(0, matchParent) { + startMargin = dip(8) + weight = 1f + } + + ivMedia4 = myNetworkImageView { + + background = ContextCompat.getDrawable( context, R.drawable.bg_thumbnail ) - contentDescription = - context.getString(R.string.thumbnail) - scaleType = ImageView.ScaleType.CENTER_CROP - - }.lparams(0, matchParent) { - startMargin = dip(8) - weight = 1f - } - - btnHideMedia = imageButton { - - background = ContextCompat.getDrawable( + contentDescription = + context.getString(R.string.thumbnail) + scaleType = ImageView.ScaleType.CENTER_CROP + + }.lparams(0, matchParent) { + startMargin = dip(8) + weight = 1f + } + + btnHideMedia = imageButton { + + background = ContextCompat.getDrawable( context, R.drawable.btn_bg_transparent_round6dp ) - contentDescription = context.getString(R.string.hide) - imageResource = R.drawable.ic_close - }.lparams(dip(32), matchParent) { - startMargin = dip(8) - } - } - - btnShowMedia = blurhashView { - - errorColor = context.getAttributeColor( + contentDescription = context.getString(R.string.hide) + imageResource = R.drawable.ic_close + }.lparams(dip(32), matchParent) { + startMargin = dip(8) + } + } + + btnShowMedia = blurhashView { + + errorColor = context.attrColor( R.attr.colorShowMediaBackground ) - gravity = Gravity.CENTER - - textColor = context.getAttributeColor( + gravity = Gravity.CENTER + + textColor = context.attrColor( R.attr.colorShowMediaText ) - - }.lparams(matchParent, matchParent) - } - } - - tvMediaDescription = textView {}.lparams(matchParent, wrapContent) - - llCardOuter = verticalLayout { - lparams(matchParent, wrapContent) { - topMargin = dip(3) - startMargin = dip(12) - endMargin = dip(6) - } - padding = dip(3) - bottomPadding = dip(6) - - background = PreviewCardBorder() - - tvCardText = myTextView { - }.lparams(matchParent, wrapContent) { - } - - flCardImage = frameLayout { - lparams(matchParent, activity.app_state.media_thumb_height) { - topMargin = dip(3) - } - - llCardImage = linearLayout { - lparams(matchParent, matchParent) - - ivCardImage = myNetworkImageView { - - contentDescription = - context.getString(R.string.thumbnail) - - scaleType = if(Pref.bpDontCropMediaThumb(App1.pref)) - ImageView.ScaleType.FIT_CENTER - else - ImageView.ScaleType.CENTER_CROP - - }.lparams(0, matchParent) { - weight = 1f - } - btnCardImageHide = imageButton { - background = ContextCompat.getDrawable( + + }.lparams(matchParent, matchParent) + } + } + + tvMediaDescription = textView {}.lparams(matchParent, wrapContent) + + llCardOuter = verticalLayout { + lparams(matchParent, wrapContent) { + topMargin = dip(3) + startMargin = dip(12) + endMargin = dip(6) + } + padding = dip(3) + bottomPadding = dip(6) + + background = PreviewCardBorder() + + tvCardText = myTextView { + }.lparams(matchParent, wrapContent) { + } + + flCardImage = frameLayout { + lparams(matchParent, activity.app_state.media_thumb_height) { + topMargin = dip(3) + } + + llCardImage = linearLayout { + lparams(matchParent, matchParent) + + ivCardImage = myNetworkImageView { + + contentDescription = + context.getString(R.string.thumbnail) + + scaleType = if (Pref.bpDontCropMediaThumb(App1.pref)) + ImageView.ScaleType.FIT_CENTER + else + ImageView.ScaleType.CENTER_CROP + + }.lparams(0, matchParent) { + weight = 1f + } + btnCardImageHide = imageButton { + background = ContextCompat.getDrawable( context, R.drawable.btn_bg_transparent_round6dp ) - contentDescription = context.getString(R.string.hide) - imageResource = R.drawable.ic_close - }.lparams(dip(32), matchParent) { - startMargin = dip(4) - } - } - - btnCardImageShow = blurhashView { - - errorColor = context.getAttributeColor( + contentDescription = context.getString(R.string.hide) + imageResource = R.drawable.ic_close + }.lparams(dip(32), matchParent) { + startMargin = dip(4) + } + } + + btnCardImageShow = blurhashView { + + errorColor = context.attrColor( R.attr.colorShowMediaBackground ) - gravity = Gravity.CENTER - - textColor = context.getAttributeColor( + gravity = Gravity.CENTER + + textColor = context.attrColor( R.attr.colorShowMediaText ) - - }.lparams(matchParent, matchParent) - } - - } - - - llExtra = verticalLayout { - lparams(matchParent, wrapContent) { - topMargin = dip(0) - } - } - } - - // button bar - statusButtonsViewHolder = StatusButtonsViewHolder( + + }.lparams(matchParent, matchParent) + } + + } + + + llExtra = verticalLayout { + lparams(matchParent, wrapContent) { + topMargin = dip(0) + } + } + } + + // button bar + statusButtonsViewHolder = StatusButtonsViewHolder( activity, matchParent, 3f, - justifyContent = when(Pref.ipBoostButtonJustify(App1.pref)) { + justifyContent = when (Pref.ipBoostButtonJustify(App1.pref)) { 0 -> JustifyContent.FLEX_START 1 -> JustifyContent.CENTER else -> JustifyContent.FLEX_END } ) - llButtonBar = statusButtonsViewHolder.viewRoot - addView(llButtonBar) - - tvApplication = textView { - gravity = Gravity.END - }.lparams(matchParent, wrapContent) - } - - } - - } - - llConversationIcons = linearLayout { - lparams(matchParent, dip(40)) - - isBaselineAligned = false - gravity = Gravity.START or Gravity.CENTER_VERTICAL - - tvConversationParticipants = textView { - text = context.getString(R.string.participants) - }.lparams(wrapContent, wrapContent) { - endMargin = dip(3) - } - - ivConversationIcon1 = myNetworkImageView { - scaleType = ImageView.ScaleType.CENTER_CROP - }.lparams(dip(24), dip(24)) { - endMargin = dip(3) - } - ivConversationIcon2 = myNetworkImageView { - scaleType = ImageView.ScaleType.CENTER_CROP - }.lparams(dip(24), dip(24)) { - endMargin = dip(3) - } - ivConversationIcon3 = myNetworkImageView { - scaleType = ImageView.ScaleType.CENTER_CROP - }.lparams(dip(24), dip(24)) { - endMargin = dip(3) - } - ivConversationIcon4 = myNetworkImageView { - scaleType = ImageView.ScaleType.CENTER_CROP - }.lparams(dip(24), dip(24)) { - endMargin = dip(3) - } - - tvConversationIconsMore = textView { - - }.lparams(wrapContent, wrapContent) - } - - llSearchTag = linearLayout { - lparams(matchParent, wrapContent) - - btnSearchTag = button { - background = - ContextCompat.getDrawable(context, R.drawable.btn_bg_transparent_round6dp) - allCaps = false - }.lparams(0, wrapContent) { - weight = 1f - } - - btnGapHead = imageButton { - - background = ContextCompat.getDrawable( + llButtonBar = statusButtonsViewHolder.viewRoot + addView(llButtonBar) + + tvApplication = textView { + gravity = Gravity.END + }.lparams(matchParent, wrapContent) + } + + } + + } + + llConversationIcons = linearLayout { + lparams(matchParent, dip(40)) + + isBaselineAligned = false + gravity = Gravity.START or Gravity.CENTER_VERTICAL + + tvConversationParticipants = textView { + text = context.getString(R.string.participants) + }.lparams(wrapContent, wrapContent) { + endMargin = dip(3) + } + + ivConversationIcon1 = myNetworkImageView { + scaleType = ImageView.ScaleType.CENTER_CROP + }.lparams(dip(24), dip(24)) { + endMargin = dip(3) + } + ivConversationIcon2 = myNetworkImageView { + scaleType = ImageView.ScaleType.CENTER_CROP + }.lparams(dip(24), dip(24)) { + endMargin = dip(3) + } + ivConversationIcon3 = myNetworkImageView { + scaleType = ImageView.ScaleType.CENTER_CROP + }.lparams(dip(24), dip(24)) { + endMargin = dip(3) + } + ivConversationIcon4 = myNetworkImageView { + scaleType = ImageView.ScaleType.CENTER_CROP + }.lparams(dip(24), dip(24)) { + endMargin = dip(3) + } + + tvConversationIconsMore = textView { + + }.lparams(wrapContent, wrapContent) + } + + llSearchTag = linearLayout { + lparams(matchParent, wrapContent) + + btnSearchTag = button { + background = + ContextCompat.getDrawable(context, R.drawable.btn_bg_transparent_round6dp) + allCaps = false + }.lparams(0, wrapContent) { + weight = 1f + } + + btnGapHead = imageButton { + + background = ContextCompat.getDrawable( context, R.drawable.btn_bg_transparent_round6dp ) - contentDescription = context.getString(R.string.read_gap_head) - imageResource = R.drawable.ic_arrow_drop_down - }.lparams(dip(32), matchParent) { - startMargin = dip(8) - } - - btnGapTail = imageButton { - background = ContextCompat.getDrawable( + contentDescription = context.getString(R.string.read_gap_head) + imageResource = R.drawable.ic_arrow_drop_down + }.lparams(dip(32), matchParent) { + startMargin = dip(8) + } + + btnGapTail = imageButton { + background = ContextCompat.getDrawable( context, R.drawable.btn_bg_transparent_round6dp ) - contentDescription = context.getString(R.string.read_gap_tail) - imageResource = R.drawable.ic_arrow_drop_up - }.lparams(dip(32), matchParent) { - startMargin = dip(8) - } - } - - llTrendTag = linearLayout { - lparams(matchParent, wrapContent) - - gravity = Gravity.CENTER_VERTICAL - background = - ContextCompat.getDrawable(context, R.drawable.btn_bg_transparent_round6dp) - - verticalLayout { - lparams(0, wrapContent) { - weight = 1f - } - tvTrendTagName = textView { - }.lparams(matchParent, wrapContent) - - tvTrendTagDesc = textView { - textSize = 12f // SP - }.lparams(matchParent, wrapContent) - } - tvTrendTagCount = textView { - - }.lparams(wrapContent, wrapContent) { - startMargin = dip(6) - endMargin = dip(6) - } - - cvTagHistory = trendTagHistoryView { - - }.lparams(dip(64), dip(32)) - - } - - llList = linearLayout { - lparams(matchParent, wrapContent) - - gravity = Gravity.CENTER_VERTICAL - isBaselineAligned = false - minimumHeight = dip(40) - - btnListTL = button { - background = - ContextCompat.getDrawable(context, R.drawable.btn_bg_transparent_round6dp) - allCaps = false - }.lparams(0, wrapContent) { - weight = 1f - } - - btnListMore = imageButton { - - background = - ContextCompat.getDrawable(context, R.drawable.btn_bg_transparent_round6dp) - imageResource = R.drawable.ic_more - contentDescription = context.getString(R.string.more) - }.lparams(dip(40), matchParent) { - startMargin = dip(4) - } - } - - tvMessageHolder = textView { - padding = dip(4) - }.lparams(matchParent, wrapContent) - - llFollowRequest = linearLayout { - lparams(matchParent, wrapContent) { - topMargin = dip(6) - } - gravity = Gravity.END - - btnFollowRequestAccept = imageButton { - background = - ContextCompat.getDrawable(context, R.drawable.btn_bg_transparent_round6dp) - contentDescription = context.getString(R.string.follow_accept) - imageResource = R.drawable.ic_check - setPadding(0, 0, 0, 0) - }.lparams(dip(48f), dip(32f)) - - btnFollowRequestDeny = imageButton { - background = - ContextCompat.getDrawable(context, R.drawable.btn_bg_transparent_round6dp) - contentDescription = context.getString(R.string.follow_deny) - imageResource = R.drawable.ic_close - setPadding(0, 0, 0, 0) - }.lparams(dip(48f), dip(32f)) { - startMargin = dip(4) - } - } - - llFilter = verticalLayout { - lparams(matchParent, wrapContent) { - } - minimumHeight = dip(40) - - tvFilterPhrase = textView { - typeface = Typeface.DEFAULT_BOLD - }.lparams(matchParent, wrapContent) - - tvFilterDetail = textView { - textSize = 12f // SP - }.lparams(matchParent, wrapContent) - } - } - b.report() - rv - } + contentDescription = context.getString(R.string.read_gap_tail) + imageResource = R.drawable.ic_arrow_drop_up + }.lparams(dip(32), matchParent) { + startMargin = dip(8) + } + } + + llTrendTag = linearLayout { + lparams(matchParent, wrapContent) + + gravity = Gravity.CENTER_VERTICAL + background = + ContextCompat.getDrawable(context, R.drawable.btn_bg_transparent_round6dp) + + verticalLayout { + lparams(0, wrapContent) { + weight = 1f + } + tvTrendTagName = textView { + }.lparams(matchParent, wrapContent) + + tvTrendTagDesc = textView { + textSize = 12f // SP + }.lparams(matchParent, wrapContent) + } + tvTrendTagCount = textView { + + }.lparams(wrapContent, wrapContent) { + startMargin = dip(6) + endMargin = dip(6) + } + + cvTagHistory = trendTagHistoryView { + + }.lparams(dip(64), dip(32)) + + } + + llList = linearLayout { + lparams(matchParent, wrapContent) + + gravity = Gravity.CENTER_VERTICAL + isBaselineAligned = false + minimumHeight = dip(40) + + btnListTL = button { + background = + ContextCompat.getDrawable(context, R.drawable.btn_bg_transparent_round6dp) + allCaps = false + }.lparams(0, wrapContent) { + weight = 1f + } + + btnListMore = imageButton { + + background = + ContextCompat.getDrawable(context, R.drawable.btn_bg_transparent_round6dp) + imageResource = R.drawable.ic_more + contentDescription = context.getString(R.string.more) + }.lparams(dip(40), matchParent) { + startMargin = dip(4) + } + } + + tvMessageHolder = textView { + padding = dip(4) + }.lparams(matchParent, wrapContent) + + llFollowRequest = linearLayout { + lparams(matchParent, wrapContent) { + topMargin = dip(6) + } + gravity = Gravity.END + + btnFollowRequestAccept = imageButton { + background = + ContextCompat.getDrawable(context, R.drawable.btn_bg_transparent_round6dp) + contentDescription = context.getString(R.string.follow_accept) + imageResource = R.drawable.ic_check + setPadding(0, 0, 0, 0) + }.lparams(dip(48f), dip(32f)) + + btnFollowRequestDeny = imageButton { + background = + ContextCompat.getDrawable(context, R.drawable.btn_bg_transparent_round6dp) + contentDescription = context.getString(R.string.follow_deny) + imageResource = R.drawable.ic_close + setPadding(0, 0, 0, 0) + }.lparams(dip(48f), dip(32f)) { + startMargin = dip(4) + } + } + + llFilter = verticalLayout { + lparams(matchParent, wrapContent) { + } + minimumHeight = dip(40) + + tvFilterPhrase = textView { + typeface = Typeface.DEFAULT_BOLD + }.lparams(matchParent, wrapContent) + + tvFilterDetail = textView { + textSize = 12f // SP + }.lparams(matchParent, wrapContent) + } + } + b.report() + rv + } } diff --git a/app/src/main/java/jp/juggler/subwaytooter/SideMenuAdapter.kt b/app/src/main/java/jp/juggler/subwaytooter/SideMenuAdapter.kt index eb0b71f9..789bcaf6 100644 --- a/app/src/main/java/jp/juggler/subwaytooter/SideMenuAdapter.kt +++ b/app/src/main/java/jp/juggler/subwaytooter/SideMenuAdapter.kt @@ -122,7 +122,7 @@ class SideMenuAdapter( ) setSpan( ForegroundColorSpan( - appContext.getAttributeColor(R.attr.colorRegexFilterError) + appContext.attrColor(R.attr.colorRegexFilterError) ), start, length, Spannable.SPAN_EXCLUSIVE_EXCLUSIVE @@ -362,7 +362,7 @@ class SideMenuAdapter( } ) - private val iconColor = actMain.getAttributeColor(R.attr.colorTimeSmall) + private val iconColor = actMain.attrColor(R.attr.colorTimeSmall) override fun getCount() : Int = list.size override fun getItem(position : Int) : Any = list[position] @@ -427,7 +427,7 @@ class SideMenuAdapter( FrameLayout.LayoutParams.MATCH_PARENT, FrameLayout.LayoutParams.MATCH_PARENT ) - backgroundColor = actMain.getAttributeColor(R.attr.colorWindowBackground) + backgroundColor = actMain.attrColor(R.attr.colorWindowBackground) selector = StateListDrawable() divider = null dividerHeight = 0 diff --git a/app/src/main/java/jp/juggler/subwaytooter/StatusButtons.kt b/app/src/main/java/jp/juggler/subwaytooter/StatusButtons.kt index a8bde810..68d69daa 100644 --- a/app/src/main/java/jp/juggler/subwaytooter/StatusButtons.kt +++ b/app/src/main/java/jp/juggler/subwaytooter/StatusButtons.kt @@ -66,7 +66,7 @@ internal class StatusButtons( private val color_normal = column.getContentColor() private val color_accent : Int - get() = activity.getAttributeColor(R.attr.colorImageButtonAccent) + get() = activity.attrColor(R.attr.colorImageButtonAccent) init { this.access_info = column.access_info diff --git a/app/src/main/java/jp/juggler/subwaytooter/Styler.kt b/app/src/main/java/jp/juggler/subwaytooter/Styler.kt index b142bd1a..e7276eed 100644 --- a/app/src/main/java/jp/juggler/subwaytooter/Styler.kt +++ b/app/src/main/java/jp/juggler/subwaytooter/Styler.kt @@ -18,7 +18,7 @@ import jp.juggler.subwaytooter.span.EmojiImageSpan import jp.juggler.subwaytooter.span.createSpan import jp.juggler.subwaytooter.table.UserRelation import jp.juggler.util.LogCategory -import jp.juggler.util.getAttributeColor +import jp.juggler.util.attrColor import jp.juggler.util.notZero import jp.juggler.util.setIconDrawableId import kotlin.math.max @@ -30,7 +30,7 @@ object Styler { fun defaultColorIcon(context : Context, iconId : Int) : Drawable? = ContextCompat.getDrawable(context, iconId)?.also { - it.setTint(context.getAttributeColor(R.attr.colorVectorDrawable)) + it.setTint(context.attrColor(R.attr.colorVectorDrawable)) it.setTintMode(PorterDuff.Mode.SRC_IN) } @@ -123,7 +123,7 @@ object Styler { val icon_id = getVisibilityIconId(isMisskeyData, visibility) val sv = getVisibilityString(context, isMisskeyData, visibility) - val color = context.getAttributeColor(R.attr.colorVectorDrawable) + val color = context.attrColor(R.attr.colorVectorDrawable) val sb = SpannableStringBuilder() // アイコン部分 @@ -160,11 +160,11 @@ object Styler { ) { fun colorAccent() = Pref.ipButtonFollowingColor(context.pref()).notZero() - ?: context.getAttributeColor(R.attr.colorImageButtonAccent) + ?: context.attrColor(R.attr.colorImageButtonAccent) fun colorError() = Pref.ipButtonFollowRequestColor(context.pref()).notZero() - ?: context.getAttributeColor(R.attr.colorRegexFilterError) + ?: context.attrColor(R.attr.colorRegexFilterError) // 被フォロー状態 when { diff --git a/app/src/main/java/jp/juggler/subwaytooter/ViewHolderHeaderProfile.kt b/app/src/main/java/jp/juggler/subwaytooter/ViewHolderHeaderProfile.kt index f21acc61..60a1464f 100644 --- a/app/src/main/java/jp/juggler/subwaytooter/ViewHolderHeaderProfile.kt +++ b/app/src/main/java/jp/juggler/subwaytooter/ViewHolderHeaderProfile.kt @@ -141,7 +141,7 @@ internal class ViewHolderHeaderProfile( override fun showColor() { llProfile.setBackgroundColor( when(val c = column.column_bg_color) { - 0 -> activity.getAttributeColor(R.attr.colorProfileBackgroundMask) + 0 -> activity.attrColor(R.attr.colorProfileBackgroundMask) else -> - 0x40000000 or (0x00ffffff and c) } ) diff --git a/app/src/main/java/jp/juggler/subwaytooter/api/entity/MisskeyReaction.kt b/app/src/main/java/jp/juggler/subwaytooter/api/entity/MisskeyReaction.kt index 1fff1375..584b2620 100644 --- a/app/src/main/java/jp/juggler/subwaytooter/api/entity/MisskeyReaction.kt +++ b/app/src/main/java/jp/juggler/subwaytooter/api/entity/MisskeyReaction.kt @@ -26,7 +26,7 @@ import jp.juggler.subwaytooter.util.EmojiDecoder //} object MisskeyReaction { - private val oldReactions = mapOf( + private val oldReactions = mapOf( "like" to "\ud83d\udc4d", "love" to "\u2665", "laugh" to "\ud83d\ude06", @@ -42,6 +42,20 @@ object MisskeyReaction { private val reCustomEmoji = """\A:([^:]+):\z""".toRegex() + fun getAnotherExpression(reaction: String): String? { + val customCode = reCustomEmoji.find(reaction)?.groupValues?.elementAtOrNull(1) ?: return null + val cols = customCode.split("@") + val name = cols.elementAtOrNull(0) + val domain = cols.elementAtOrNull(1) + return if (domain == null) ":$name@.:" else if (domain == ".") ":$name:" else null + } + + fun equals(a:String?,b:String?) = when { + a==null -> b==null + b==null -> false + else -> a ==b || getAnotherExpression(a) == b || a == getAnotherExpression(b) + } + fun toSpannableStringBuilder( code: String, options: DecodeOptions, diff --git a/app/src/main/java/jp/juggler/subwaytooter/api/entity/TootStatus.kt b/app/src/main/java/jp/juggler/subwaytooter/api/entity/TootStatus.kt index 2e6e0d8c..8a83c004 100644 --- a/app/src/main/java/jp/juggler/subwaytooter/api/entity/TootStatus.kt +++ b/app/src/main/java/jp/juggler/subwaytooter/api/entity/TootStatus.kt @@ -928,17 +928,7 @@ class TootStatus(parser: TootParser, src: JsonObject) : TimelineItem() { return list } - private fun getAnotherReactionExpression(reaction:String):String{ - // :reaction: => reaction - // :reaction@xxx: => reaction@xxx - val customCode = reaction.replace(":","") - // reaction => :reaction@.: - return if( customCode != reaction && !customCode.contains("@")) - ":${customCode}@.:" - else - reaction - } // return true if updated fun increaseReaction(reaction: String?, byMe: Boolean, caller: String): Boolean { @@ -962,16 +952,14 @@ class TootStatus(parser: TootParser, src: JsonObject) : TimelineItem() { this.reactionCounts = map } - - val anotherExpression = getAnotherReactionExpression(reaction) - - for( entry in map){ - if( entry.key == reaction || entry.key == anotherExpression){ - map[entry.key] = entry.value +1 - return true - } + when ( + val key = reaction.takeIf { map.containsKey(it) } + ?: MisskeyReaction.getAnotherExpression(reaction)?.takeIf { map.containsKey(it) } + ) { + null -> map[reaction] = 1 + else -> map[key] = max(0, map[key]!! + 1) } - map[reaction] = 1 + return true } } @@ -998,15 +986,14 @@ class TootStatus(parser: TootParser, src: JsonObject) : TimelineItem() { this.reactionCounts = map } - val anotherExpression = getAnotherReactionExpression(reaction) + when ( + val key = reaction.takeIf { map.containsKey(it) } + ?: MisskeyReaction.getAnotherExpression(reaction)?.takeIf { map.containsKey(it) } + ) { + null -> map[reaction] = 0 + else -> map[key] = max(0, map[key]!! - 1) + } - for( entry in map){ - if( entry.key == reaction || entry.key == anotherExpression){ - map[entry.key] = max(0,entry.value -1) - return true - } - } - map[reaction] = 0 return true } } @@ -1214,34 +1201,34 @@ class TootStatus(parser: TootParser, src: JsonObject) : TimelineItem() { fun formatTime(context: Context, t: Long, bAllowRelative: Boolean, onlyDate: Boolean = false): String { - val now = System.currentTimeMillis() - var delta = now - t + val now = System.currentTimeMillis() + var delta = now - t - @StringRes val phraseId = if (delta >= 0) - R.string.relative_time_phrase_past - else - R.string.relative_time_phrase_future + @StringRes val phraseId = if (delta >= 0) + R.string.relative_time_phrase_past + else + R.string.relative_time_phrase_future - fun f(v: Long, unit1: Int, units: Int): String { - val vi = v.toInt() - return context.getString( + fun f(v: Long, unit1: Int, units: Int): String { + val vi = v.toInt() + return context.getString( phraseId, vi, context.getString(if (vi <= 1) unit1 else units) ) - } + } - if( onlyDate) return when{ - delta < 40 * 86400000L -> f( + if (onlyDate) return when { + delta < 40 * 86400000L -> f( delta / 86400000L, R.string.relative_time_unit_day1, R.string.relative_time_unit_days ) - else -> - formatDate(t, date_format2, omitZeroSecond = false, omitYear = true) - } + else -> + formatDate(t, date_format2, omitZeroSecond = false, omitYear = true) + } - if (bAllowRelative && Pref.bpRelativeTimestamp(App1.pref)) { + if (bAllowRelative && Pref.bpRelativeTimestamp(App1.pref)) { delta = abs(delta) @@ -1268,13 +1255,13 @@ class TootStatus(parser: TootParser, src: JsonObject) : TimelineItem() { R.string.relative_time_unit_hours ) - delta < 40 * 86400000L -> return f( + delta < 40 * 86400000L -> return f( delta / 86400000L, R.string.relative_time_unit_day1, R.string.relative_time_unit_days ) } - // fall back to absolute time + // fall back to absolute time } return formatDate(t, date_format, omitZeroSecond = false, omitYear = false) @@ -1299,8 +1286,8 @@ class TootStatus(parser: TootParser, src: JsonObject) : TimelineItem() { val dateNow = format.format(Date()) val delm = dateNow.indexOf('-') if (delm != -1 && - dateNow.substring(0, delm + 1) == dateTarget.substring(0,delm + 1) - ) { + dateNow.substring(0, delm + 1) == dateTarget.substring(0, delm + 1) + ) { dateTarget = dateTarget.substring(delm + 1) } } diff --git a/app/src/main/java/jp/juggler/subwaytooter/dialog/DlgAppPicker.kt b/app/src/main/java/jp/juggler/subwaytooter/dialog/DlgAppPicker.kt index 98117008..033b5253 100644 --- a/app/src/main/java/jp/juggler/subwaytooter/dialog/DlgAppPicker.kt +++ b/app/src/main/java/jp/juggler/subwaytooter/dialog/DlgAppPicker.kt @@ -150,7 +150,7 @@ class DlgAppPicker( activity, ivImage, R.drawable.ic_question, - color = activity.getAttributeColor(R.attr.colorVectorDrawable), + color = activity.attrColor(R.attr.colorVectorDrawable), alphaMultiplier = 1f ) } diff --git a/app/src/main/java/jp/juggler/subwaytooter/dialog/DlgListMember.kt b/app/src/main/java/jp/juggler/subwaytooter/dialog/DlgListMember.kt index 8d73ab83..fab2c417 100644 --- a/app/src/main/java/jp/juggler/subwaytooter/dialog/DlgListMember.kt +++ b/app/src/main/java/jp/juggler/subwaytooter/dialog/DlgListMember.kt @@ -134,7 +134,7 @@ class DlgListMember( this.list_owner = a if(a == null) { btnListOwner.setText(R.string.not_selected) - btnListOwner.setTextColor(activity.getAttributeColor( android.R.attr.textColorPrimary)) + btnListOwner.setTextColor(activity.attrColor( android.R.attr.textColorPrimary)) btnListOwner.setBackgroundResource(R.drawable.btn_bg_transparent_round6dp) // @@ -148,7 +148,7 @@ class DlgListMember( btnListOwner.setBackgroundResource(R.drawable.btn_bg_transparent_round6dp) } btnListOwner.textColor = ac.color_fg.notZero() - ?: activity.getAttributeColor( android.R.attr.textColorPrimary) + ?: activity.attrColor( android.R.attr.textColorPrimary) } loadLists() diff --git a/app/src/main/java/jp/juggler/subwaytooter/dialog/EmojiPicker.kt b/app/src/main/java/jp/juggler/subwaytooter/dialog/EmojiPicker.kt index 41eb0002..660fea7b 100644 --- a/app/src/main/java/jp/juggler/subwaytooter/dialog/EmojiPicker.kt +++ b/app/src/main/java/jp/juggler/subwaytooter/dialog/EmojiPicker.kt @@ -269,7 +269,7 @@ class EmojiPicker( setTypeface(typeface, Typeface.BOLD) - textColor = this@EmojiPicker.activity.getAttributeColor(R.attr.colorContentText) + textColor = this@EmojiPicker.activity.attrColor(R.attr.colorContentText) textSize = 16f // SP単位 text = when(val name = it.key) { diff --git a/app/src/main/java/jp/juggler/subwaytooter/util/AppOpener.kt b/app/src/main/java/jp/juggler/subwaytooter/util/AppOpener.kt index 2e6eb7c4..3f7f0207 100644 --- a/app/src/main/java/jp/juggler/subwaytooter/util/AppOpener.kt +++ b/app/src/main/java/jp/juggler/subwaytooter/util/AppOpener.kt @@ -149,7 +149,7 @@ fun Activity.openCustomTab(url: String?, pref:SharedPreferences = pref()) { CustomTabsIntent.Builder() .setDefaultColorSchemeParams( CustomTabColorSchemeParams.Builder() - .setToolbarColor(getAttributeColor(R.attr.colorPrimary)) + .setToolbarColor(attrColor(R.attr.colorPrimary)) .build() ) .setShowTitle(true) diff --git a/app/src/main/java/jp/juggler/subwaytooter/util/CustomShare.kt b/app/src/main/java/jp/juggler/subwaytooter/util/CustomShare.kt index 131e5e79..87ae1fa8 100644 --- a/app/src/main/java/jp/juggler/subwaytooter/util/CustomShare.kt +++ b/app/src/main/java/jp/juggler/subwaytooter/util/CustomShare.kt @@ -10,7 +10,7 @@ import jp.juggler.subwaytooter.R import jp.juggler.subwaytooter.api.entity.TootStatus import jp.juggler.subwaytooter.table.SavedAccount import jp.juggler.util.LogCategory -import jp.juggler.util.getAttributeColor +import jp.juggler.util.attrColor import jp.juggler.util.showToast import jp.juggler.util.systemService @@ -71,7 +71,7 @@ object CustomShare { label = "${context.getString(R.string.copy_to_clipboard)}(${context.getString(R.string.app_name)})" icon = ContextCompat.getDrawable(context, R.drawable.ic_copy)?.mutate()?.apply { - setTint(context.getAttributeColor(R.attr.colorVectorDrawable)) + setTint(context.attrColor(R.attr.colorVectorDrawable)) setTintMode(PorterDuff.Mode.SRC_IN) } } else { diff --git a/app/src/main/java/jp/juggler/subwaytooter/util/PopupAutoCompleteAcct.kt b/app/src/main/java/jp/juggler/subwaytooter/util/PopupAutoCompleteAcct.kt index 92fc51e4..3db43c24 100644 --- a/app/src/main/java/jp/juggler/subwaytooter/util/PopupAutoCompleteAcct.kt +++ b/app/src/main/java/jp/juggler/subwaytooter/util/PopupAutoCompleteAcct.kt @@ -19,7 +19,7 @@ import jp.juggler.subwaytooter.api.entity.Acct import jp.juggler.subwaytooter.view.MyEditText import jp.juggler.util.LogCategory import jp.juggler.util.asciiPattern -import jp.juggler.util.getAttributeColor +import jp.juggler.util.attrColor import jp.juggler.util.groupEx import java.util.* import kotlin.math.min @@ -97,7 +97,7 @@ internal class PopupAutoCompleteAcct( run { val v = activity.layoutInflater .inflate(R.layout.lv_spinner_dropdown, llItems, false) as CheckedTextView - v.setTextColor(activity.getAttributeColor(android.R.attr.textColorPrimary)) + v.setTextColor(activity.attrColor(android.R.attr.textColorPrimary)) v.setText(R.string.close) v.setOnClickListener { acct_popup.dismiss() } llItems.addView(v) @@ -107,7 +107,7 @@ internal class PopupAutoCompleteAcct( if(picker_caption != null && picker_callback != null) { val v = activity.layoutInflater .inflate(R.layout.lv_spinner_dropdown, llItems, false) as CheckedTextView - v.setTextColor(activity.getAttributeColor(android.R.attr.textColorPrimary)) + v.setTextColor(activity.attrColor(android.R.attr.textColorPrimary)) v.text = picker_caption v.setOnClickListener { acct_popup.dismiss() @@ -125,7 +125,7 @@ internal class PopupAutoCompleteAcct( val acct = acct_list[i] val v = activity.layoutInflater .inflate(R.layout.lv_spinner_dropdown, llItems, false) as CheckedTextView - v.setTextColor(activity.getAttributeColor(android.R.attr.textColorPrimary)) + v.setTextColor(activity.attrColor(android.R.attr.textColorPrimary)) v.text = acct if(acct is Spannable) { NetworkEmojiInvalidator(handler, v).register(acct) diff --git a/app/src/main/java/jp/juggler/subwaytooter/util/PostHelper.kt b/app/src/main/java/jp/juggler/subwaytooter/util/PostHelper.kt index 0de220f0..b91ccc7a 100644 --- a/app/src/main/java/jp/juggler/subwaytooter/util/PostHelper.kt +++ b/app/src/main/java/jp/juggler/subwaytooter/util/PostHelper.kt @@ -893,7 +893,7 @@ class PostHelper( sb.append(item.alias) sb.append(": → ") sb.setSpan( - ForegroundColorSpan(activity.getAttributeColor(R.attr.colorTimeSmall)), + ForegroundColorSpan(activity.attrColor(R.attr.colorTimeSmall)), start, sb.length, Spanned.SPAN_EXCLUSIVE_EXCLUSIVE diff --git a/app/src/main/java/jp/juggler/subwaytooter/view/ListDivider.kt b/app/src/main/java/jp/juggler/subwaytooter/view/ListDivider.kt index b23100e9..9667d217 100644 --- a/app/src/main/java/jp/juggler/subwaytooter/view/ListDivider.kt +++ b/app/src/main/java/jp/juggler/subwaytooter/view/ListDivider.kt @@ -7,7 +7,7 @@ import android.graphics.Rect import android.view.View import androidx.recyclerview.widget.RecyclerView import jp.juggler.subwaytooter.R -import jp.juggler.util.getAttributeDrawable +import jp.juggler.util.attrDrawable class ListDivider(context : Context) : RecyclerView.ItemDecoration() { @@ -18,7 +18,7 @@ class ListDivider(context : Context) : RecyclerView.ItemDecoration() { var marginH : Int = 0 } - private val drawable = getAttributeDrawable(context, R.attr.colorSettingDivider) + private val drawable = context.attrDrawable( R.attr.colorSettingDivider) private val paint = Paint() private val rect = Rect() diff --git a/app/src/main/java/jp/juggler/subwaytooter/view/TabletColumnDivider.kt b/app/src/main/java/jp/juggler/subwaytooter/view/TabletColumnDivider.kt index d6cf526a..5b07ed07 100644 --- a/app/src/main/java/jp/juggler/subwaytooter/view/TabletColumnDivider.kt +++ b/app/src/main/java/jp/juggler/subwaytooter/view/TabletColumnDivider.kt @@ -7,7 +7,7 @@ import android.graphics.Rect import android.view.View import androidx.recyclerview.widget.RecyclerView import jp.juggler.subwaytooter.R -import jp.juggler.util.getAttributeDrawable +import jp.juggler.util.attrDrawable class TabletColumnDivider(context : Context) : RecyclerView.ItemDecoration() { @@ -19,7 +19,7 @@ class TabletColumnDivider(context : Context) : RecyclerView.ItemDecoration() { var barWidth : Int = 0 } - private val drawable = getAttributeDrawable(context, R.attr.colorSettingDivider) + private val drawable = context.attrDrawable( R.attr.colorSettingDivider) private val paint = Paint() private val rect = Rect() diff --git a/app/src/main/java/jp/juggler/util/UiUtils.kt b/app/src/main/java/jp/juggler/util/UiUtils.kt index 1d3389d3..284b73be 100644 --- a/app/src/main/java/jp/juggler/util/UiUtils.kt +++ b/app/src/main/java/jp/juggler/util/UiUtils.kt @@ -5,6 +5,7 @@ import android.content.ClipboardManager import android.content.Context import android.content.DialogInterface import android.content.res.ColorStateList +import android.content.res.TypedArray import android.graphics.Color import android.graphics.ColorFilter import android.graphics.PorterDuff @@ -37,40 +38,25 @@ fun Int.applyAlphaMultiplier(alphaMultiplier : Float? = null) : Int { } } -fun Context.getAttributeColor(attrId : Int) : Int { +fun Context.attrColor(attrId : Int) : Int { val a = theme.obtainStyledAttributes(intArrayOf(attrId)) val color = a.getColor(0, Color.BLACK) a.recycle() return color } -fun getAttributeDrawable(context : Context, attrId : Int) : Drawable { - - fun getAttributeResourceId(context : Context, attrId : Int) : Int { - val theme = context.theme - val a = theme.obtainStyledAttributes(intArrayOf(attrId)) - val resourceId = a.getResourceId(0, 0) - a.recycle() - if(resourceId == 0) - throw RuntimeException( - String.format( - Locale.JAPAN, - "attr not defined.attr_id=0x%x", - attrId - ) - ) - return resourceId - } - - val drawableId = getAttributeResourceId(context, attrId) - val d = ContextCompat.getDrawable(context, drawableId) - return d ?: throw RuntimeException( - String.format( - Locale.JAPAN, - "getDrawable failed. drawableId=0x%x", - drawableId - ) - ) +fun TypedArray.use(block:(TypedArray)->T):T = + try{ block(this) }finally{ recycle() } + +fun Context.getAttributeResourceId( attrId : Int) = + theme.obtainStyledAttributes(intArrayOf(attrId)) + .use{ it.getResourceId(0, 0) } + .notZero() ?: error("missing resource id. attr_id=0x${attrId.toString(16)}") + +fun Context.attrDrawable( attrId : Int) : Drawable { + val drawableId = getAttributeResourceId( attrId) + return ContextCompat.getDrawable(this, drawableId) + ?: error("getDrawable failed. drawableId=0x${drawableId.toString(16)}") } ///////////////////////////////////////////////////////// diff --git a/app/src/main/java/jp/juggler/util/ViewUtils.kt b/app/src/main/java/jp/juggler/util/ViewUtils.kt index 043f4896..07df4493 100644 --- a/app/src/main/java/jp/juggler/util/ViewUtils.kt +++ b/app/src/main/java/jp/juggler/util/ViewUtils.kt @@ -108,10 +108,10 @@ fun Context.setSwitchColor( pref : SharedPreferences, root : View? ) { - val colorBg = getAttributeColor(R.attr.colorWindowBackground) + val colorBg = attrColor(R.attr.colorWindowBackground) val colorOn = Pref.ipSwitchOnColor(pref) val colorOff = /* Pref.ipSwitchOffColor(pref).notZero() ?: */ - getAttributeColor(android.R.attr.colorPrimary) + attrColor(android.R.attr.colorPrimary) val colorDisabled = mixColor(colorBg, colorOff) @@ -207,7 +207,7 @@ fun AppCompatActivity.setStatusBarColor(forceDark : Boolean = false) { var c = when { forceDark -> Color.BLACK else -> Pref.ipStatusBarColor(App1.pref).notZero() - ?: getAttributeColor(R.attr.colorPrimaryDark) + ?: attrColor(R.attr.colorPrimaryDark) } statusBarColor = c or Color.BLACK