more split

This commit is contained in:
tateisu 2021-06-28 21:52:26 +09:00
parent d03116840a
commit 1a99182e2b
9 changed files with 301 additions and 323 deletions

View File

@ -6,39 +6,41 @@ import android.content.Intent
import android.content.SharedPreferences import android.content.SharedPreferences
import android.content.res.Configuration import android.content.res.Configuration
import android.graphics.Typeface import android.graphics.Typeface
import android.os.* import android.os.Bundle
import android.text.Spannable import android.os.Handler
import android.view.* import android.view.KeyEvent
import android.widget.* import android.view.View
import android.view.Window
import android.view.WindowManager
import android.widget.HorizontalScrollView
import android.widget.ImageButton
import android.widget.LinearLayout
import androidx.appcompat.app.AppCompatActivity import androidx.appcompat.app.AppCompatActivity
import androidx.core.view.GravityCompat
import androidx.drawerlayout.widget.DrawerLayout import androidx.drawerlayout.widget.DrawerLayout
import androidx.recyclerview.widget.RecyclerView import androidx.recyclerview.widget.RecyclerView
import androidx.viewpager.widget.ViewPager import androidx.viewpager.widget.ViewPager
import jp.juggler.subwaytooter.action.* import jp.juggler.subwaytooter.action.checkAccessToken2
import jp.juggler.subwaytooter.action.timeline
import jp.juggler.subwaytooter.actmain.* import jp.juggler.subwaytooter.actmain.*
import jp.juggler.subwaytooter.actmain.TabletColumnViewHolder
import jp.juggler.subwaytooter.actpost.CompletionHelper import jp.juggler.subwaytooter.actpost.CompletionHelper
import jp.juggler.subwaytooter.api.* import jp.juggler.subwaytooter.api.entity.Acct
import jp.juggler.subwaytooter.api.entity.* import jp.juggler.subwaytooter.api.entity.EntityId
import jp.juggler.subwaytooter.api.entity.TootTag.Companion.findHashtagFromUrl import jp.juggler.subwaytooter.api.entity.TootVisibility
import jp.juggler.subwaytooter.column.* import jp.juggler.subwaytooter.column.*
import jp.juggler.subwaytooter.columnviewholder.ColumnViewHolder import jp.juggler.subwaytooter.dialog.DlgQuickTootMenu
import jp.juggler.subwaytooter.columnviewholder.ViewHolderHeaderBase
import jp.juggler.subwaytooter.columnviewholder.ViewHolderItem
import jp.juggler.subwaytooter.dialog.*
import jp.juggler.subwaytooter.itemviewholder.ItemViewHolder
import jp.juggler.subwaytooter.itemviewholder.StatusButtonsPopup import jp.juggler.subwaytooter.itemviewholder.StatusButtonsPopup
import jp.juggler.subwaytooter.notification.PollingWorker import jp.juggler.subwaytooter.notification.PollingWorker
import jp.juggler.subwaytooter.span.MyClickableSpan import jp.juggler.subwaytooter.span.MyClickableSpan
import jp.juggler.subwaytooter.span.MyClickableSpanHandler import jp.juggler.subwaytooter.span.MyClickableSpanHandler
import jp.juggler.subwaytooter.table.SavedAccount import jp.juggler.subwaytooter.table.SavedAccount
import jp.juggler.subwaytooter.util.* import jp.juggler.subwaytooter.util.EmojiDecoder
import jp.juggler.subwaytooter.view.* import jp.juggler.subwaytooter.util.checkPrivacyPolicy
import jp.juggler.subwaytooter.util.openBrowser
import jp.juggler.subwaytooter.view.MyDrawerLayout
import jp.juggler.subwaytooter.view.MyEditText
import jp.juggler.util.* import jp.juggler.util.*
import java.lang.ref.WeakReference import java.lang.ref.WeakReference
import java.util.* import java.util.*
import kotlin.math.max
class ActMain : AppCompatActivity(), class ActMain : AppCompatActivity(),
View.OnClickListener, View.OnClickListener,
@ -49,21 +51,12 @@ class ActMain : AppCompatActivity(),
companion object { companion object {
private val log = LogCategory("ActMain") private val log = LogCategory("ActMain")
// リザルト
const val RESULT_APP_DATA_IMPORT = Activity.RESULT_FIRST_USER
// リクエスト
// const val REQUEST_CODE_COLUMN_LIST = 1
// const val REQUEST_APP_ABOUT = 3
// const val REQUEST_CODE_NICKNAME = 4
// const val REQUEST_CODE_POST = 5
// const val REQUEST_CODE_TEXT = 8
// const val REQUEST_CODE_LANGUAGE_FILTER = 9
const val COLUMN_WIDTH_MIN_DP = 300 const val COLUMN_WIDTH_MIN_DP = 300
const val STATE_CURRENT_PAGE = "current_page" const val STATE_CURRENT_PAGE = "current_page"
const val RESULT_APP_DATA_IMPORT = Activity.RESULT_FIRST_USER
// ActPostから参照される // ActPostから参照される
var refActMain: WeakReference<ActMain>? = null var refActMain: WeakReference<ActMain>? = null
@ -78,9 +71,6 @@ class ActMain : AppCompatActivity(),
var screenBottomPadding = 0 var screenBottomPadding = 0
var timelineFont: Typeface = Typeface.DEFAULT var timelineFont: Typeface = Typeface.DEFAULT
var timeline_font_bold: Typeface = Typeface.DEFAULT_BOLD var timeline_font_bold: Typeface = Typeface.DEFAULT_BOLD
private fun Float.clipFontSize(): Float =
if (isNaN()) this else max(1f, this)
} }
// アプリ設定のキャッシュ // アプリ設定のキャッシュ
@ -115,8 +105,8 @@ class ActMain : AppCompatActivity(),
// 状態保存の必要なし // 状態保存の必要なし
internal var popupStatusButtons: StatusButtonsPopup? = null internal var popupStatusButtons: StatusButtonsPopup? = null
var phoneViews: PhoneViews? = null var phoneViews: ActMainPhoneViews? = null
var tabletViews: TabletViews? = null var tabletViews: ActMainTabletViews? = null
var nScreenColumn: Int = 0 var nScreenColumn: Int = 0
var nColumnWidth: Int = 0 // dividerの幅を含む var nColumnWidth: Int = 0 // dividerの幅を含む
@ -152,45 +142,35 @@ class ActMain : AppCompatActivity(),
////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////
// 読み取り専用のプロパティ // 読み取り専用のプロパティ
val followCompleteCallback: () -> Unit = { val followCompleteCallback: () -> Unit =
showToast(false, R.string.follow_succeeded) { showToast(false, R.string.follow_succeeded) }
}
val unfollowCompleteCallback: () -> Unit = { val unfollowCompleteCallback: () -> Unit =
showToast(false, R.string.unfollow_succeeded) { showToast(false, R.string.unfollow_succeeded) }
}
val cancelFollowRequestCompleteCallback: () -> Unit = { val cancelFollowRequestCompleteCallback: () -> Unit =
showToast(false, R.string.follow_request_cancelled) { showToast(false, R.string.follow_request_cancelled) }
}
val favouriteCompleteCallback: () -> Unit = { val favouriteCompleteCallback: () -> Unit =
showToast(false, R.string.favourite_succeeded) { showToast(false, R.string.favourite_succeeded) }
}
val unfavouriteCompleteCallback: () -> Unit = { val unfavouriteCompleteCallback: () -> Unit =
showToast(false, R.string.unfavourite_succeeded) { showToast(false, R.string.unfavourite_succeeded) }
}
val bookmarkCompleteCallback: () -> Unit = { val bookmarkCompleteCallback: () -> Unit =
showToast(false, R.string.bookmark_succeeded) { showToast(false, R.string.bookmark_succeeded) }
}
val unbookmarkCompleteCallback: () -> Unit = { val unbookmarkCompleteCallback: () -> Unit =
showToast(false, R.string.unbookmark_succeeded) { showToast(false, R.string.unbookmark_succeeded) }
}
val boostCompleteCallback: () -> Unit = { val boostCompleteCallback: () -> Unit =
showToast(false, R.string.boost_succeeded) { showToast(false, R.string.boost_succeeded) }
}
val unboostCompleteCallback: () -> Unit = { val unboostCompleteCallback: () -> Unit =
showToast(false, R.string.unboost_succeeded) { showToast(false, R.string.unboost_succeeded) }
}
val reactionCompleteCallback: () -> Unit = { val reactionCompleteCallback: () -> Unit =
showToast(false, R.string.reaction_succeeded) { showToast(false, R.string.reaction_succeeded) }
}
// 相対時刻の表記を定期的に更新する // 相対時刻の表記を定期的に更新する
private val procUpdateRelativeTime = object : Runnable { private val procUpdateRelativeTime = object : Runnable {
@ -333,7 +313,7 @@ class ActMain : AppCompatActivity(),
} }
////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////
// アクティビティイベント // ライフサイクルイベント
override fun onCreate(savedInstanceState: Bundle?) { override fun onCreate(savedInstanceState: Bundle?) {
log.d("onCreate") log.d("onCreate")
@ -362,34 +342,12 @@ class ActMain : AppCompatActivity(),
EmojiDecoder.handleUnicodeEmoji = PrefB.bpInAppUnicodeEmoji(pref) EmojiDecoder.handleUnicodeEmoji = PrefB.bpInAppUnicodeEmoji(pref)
acctPadLr = (0.5f + 4f * density).toInt() acctPadLr = (0.5f + 4f * density).toInt()
timelineFontSizeSp = PrefF.fpTimelineFontSize(pref).clipFontSize() reloadTextSize()
acctFontSizeSp = PrefF.fpAcctFontSize(pref).clipFontSize()
notificationTlFontSizeSp = PrefF.fpNotificationTlFontSize(pref).clipFontSize()
headerTextSizeSp = PrefF.fpHeaderTextSize(pref).clipFontSize()
val fv = PrefS.spTimelineSpacing(pref).toFloatOrNull()
timelineSpacing = if (fv != null && fv.isFinite() && fv != 0f) fv else null
initUI() initUI()
updateColumnStrip() updateColumnStrip()
scrollToLastColumn()
if (appState.columnCount > 0) {
val columnPos = PrefI.ipLastColumnPos(pref)
log.d("ipLastColumnPos load $columnPos")
// 前回最後に表示していたカラムの位置にスクロールする
if (columnPos in 0 until appState.columnCount) {
scrollToColumn(columnPos, false)
}
// 表示位置に合わせたイベントを発行
phoneTab(
{ env -> onPageSelected(env.pager.currentItem) },
{ env -> resizeColumnWidth(env) }
)
}
PollingWorker.queueUpdateNotification(this) PollingWorker.queueUpdateNotification(this)
@ -436,10 +394,8 @@ class ActMain : AppCompatActivity(),
} }
override fun onSaveInstanceState(outState: Bundle) { override fun onSaveInstanceState(outState: Bundle) {
super.onSaveInstanceState(outState)
log.d("onSaveInstanceState") log.d("onSaveInstanceState")
super.onSaveInstanceState(outState)
phoneTab( phoneTab(
{ env -> outState.putInt(STATE_CURRENT_PAGE, env.pager.currentItem) }, { env -> outState.putInt(STATE_CURRENT_PAGE, env.pager.currentItem) },
{ env -> { env ->
@ -448,7 +404,6 @@ class ActMain : AppCompatActivity(),
?.let { outState.putInt(STATE_CURRENT_PAGE, it) } ?.let { outState.putInt(STATE_CURRENT_PAGE, it) }
} }
) )
appState.columnList.forEach { it.saveScrollPosition() } appState.columnList.forEach { it.saveScrollPosition() }
} }
@ -461,8 +416,7 @@ class ActMain : AppCompatActivity(),
phoneTab( phoneTab(
{ env -> env.pager.currentItem = pos }, { env -> env.pager.currentItem = pos },
{ env -> { env ->
env.tabletLayoutManager env.tabletLayoutManager.smoothScrollToPosition(env.tabletPager, null, pos)
.smoothScrollToPosition(env.tabletPager, null, pos)
} }
) )
} }
@ -497,9 +451,7 @@ class ActMain : AppCompatActivity(),
} }
benchmark("removeColumnByAccount") { benchmark("removeColumnByAccount") {
val setDbId = newAccounts.map { it.db_id }.toSet() val setDbId = newAccounts.map { it.db_id }.toSet()
// アカウント設定から戻ってきたら、カラムを消す必要があるかもしれない // アカウント設定から戻ってきたら、カラムを消す必要があるかもしれない
appState.columnList appState.columnList
.mapIndexedNotNull { index, column -> .mapIndexedNotNull { index, column ->
@ -519,12 +471,10 @@ class ActMain : AppCompatActivity(),
column.fireColumnColor() column.fireColumnColor()
} }
} }
benchmark("reloadAccountSetting") { benchmark("reloadAccountSetting") {
// 各カラムのアカウント設定を読み直す // 各カラムのアカウント設定を読み直す
reloadAccountSetting(newAccounts) reloadAccountSetting(newAccounts)
} }
benchmark("refreshAfterPost") { benchmark("refreshAfterPost") {
// 投稿直後ならカラムの再取得を行う // 投稿直後ならカラムの再取得を行う
refreshAfterPost() refreshAfterPost()
@ -543,13 +493,9 @@ class ActMain : AppCompatActivity(),
} }
benchmark("fireShowContent") { benchmark("fireShowContent") {
appState.columnList.forEach { appState.columnList.forEach {
it.fireShowContent( it.fireShowContent(reason = "ActMain onStart", reset = true)
reason = "ActMain onStart",
reset = true
)
} }
} }
benchmark("proc_updateRelativeTime") { benchmark("proc_updateRelativeTime") {
// 相対時刻表示の更新 // 相対時刻表示の更新
procUpdateRelativeTime.run() procUpdateRelativeTime.run()
@ -653,197 +599,26 @@ class ActMain : AppCompatActivity(),
override fun onPageScrollStateChanged(state: Int) {} override fun onPageScrollStateChanged(state: Int) {}
override fun onPageScrolled( override fun onPageScrolled(position: Int, positionOffset: Float, positionOffsetPixels: Int) {
position: Int,
positionOffset: Float,
positionOffsetPixels: Int,
) {
updateColumnStripSelection(position, positionOffset) updateColumnStripSelection(position, positionOffset)
} }
override fun onPageSelected(position: Int) { override fun onPageSelected(position: Int) {
handler.post { handler.post {
appState.column(position)?.let { column -> appState.column(position)?.let { column ->
if (!column.bFirstInitialized) { if (!column.bFirstInitialized) column.startLoading()
column.startLoading()
}
scrollColumnStrip(position) scrollColumnStrip(position)
completionHelper.setInstance( completionHelper.setInstance(column.accessInfo.takeIf { !it.isNA })
when {
column.accessInfo.isNA -> null
else -> column.accessInfo
}
)
} }
} }
} }
override fun onBackPressed() { override fun onBackPressed() = onBackPressedImpl()
// メニューが開いていたら閉じる override fun onClick(v: View) = onClickImpl(v)
if (drawer.isDrawerOpen(GravityCompat.START)) {
drawer.closeDrawer(GravityCompat.START)
return
}
// カラムが0個ならアプリを終了する override fun onMyClickableSpanClicked(viewClicked: View, span: MyClickableSpan) =
if (appState.columnCount == 0) { onMyClickableSpanClickedImpl(viewClicked, span)
finish()
return
}
// カラム設定が開いているならカラム設定を閉じる
if (closeColumnSetting()) {
return
}
fun getClosableColumnList(): List<Column> {
val visibleColumnList = ArrayList<Column>()
phoneTab({ env ->
try {
appState.column(env.pager.currentItem)?.addTo(visibleColumnList)
} catch (ex: Throwable) {
log.w(ex)
}
}, { env ->
visibleColumnList.addAll(env.visibleColumns)
})
return visibleColumnList.filter { !it.dontClose }
}
// カラムが1個以上ある場合は設定に合わせて挙動を変える
when (PrefI.ipBackButtonAction(pref)) {
PrefI.BACK_EXIT_APP -> this@ActMain.finish()
PrefI.BACK_OPEN_COLUMN_LIST -> openColumnList()
PrefI.BACK_CLOSE_COLUMN -> {
val closeableColumnList = getClosableColumnList()
when (closeableColumnList.size) {
0 -> {
if (PrefB.bpExitAppWhenCloseProtectedColumn(pref) &&
PrefB.bpDontConfirmBeforeCloseColumn(pref)
) {
this@ActMain.finish()
} else {
showToast(false, R.string.missing_closeable_column)
}
}
1 -> {
closeColumn(closeableColumnList.first())
}
else -> {
showToast(
false,
R.string.cant_close_column_by_back_button_when_multiple_column_shown
)
}
}
}
// ActAppSetting.BACK_ASK_ALWAYS
else -> {
val closeableColumnList = getClosableColumnList()
val dialog = ActionsDialog()
if (closeableColumnList.size == 1) {
val column = closeableColumnList.first()
dialog.addAction(getString(R.string.close_column)) {
closeColumn(column, bConfirmed = true)
}
}
dialog.addAction(getString(R.string.open_column_list)) { openColumnList() }
dialog.addAction(getString(R.string.app_exit)) { this@ActMain.finish() }
dialog.show(this, null)
}
}
}
override fun onClick(v: View) {
when (v.id) {
R.id.btnToot -> openPost()
R.id.btnQuickToot -> performQuickPost(null)
R.id.btnQuickTootMenu -> toggleQuickPostMenu()
R.id.btnMenu -> if (!drawer.isDrawerOpen(GravityCompat.START)) {
drawer.openDrawer(GravityCompat.START)
}
}
}
override fun onMyClickableSpanClicked(viewClicked: View, span: MyClickableSpan) {
// ビュー階層を下から辿って文脈を取得する
var column: Column? = null
var whoRef: TootAccountRef? = null
var view = viewClicked
loop@ while (true) {
when (val tag = view.tag) {
is ItemViewHolder -> {
column = tag.column
whoRef = tag.getAccount()
break@loop
}
is ViewHolderItem -> {
column = tag.ivh.column
whoRef = tag.ivh.getAccount()
break@loop
}
is ColumnViewHolder -> {
column = tag.column
whoRef = null
break@loop
}
is ViewHolderHeaderBase -> {
column = tag.column
whoRef = tag.getAccount()
break@loop
}
is TabletColumnViewHolder -> {
column = tag.columnViewHolder.column
break@loop
}
else -> when (val parent = view.parent) {
is View -> view = parent
else -> break@loop
}
}
}
val hashtagList = ArrayList<String>().apply {
try {
val cs = viewClicked.cast<TextView>()?.text
if (cs is Spannable) {
for (s in cs.getSpans(0, cs.length, MyClickableSpan::class.java)) {
val li = s.linkInfo
val pair = li.url.findHashtagFromUrl()
if (pair != null) add(if (li.text.startsWith('#')) li.text else "#${pair.first}")
}
}
} catch (ex: Throwable) {
log.trace(ex)
}
}
val linkInfo = span.linkInfo
openCustomTab(
this,
nextPosition(column),
linkInfo.url,
accessInfo = column?.accessInfo,
tagList = hashtagList.notEmpty(),
whoRef = whoRef,
linkInfo = linkInfo
)
}
override fun onDrawerSlide(drawerView: View, slideOffset: Float) { override fun onDrawerSlide(drawerView: View, slideOffset: Float) {
completionHelper.closeAcctPopup() completionHelper.closeAcctPopup()
@ -883,8 +658,11 @@ class ActMain : AppCompatActivity(),
return rv return rv
} }
// lateinitなビュー変数を初期化する //////////////////////////////////////////////////////////////////
fun findViews() { // UI初期化
// ビューのlateinit変数を初期化する
private fun findViews() {
llFormRoot = findViewById(R.id.llFormRoot) llFormRoot = findViewById(R.id.llFormRoot)
llEmpty = findViewById(R.id.llEmpty) llEmpty = findViewById(R.id.llEmpty)
drawer = findViewById(R.id.drawer_layout) drawer = findViewById(R.id.drawer_layout)
@ -932,33 +710,9 @@ class ActMain : AppCompatActivity(),
justifyWindowContentPortrait() justifyWindowContentPortrait()
initUIQuickPost() initUIQuickPost()
svColumnStrip.isHorizontalFadingEdgeEnabled = true svColumnStrip.isHorizontalFadingEdgeEnabled = true
val dm = resources.displayMetrics
val density = dm.density
reloadMediaHeight() reloadMediaHeight()
val columnWMin = loadColumnMin(density) initPhoneTablet()
val sw = dm.widthPixels
// スマホモードとタブレットモードの切り替え
if (PrefB.bpDisableTabletMode(pref) || sw < columnWMin * 2) {
phoneViews = PhoneViews(this)
} else {
tabletViews = TabletViews(this)
}
val tmpPhonePager: MyViewPager = findViewById(R.id.viewPager)
val tmpTabletPager: RecyclerView = findViewById(R.id.rvPager)
phoneTab({ env ->
tmpTabletPager.visibility = View.GONE
env.initUI(tmpPhonePager)
resizeAutoCW(sw)
}, { env ->
tmpPhonePager.visibility = View.GONE
env.initUI(tmpTabletPager)
})
showFooterColor() showFooterColor()
} }
} }

View File

@ -0,0 +1,170 @@
package jp.juggler.subwaytooter.actmain
import android.text.Spannable
import android.view.View
import android.widget.TextView
import androidx.core.view.GravityCompat
import jp.juggler.subwaytooter.ActMain
import jp.juggler.subwaytooter.PrefB
import jp.juggler.subwaytooter.PrefI
import jp.juggler.subwaytooter.R
import jp.juggler.subwaytooter.action.openColumnList
import jp.juggler.subwaytooter.action.openPost
import jp.juggler.subwaytooter.api.entity.TootAccountRef
import jp.juggler.subwaytooter.api.entity.TootTag.Companion.findHashtagFromUrl
import jp.juggler.subwaytooter.column.Column
import jp.juggler.subwaytooter.columnviewholder.ColumnViewHolder
import jp.juggler.subwaytooter.columnviewholder.TabletColumnViewHolder
import jp.juggler.subwaytooter.columnviewholder.ViewHolderHeaderBase
import jp.juggler.subwaytooter.columnviewholder.ViewHolderItem
import jp.juggler.subwaytooter.dialog.ActionsDialog
import jp.juggler.subwaytooter.itemviewholder.ItemViewHolder
import jp.juggler.subwaytooter.span.MyClickableSpan
import jp.juggler.subwaytooter.util.openCustomTab
import jp.juggler.util.*
import java.util.*
private val log = LogCategory("ActMainActions")
fun ActMain.onBackPressedImpl() {
// メニューが開いていたら閉じる
if (drawer.isDrawerOpen(GravityCompat.START)) {
drawer.closeDrawer(GravityCompat.START)
return
}
// カラムが0個ならアプリを終了する
if (appState.columnCount == 0) {
finish()
return
}
// カラム設定が開いているならカラム設定を閉じる
if (closeColumnSetting()) {
return
}
fun getClosableColumnList(): List<Column> {
val visibleColumnList = ArrayList<Column>()
phoneTab({ env ->
try {
appState.column(env.pager.currentItem)?.addTo(visibleColumnList)
} catch (ex: Throwable) {
log.w(ex)
}
}, { env ->
visibleColumnList.addAll(env.visibleColumns)
})
return visibleColumnList.filter { !it.dontClose }
}
// カラムが1個以上ある場合は設定に合わせて挙動を変える
when (PrefI.ipBackButtonAction(pref)) {
PrefI.BACK_EXIT_APP -> finish()
PrefI.BACK_OPEN_COLUMN_LIST -> openColumnList()
PrefI.BACK_CLOSE_COLUMN -> {
val closeableColumnList = getClosableColumnList()
when (closeableColumnList.size) {
0 -> when {
PrefB.bpExitAppWhenCloseProtectedColumn(pref) && PrefB.bpDontConfirmBeforeCloseColumn(pref) -> finish()
else -> showToast(false, R.string.missing_closeable_column)
}
1 -> closeColumn(closeableColumnList.first())
else -> showToast(false, R.string.cant_close_column_by_back_button_when_multiple_column_shown)
}
}
// ActAppSetting.BACK_ASK_ALWAYS
else -> {
val closeableColumnList = getClosableColumnList()
val dialog = ActionsDialog()
if (closeableColumnList.size == 1) {
val column = closeableColumnList.first()
dialog.addAction(getString(R.string.close_column)) {
closeColumn(column, bConfirmed = true)
}
}
dialog.addAction(getString(R.string.open_column_list)) { openColumnList() }
dialog.addAction(getString(R.string.app_exit)) { finish() }
dialog.show(this, null)
}
}
}
fun ActMain.onClickImpl(v: View) {
when (v.id) {
R.id.btnToot -> openPost()
R.id.btnQuickToot -> performQuickPost(null)
R.id.btnQuickTootMenu -> toggleQuickPostMenu()
R.id.btnMenu -> if (!drawer.isDrawerOpen(GravityCompat.START)) {
drawer.openDrawer(GravityCompat.START)
}
}
}
fun ActMain.onMyClickableSpanClickedImpl(viewClicked: View, span: MyClickableSpan) {
// ビュー階層を下から辿って文脈を取得する
var column: Column? = null
var whoRef: TootAccountRef? = null
var view = viewClicked
loop@ while (true) {
when (val tag = view.tag) {
is ItemViewHolder -> {
column = tag.column
whoRef = tag.getAccount()
break@loop
}
is ViewHolderItem -> {
column = tag.ivh.column
whoRef = tag.ivh.getAccount()
break@loop
}
is ColumnViewHolder -> {
column = tag.column
whoRef = null
break@loop
}
is ViewHolderHeaderBase -> {
column = tag.column
whoRef = tag.getAccount()
break@loop
}
is TabletColumnViewHolder -> {
column = tag.columnViewHolder.column
break@loop
}
else -> when (val parent = view.parent) {
is View -> view = parent
else -> break@loop
}
}
}
val hashtagList = ArrayList<String>().apply {
try {
val cs = viewClicked.cast<TextView>()?.text
if (cs is Spannable) {
for (s in cs.getSpans(0, cs.length, MyClickableSpan::class.java)) {
val li = s.linkInfo
val pair = li.url.findHashtagFromUrl()
if (pair != null) add(if (li.text.startsWith('#')) li.text else "#${pair.first}")
}
}
} catch (ex: Throwable) {
log.trace(ex)
}
}
val linkInfo = span.linkInfo
openCustomTab(
this,
nextPosition(column),
linkInfo.url,
accessInfo = column?.accessInfo,
tagList = hashtagList.notEmpty(),
whoRef = whoRef,
linkInfo = linkInfo
)
}

View File

@ -7,11 +7,9 @@ import android.widget.ImageView
import android.widget.LinearLayout import android.widget.LinearLayout
import androidx.appcompat.app.AlertDialog import androidx.appcompat.app.AlertDialog
import androidx.recyclerview.widget.RecyclerView import androidx.recyclerview.widget.RecyclerView
import jp.juggler.subwaytooter.ActMain import jp.juggler.subwaytooter.*
import jp.juggler.subwaytooter.PrefB
import jp.juggler.subwaytooter.PrefS
import jp.juggler.subwaytooter.R
import jp.juggler.subwaytooter.column.* import jp.juggler.subwaytooter.column.*
import jp.juggler.subwaytooter.columnviewholder.TabletColumnViewHolder
import jp.juggler.subwaytooter.columnviewholder.scrollToTop2 import jp.juggler.subwaytooter.columnviewholder.scrollToTop2
import jp.juggler.subwaytooter.columnviewholder.showColumnSetting import jp.juggler.subwaytooter.columnviewholder.showColumnSetting
import jp.juggler.subwaytooter.table.AcctColor import jp.juggler.subwaytooter.table.AcctColor
@ -355,7 +353,26 @@ fun ActMain.scrollToColumn(index: Int, smoothScroll: Boolean = true) {
) )
} }
fun ActMain.resizeColumnWidth(views: TabletViews) { // onCreate時に前回のカラムまでスクロールする
fun ActMain.scrollToLastColumn() {
if (appState.columnCount <= 0) return
val columnPos = PrefI.ipLastColumnPos(pref)
log.d("ipLastColumnPos load $columnPos")
// 前回最後に表示していたカラムの位置にスクロールする
if (columnPos in 0 until appState.columnCount) {
scrollToColumn(columnPos, false)
}
// 表示位置に合わせたイベントを発行
phoneTab(
{ env -> onPageSelected(env.pager.currentItem) },
{ env -> resizeColumnWidth(env) }
)
}
fun ActMain.resizeColumnWidth(views: ActMainTabletViews) {
var columnWMinDp = ActMain.COLUMN_WIDTH_MIN_DP var columnWMinDp = ActMain.COLUMN_WIDTH_MIN_DP
val sv = PrefS.spColumnWidth(pref) val sv = PrefS.spColumnWidth(pref)

View File

@ -3,7 +3,7 @@ package jp.juggler.subwaytooter.actmain
import jp.juggler.subwaytooter.ActMain import jp.juggler.subwaytooter.ActMain
import jp.juggler.subwaytooter.view.MyViewPager import jp.juggler.subwaytooter.view.MyViewPager
class PhoneViews(val actMain: ActMain) { class ActMainPhoneViews(val actMain: ActMain) {
internal lateinit var pager: MyViewPager internal lateinit var pager: MyViewPager
internal lateinit var pagerAdapter: ColumnPagerAdapter internal lateinit var pagerAdapter: ColumnPagerAdapter

View File

@ -14,6 +14,7 @@ import jp.juggler.subwaytooter.view.ListDivider
import jp.juggler.util.* import jp.juggler.util.*
import org.jetbrains.anko.backgroundDrawable import org.jetbrains.anko.backgroundDrawable
import java.util.* import java.util.*
import kotlin.math.max
private val log = LogCategory("ActMainStyle") private val log = LogCategory("ActMainStyle")
@ -120,6 +121,18 @@ fun ActMain.reloadMediaHeight() {
appState.mediaThumbHeight = (0.5f + mediaThumbHeightDp * density).toInt() appState.mediaThumbHeight = (0.5f + mediaThumbHeightDp * density).toInt()
} }
private fun Float.clipFontSize(): Float =
if (isNaN()) this else max(1f, this)
fun ActMain.reloadTextSize() {
timelineFontSizeSp = PrefF.fpTimelineFontSize(pref).clipFontSize()
acctFontSizeSp = PrefF.fpAcctFontSize(pref).clipFontSize()
notificationTlFontSizeSp = PrefF.fpNotificationTlFontSize(pref).clipFontSize()
headerTextSizeSp = PrefF.fpHeaderTextSize(pref).clipFontSize()
val fv = PrefS.spTimelineSpacing(pref).toFloatOrNull()
timelineSpacing = if (fv != null && fv.isFinite() && fv != 0f) fv else null
}
fun ActMain.loadColumnMin(density: Float): Int { fun ActMain.loadColumnMin(density: Float): Int {
var x = ActMain.COLUMN_WIDTH_MIN_DP.toFloat() var x = ActMain.COLUMN_WIDTH_MIN_DP.toFloat()
val sv = PrefS.spColumnWidth(pref) val sv = PrefS.spColumnWidth(pref)

View File

@ -1,16 +1,42 @@
package jp.juggler.subwaytooter.actmain package jp.juggler.subwaytooter.actmain
import android.view.View
import androidx.recyclerview.widget.RecyclerView
import jp.juggler.subwaytooter.ActMain import jp.juggler.subwaytooter.ActMain
import jp.juggler.subwaytooter.PrefB
import jp.juggler.subwaytooter.R
import jp.juggler.subwaytooter.view.MyViewPager
// スマホモードならラムダを実行する。タブレットモードならnullを返す // スマホモードならラムダを実行する。タブレットモードならnullを返す
inline fun <R:Any?> ActMain.phoneOnly(code: (PhoneViews) -> R): R? = phoneViews?.let { code(it) } inline fun <R : Any?> ActMain.phoneOnly(code: (ActMainPhoneViews) -> R): R? = phoneViews?.let { code(it) }
// タブレットモードならラムダを実行する。スマホモードならnullを返す // タブレットモードならラムダを実行する。スマホモードならnullを返す
inline fun <R:Any?> ActMain.tabOnly(code: (TabletViews) -> R): R? = tabletViews?.let { code(it) } inline fun <R : Any?> ActMain.tabOnly(code: (ActMainTabletViews) -> R): R? = tabletViews?.let { code(it) }
// スマホモードとタブレットモードでコードを切り替える // スマホモードとタブレットモードでコードを切り替える
inline fun <R:Any?> ActMain.phoneTab(codePhone: (PhoneViews) -> R, codeTablet: (TabletViews) -> R): R { inline fun <R : Any?> ActMain.phoneTab(codePhone: (ActMainPhoneViews) -> R, codeTablet: (ActMainTabletViews) -> R): R {
phoneViews?.let { return codePhone(it) } phoneViews?.let { return codePhone(it) }
tabletViews?.let { return codeTablet(it) } tabletViews?.let { return codeTablet(it) }
error("missing phoneViews/tabletViews") error("missing phoneViews/tabletViews")
} }
fun ActMain.initPhoneTablet() {
val columnWMin = loadColumnMin(density)
val sw = resources.displayMetrics.widthPixels
val tmpPhonePager: MyViewPager = findViewById(R.id.viewPager)
val tmpTabletPager: RecyclerView = findViewById(R.id.rvPager)
// スマホモードとタブレットモードの切り替え
if (PrefB.bpDisableTabletMode(pref) || sw < columnWMin * 2) {
tmpTabletPager.visibility = View.GONE
phoneViews = ActMainPhoneViews(this).apply {
initUI(tmpPhonePager)
}
resizeAutoCW(sw)
} else {
tmpPhonePager.visibility = View.GONE
tabletViews = ActMainTabletViews(this).apply {
initUI(tmpTabletPager)
}
}
}

View File

@ -10,7 +10,7 @@ import jp.juggler.util.clipRange
import kotlin.math.abs import kotlin.math.abs
import kotlin.math.min import kotlin.math.min
class TabletViews(val actMain: ActMain) { class ActMainTabletViews(val actMain: ActMain) {
internal lateinit var tabletPager: RecyclerView internal lateinit var tabletPager: RecyclerView
internal lateinit var tabletPagerAdapter: TabletColumnPagerAdapter internal lateinit var tabletPagerAdapter: TabletColumnPagerAdapter
internal lateinit var tabletLayoutManager: LinearLayoutManager internal lateinit var tabletLayoutManager: LinearLayoutManager

View File

@ -3,6 +3,7 @@ package jp.juggler.subwaytooter.actmain
import android.view.ViewGroup import android.view.ViewGroup
import androidx.recyclerview.widget.RecyclerView import androidx.recyclerview.widget.RecyclerView
import jp.juggler.subwaytooter.ActMain import jp.juggler.subwaytooter.ActMain
import jp.juggler.subwaytooter.columnviewholder.TabletColumnViewHolder
internal class TabletColumnPagerAdapter( internal class TabletColumnPagerAdapter(
private val activity: ActMain, private val activity: ActMain,

View File

@ -1,13 +1,10 @@
package jp.juggler.subwaytooter.actmain package jp.juggler.subwaytooter.columnviewholder
import android.view.ViewGroup import android.view.ViewGroup
import androidx.recyclerview.widget.RecyclerView import androidx.recyclerview.widget.RecyclerView
import jp.juggler.subwaytooter.ActMain import jp.juggler.subwaytooter.ActMain
import jp.juggler.subwaytooter.column.Column import jp.juggler.subwaytooter.column.Column
import jp.juggler.subwaytooter.column.startLoading import jp.juggler.subwaytooter.column.startLoading
import jp.juggler.subwaytooter.columnviewholder.ColumnViewHolder
import jp.juggler.subwaytooter.columnviewholder.onPageCreate
import jp.juggler.subwaytooter.columnviewholder.onPageDestroy
import jp.juggler.util.LogCategory import jp.juggler.util.LogCategory
internal class TabletColumnViewHolder( internal class TabletColumnViewHolder(