mirror of
https://github.com/tateisu/SubwayTooter
synced 2025-02-08 08:09:02 +01:00
デフォルトの投稿アカウントの設定をタブレットセクションから投稿セクションに移動。簡易投稿と投稿作成画面に投稿者のアイコンを表示。
This commit is contained in:
parent
657302ea14
commit
a5f030e9e9
@ -1019,26 +1019,18 @@ class ActAppSetting : AppCompatActivity(), ColorPickerDialogListener, View.OnCli
|
||||
|
||||
inner class AccountAdapter(val list: List<SavedAccount>) : BaseAdapter() {
|
||||
|
||||
override fun getCount(): Int {
|
||||
return 1 + list.size
|
||||
}
|
||||
|
||||
override fun getItem(position: Int): Any? {
|
||||
return if (position == 0) null else list[position - 1]
|
||||
}
|
||||
|
||||
override fun getItemId(position: Int): Long {
|
||||
return 0
|
||||
}
|
||||
override fun getCount() = 1 + list.size
|
||||
override fun getItemId(position: Int) = 0L
|
||||
override fun getItem(position: Int) = if (position == 0) null else list[position - 1]
|
||||
|
||||
override fun getView(position: Int, viewOld: View?, parent: ViewGroup): View {
|
||||
val view = viewOld ?: layoutInflater.inflate(
|
||||
android.R.layout.simple_spinner_item,
|
||||
R.layout.lv_spinner_wrap_text,
|
||||
parent,
|
||||
false
|
||||
)
|
||||
view.findViewById<TextView>(android.R.id.text1).text = when (position) {
|
||||
0 -> getString(R.string.ask_always)
|
||||
0 -> getString(R.string.default_post_account_default_action)
|
||||
else -> daoAcctColor.getNickname(list[position - 1])
|
||||
}
|
||||
return view
|
||||
@ -1048,16 +1040,24 @@ class ActAppSetting : AppCompatActivity(), ColorPickerDialogListener, View.OnCli
|
||||
val view =
|
||||
viewOld ?: layoutInflater.inflate(R.layout.lv_spinner_dropdown, parent, false)
|
||||
view.findViewById<TextView>(android.R.id.text1).text = when (position) {
|
||||
0 -> getString(R.string.ask_always)
|
||||
0 -> getString(R.string.default_post_account_default_action)
|
||||
else -> daoAcctColor.getNickname(list[position - 1])
|
||||
}
|
||||
return view
|
||||
}
|
||||
|
||||
/**
|
||||
* 設定に保存したdbId から アダプターのインデクス値に変換
|
||||
*/
|
||||
|
||||
// 見つからなければ0,見つかったら1以上
|
||||
internal fun getIndexFromId(dbId: Long): Int =
|
||||
1 + list.indexOfFirst { it.db_id == dbId }
|
||||
|
||||
/**
|
||||
* アダプターのインデクス値から設定に保存するdbIdに変換
|
||||
* - -1L : タブレットモードなら毎回尋ねる。スマホモードなら現在開いているカラム。
|
||||
*/
|
||||
internal fun getIdFromIndex(position: Int): Long =
|
||||
if (position > 0) list[position - 1].db_id else -1L
|
||||
}
|
||||
|
@ -14,6 +14,7 @@ import android.view.Window
|
||||
import android.view.WindowManager
|
||||
import android.widget.HorizontalScrollView
|
||||
import android.widget.ImageButton
|
||||
import android.widget.ImageView
|
||||
import android.widget.LinearLayout
|
||||
import androidx.appcompat.app.AppCompatActivity
|
||||
import androidx.core.content.ContextCompat
|
||||
@ -39,6 +40,7 @@ import jp.juggler.subwaytooter.table.daoSavedAccount
|
||||
import jp.juggler.subwaytooter.util.*
|
||||
import jp.juggler.subwaytooter.view.MyDrawerLayout
|
||||
import jp.juggler.subwaytooter.view.MyEditText
|
||||
import jp.juggler.subwaytooter.view.MyNetworkImageView
|
||||
import jp.juggler.util.backPressed
|
||||
import jp.juggler.util.coroutine.launchAndShowError
|
||||
import jp.juggler.util.data.notEmpty
|
||||
@ -139,6 +141,7 @@ class ActMain : AppCompatActivity(),
|
||||
lateinit var vBottomPadding: View
|
||||
lateinit var llQuickPostBar: LinearLayout
|
||||
lateinit var etQuickPost: MyEditText
|
||||
lateinit var ivQuickTootAccount: MyNetworkImageView
|
||||
lateinit var btnQuickToot: ImageButton
|
||||
lateinit var btnQuickPostMenu: ImageButton
|
||||
lateinit var llEmpty: View
|
||||
@ -696,11 +699,13 @@ class ActMain : AppCompatActivity(),
|
||||
svColumnStrip = findViewById(R.id.svColumnStrip)
|
||||
llQuickPostBar = findViewById(R.id.llQuickTootBar)
|
||||
etQuickPost = findViewById(R.id.etQuickToot)
|
||||
ivQuickTootAccount=findViewById(R.id.ivQuickTootAccount)
|
||||
btnQuickToot = findViewById(R.id.btnQuickToot)
|
||||
btnQuickPostMenu = findViewById(R.id.btnQuickTootMenu)
|
||||
|
||||
btnToot.setOnClickListener(this)
|
||||
btnMenu.setOnClickListener(this)
|
||||
ivQuickTootAccount.setOnClickListener(this)
|
||||
btnQuickToot.setOnClickListener(this)
|
||||
btnQuickPostMenu.setOnClickListener(this)
|
||||
}
|
||||
|
@ -267,6 +267,7 @@ class ActPost : AppCompatActivity(),
|
||||
refActPost = WeakReference(this)
|
||||
when (v.id) {
|
||||
R.id.btnAccount -> performAccountChooser()
|
||||
R.id.ivAccount -> performAccountChooser()
|
||||
R.id.btnVisibility -> openVisibilityPicker()
|
||||
R.id.btnAttachment -> openAttachment()
|
||||
R.id.ivMedia1 -> performAttachmentClick(0)
|
||||
@ -409,6 +410,7 @@ class ActPost : AppCompatActivity(),
|
||||
views.btnPlugin,
|
||||
views.btnEmojiPicker,
|
||||
views.btnMore,
|
||||
views.ivAccount,
|
||||
).forEach { it.setOnClickListener(this) }
|
||||
|
||||
ivMedia.forEach { it.setOnClickListener(this) }
|
||||
|
@ -8,44 +8,44 @@ import jp.juggler.subwaytooter.table.daoSavedAccount
|
||||
|
||||
// デフォルトの投稿先アカウントを探す。アカウント選択が必要な状況ならnull
|
||||
val ActMain.currentPostTarget: SavedAccount?
|
||||
get() = phoneTab(
|
||||
{ env ->
|
||||
val c = env.pagerAdapter.getColumn(env.pager.currentItem)
|
||||
return when {
|
||||
c == null || c.accessInfo.isPseudo -> null
|
||||
else -> c.accessInfo
|
||||
}
|
||||
},
|
||||
{ env ->
|
||||
|
||||
val dbId = PrefL.lpTabletTootDefaultAccount.value
|
||||
if (dbId != -1L) {
|
||||
val a = daoSavedAccount.loadAccount(dbId)
|
||||
if (a != null && !a.isPseudo) return a
|
||||
}
|
||||
|
||||
val accounts = ArrayList<SavedAccount>()
|
||||
for (c in env.visibleColumns) {
|
||||
try {
|
||||
val a = c.accessInfo
|
||||
// 画面内に疑似アカウントがあれば常にアカウント選択が必要
|
||||
if (a.isPseudo) {
|
||||
accounts.clear()
|
||||
break
|
||||
}
|
||||
// 既出でなければ追加する
|
||||
if (accounts.none { it == a }) accounts.add(a)
|
||||
} catch (ignored: Throwable) {
|
||||
get(){
|
||||
val dbId = PrefL.lpDefaultPostAccount.value
|
||||
if (dbId != -1L) {
|
||||
val a = daoSavedAccount.loadAccount(dbId)
|
||||
if (a != null && !a.isPseudo) return a
|
||||
}
|
||||
phoneTab(
|
||||
{ env ->
|
||||
val c = env.pagerAdapter.getColumn(env.pager.currentItem)
|
||||
return when {
|
||||
c == null || c.accessInfo.isPseudo -> null
|
||||
else -> c.accessInfo
|
||||
}
|
||||
},
|
||||
{ env ->
|
||||
val accounts = ArrayList<SavedAccount>()
|
||||
for (c in env.visibleColumns) {
|
||||
try {
|
||||
val a = c.accessInfo
|
||||
// 画面内に疑似アカウントがあれば常にアカウント選択が必要
|
||||
if (a.isPseudo) {
|
||||
accounts.clear()
|
||||
break
|
||||
}
|
||||
// 既出でなければ追加する
|
||||
if (accounts.none { it == a }) accounts.add(a)
|
||||
} catch (ignored: Throwable) {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return when (accounts.size) {
|
||||
// 候補が1つだけならアカウント選択は不要
|
||||
1 -> accounts.first()
|
||||
// 候補が2つ以上ならアカウント選択は必要
|
||||
else -> null
|
||||
}
|
||||
})
|
||||
return when (accounts.size) {
|
||||
// 候補が1つだけならアカウント選択は不要
|
||||
1 -> accounts.first()
|
||||
// 候補が2つ以上ならアカウント選択は必要
|
||||
else -> null
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
fun ActMain.reloadAccountSetting(
|
||||
newAccounts: List<SavedAccount>,
|
||||
|
@ -14,6 +14,7 @@ import jp.juggler.subwaytooter.api.entity.TootAccountRef
|
||||
import jp.juggler.subwaytooter.api.entity.TootTag.Companion.findHashtagFromUrl
|
||||
import jp.juggler.subwaytooter.appsetting.appSettingRoot
|
||||
import jp.juggler.subwaytooter.column.Column
|
||||
import jp.juggler.subwaytooter.column.ColumnType
|
||||
import jp.juggler.subwaytooter.columnviewholder.ColumnViewHolder
|
||||
import jp.juggler.subwaytooter.columnviewholder.TabletColumnViewHolder
|
||||
import jp.juggler.subwaytooter.columnviewholder.ViewHolderHeaderBase
|
||||
@ -112,7 +113,13 @@ fun ActMain.onBackPressedImpl() {
|
||||
fun ActMain.onClickImpl(v: View) {
|
||||
when (v.id) {
|
||||
R.id.btnToot -> openPost()
|
||||
R.id.btnQuickToot -> performQuickPost(null)
|
||||
R.id.ivQuickTootAccount -> quickPostAccountDialog(
|
||||
getString(
|
||||
R.string.account_picker_add_timeline_of,
|
||||
ColumnType.PROFILE.name1(this)
|
||||
)
|
||||
){ openProfileQuickPostAccount(it)}
|
||||
R.id.btnQuickToot -> quickPostAccountDialog{ performQuickPost(it)}
|
||||
R.id.btnQuickTootMenu -> toggleQuickPostMenu()
|
||||
R.id.btnMenu -> if (!drawer.isDrawerOpen(GravityCompat.START)) {
|
||||
drawer.openDrawer(GravityCompat.START)
|
||||
@ -120,6 +127,7 @@ fun ActMain.onClickImpl(v: View) {
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
fun ActMain.onMyClickableSpanClickedImpl(viewClicked: View, span: MyClickableSpan) {
|
||||
// ビュー階層を下から辿って文脈を取得する
|
||||
var column: Column? = null
|
||||
|
@ -18,7 +18,9 @@ import jp.juggler.subwaytooter.pref.PrefI
|
||||
import jp.juggler.subwaytooter.pref.PrefS
|
||||
import jp.juggler.subwaytooter.table.SavedAccount
|
||||
import jp.juggler.subwaytooter.table.daoAcctColor
|
||||
import jp.juggler.subwaytooter.util.AccountCache
|
||||
import jp.juggler.util.*
|
||||
import jp.juggler.util.coroutine.launchMain
|
||||
import jp.juggler.util.data.clip
|
||||
import jp.juggler.util.log.LogCategory
|
||||
import jp.juggler.util.log.showToast
|
||||
@ -468,6 +470,19 @@ fun ActMain.scrollColumnStrip(select: Int) {
|
||||
|
||||
val sx = iconLeft + iconWidth / 2 - svWidth / 2
|
||||
svColumnStrip.smoothScrollTo(sx, 0)
|
||||
|
||||
launchMain {
|
||||
try {
|
||||
val a = AccountCache.load(this@scrollColumnStrip, quickPostAccount())
|
||||
ivQuickTootAccount.setImageUrl(
|
||||
calcIconRound(ivQuickTootAccount.layoutParams.width),
|
||||
urlStatic = a?.avatar_static,
|
||||
urlAnime = a?.avatar,
|
||||
)
|
||||
} catch (ex: Throwable) {
|
||||
log.e(ex, "load account failed.")
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fun ActMain.updateColumnStripSelection(position: Int, positionOffset: Float) {
|
||||
|
@ -10,6 +10,7 @@ import jp.juggler.subwaytooter.App1
|
||||
import jp.juggler.subwaytooter.R
|
||||
import jp.juggler.subwaytooter.actpost.CompletionHelper
|
||||
import jp.juggler.subwaytooter.api.entity.TootVisibility
|
||||
import jp.juggler.subwaytooter.column.ColumnType
|
||||
import jp.juggler.subwaytooter.dialog.pickAccount
|
||||
import jp.juggler.subwaytooter.getVisibilityIconId
|
||||
import jp.juggler.subwaytooter.pref.PrefB
|
||||
@ -17,7 +18,6 @@ import jp.juggler.subwaytooter.table.SavedAccount
|
||||
import jp.juggler.subwaytooter.util.PostImpl
|
||||
import jp.juggler.subwaytooter.util.PostResult
|
||||
import jp.juggler.util.coroutine.launchAndShowError
|
||||
import jp.juggler.util.coroutine.launchMain
|
||||
import jp.juggler.util.ui.hideKeyboard
|
||||
import org.jetbrains.anko.imageResource
|
||||
|
||||
@ -80,30 +80,42 @@ fun ActMain.toggleQuickPostMenu() {
|
||||
dlgQuickTootMenu.toggle()
|
||||
}
|
||||
|
||||
fun ActMain.performQuickPost(account: SavedAccount?) {
|
||||
if (account == null) {
|
||||
val a = if (tabletViews != null && !PrefB.bpQuickTootOmitAccountSelection.value) {
|
||||
// タブレットモードでオプションが無効なら
|
||||
// 簡易投稿は常にアカウント選択する
|
||||
fun ActMain.quickPostAccount(): SavedAccount? =
|
||||
when {
|
||||
// タブレットモードでオプションが無効なら
|
||||
// 簡易投稿は常にアカウント選択する
|
||||
tabletViews != null && !PrefB.bpQuickTootOmitAccountSelection.value -> {
|
||||
null
|
||||
} else {
|
||||
currentPostTarget
|
||||
}
|
||||
else -> currentPostTarget
|
||||
}
|
||||
|
||||
if (a != null && !a.isPseudo) {
|
||||
performQuickPost(a)
|
||||
} else {
|
||||
// アカウントを選択してやり直し
|
||||
launchMain {
|
||||
fun ActMain.quickPostAccountDialog(
|
||||
title: String = getString(R.string.account_picker_toot),
|
||||
block: (SavedAccount) -> Unit,
|
||||
) {
|
||||
val a = quickPostAccount()
|
||||
when {
|
||||
a != null && !a.isPseudo -> block(a)
|
||||
else -> {
|
||||
launchAndShowError {
|
||||
pickAccount(
|
||||
bAllowPseudo = false,
|
||||
bAuto = true,
|
||||
message = getString(R.string.account_picker_toot)
|
||||
)?.let { performQuickPost(it) }
|
||||
message = title,
|
||||
)?.let { block(it) }
|
||||
}
|
||||
}
|
||||
return
|
||||
}
|
||||
}
|
||||
|
||||
fun ActMain.openProfileQuickPostAccount(account: SavedAccount) {
|
||||
account.loginAccount?.id?.let {
|
||||
addColumn(defaultInsertPosition, account, ColumnType.PROFILE, params = arrayOf(it))
|
||||
}
|
||||
}
|
||||
|
||||
fun ActMain.performQuickPost(account: SavedAccount) {
|
||||
|
||||
etQuickPost.hideKeyboard()
|
||||
|
||||
|
@ -6,6 +6,8 @@ import android.graphics.Typeface
|
||||
import android.view.View
|
||||
import android.view.ViewGroup
|
||||
import android.widget.LinearLayout
|
||||
import androidx.core.content.ContextCompat
|
||||
import androidx.core.graphics.drawable.DrawableCompat
|
||||
import jp.juggler.subwaytooter.ActMain
|
||||
import jp.juggler.subwaytooter.R
|
||||
import jp.juggler.subwaytooter.api.entity.TootStatus
|
||||
@ -237,9 +239,16 @@ fun ActMain.showFooterColor() {
|
||||
getAdaptiveRippleDrawableRound(this, colorButtonBg, colorButtonFg)
|
||||
btnQuickToot.backgroundDrawable =
|
||||
getAdaptiveRippleDrawableRound(this, colorButtonBg, colorButtonFg)
|
||||
ivQuickTootAccount.backgroundDrawable=
|
||||
getAdaptiveRippleDrawableRound(this, colorButtonBg, colorButtonFg)
|
||||
btnQuickPostMenu.backgroundDrawable =
|
||||
getAdaptiveRippleDrawableRound(this, colorButtonBg, colorButtonFg)
|
||||
|
||||
var c = footerButtonFgColor.notZero() ?: attrColor(R.attr.colorTextContent)
|
||||
val d = ContextCompat.getDrawable(this, R.drawable.ic_question)
|
||||
?.let { DrawableCompat.wrap(it).apply { setTint(c) } }
|
||||
ivQuickTootAccount.setDefaultImage(d)
|
||||
|
||||
val csl = ColorStateList.valueOf(
|
||||
footerButtonFgColor.notZero() ?: attrColor(R.attr.colorTextContent)
|
||||
)
|
||||
@ -248,7 +257,7 @@ fun ActMain.showFooterColor() {
|
||||
btnQuickToot.imageTintList = csl
|
||||
btnQuickPostMenu.imageTintList = csl
|
||||
|
||||
val c = footerTabDividerColor.notZero() ?: colorColumnStripBackground
|
||||
c = footerTabDividerColor.notZero() ?: colorColumnStripBackground
|
||||
vFooterDivider1.setBackgroundColor(c)
|
||||
vFooterDivider2.setBackgroundColor(c)
|
||||
|
||||
|
@ -4,11 +4,13 @@ import jp.juggler.subwaytooter.ActPost
|
||||
import jp.juggler.subwaytooter.App1
|
||||
import jp.juggler.subwaytooter.R
|
||||
import jp.juggler.subwaytooter.api.entity.TootVisibility
|
||||
import jp.juggler.subwaytooter.calcIconRound
|
||||
import jp.juggler.subwaytooter.dialog.pickAccount
|
||||
import jp.juggler.subwaytooter.table.SavedAccount
|
||||
import jp.juggler.subwaytooter.table.daoAcctColor
|
||||
import jp.juggler.subwaytooter.table.daoSavedAccount
|
||||
import jp.juggler.subwaytooter.table.sortedByNickname
|
||||
import jp.juggler.subwaytooter.util.AccountCache
|
||||
import jp.juggler.util.coroutine.launchMain
|
||||
import jp.juggler.util.data.notZero
|
||||
import jp.juggler.util.log.LogCategory
|
||||
@ -50,6 +52,19 @@ fun ActPost.selectAccount(a: SavedAccount?) {
|
||||
}
|
||||
updateTextCount()
|
||||
updateFeaturedTags()
|
||||
|
||||
launchMain {
|
||||
try {
|
||||
val ta = AccountCache.load(this@selectAccount, a)
|
||||
views.ivAccount.setImageUrl(
|
||||
calcIconRound(views.ivAccount.layoutParams.width),
|
||||
urlStatic = ta?.avatar_static,
|
||||
urlAnime = ta?.avatar,
|
||||
)
|
||||
} catch (ex: Throwable) {
|
||||
log.e(ex, "failed.")
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fun ActPost.canSwitchAccount(): Boolean {
|
||||
|
@ -214,7 +214,7 @@ suspend fun <T : Any?, A : Context> A.runApiTask2(
|
||||
progressPrefix: String? = null,
|
||||
progressSetup: (progress: ProgressDialogEx) -> Unit = ApiTask.defaultProgressSetupCallback,
|
||||
backgroundBlock: suspend A.(client: TootApiClient) -> T,
|
||||
) = TootTaskRunner2.runApiTask(
|
||||
) :T = TootTaskRunner2.runApiTask(
|
||||
this,
|
||||
accessInfo,
|
||||
null,
|
||||
|
@ -68,8 +68,8 @@ class AuthRepo(
|
||||
fun accountRemove(account: SavedAccount) {
|
||||
// if account is default account of tablet mode,
|
||||
// reset default.
|
||||
if (account.db_id == PrefL.lpTabletTootDefaultAccount.value) {
|
||||
PrefL.lpTabletTootDefaultAccount.value = -1L
|
||||
if (account.db_id == PrefL.lpDefaultPostAccount.value) {
|
||||
PrefL.lpDefaultPostAccount.value = -1L
|
||||
}
|
||||
daoSavedAccount.delete(account.db_id)
|
||||
daoPushMessage.deleteAccount(account.acct)
|
||||
|
@ -423,10 +423,10 @@ object AppDataExporter {
|
||||
}
|
||||
|
||||
run {
|
||||
val old_id = PrefL.lpTabletTootDefaultAccount.value
|
||||
val old_id = PrefL.lpDefaultPostAccount.value
|
||||
if (old_id != -1L) {
|
||||
val new_id = account_id_map[old_id]
|
||||
PrefL.lpTabletTootDefaultAccount.value = new_id ?: -1L
|
||||
PrefL.lpDefaultPostAccount.value = new_id ?: -1L
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -401,6 +401,28 @@ val appSettingRoot = AppSettingItem(null, SettingType.Section, R.string.app_sett
|
||||
|
||||
section(R.string.post) {
|
||||
|
||||
item(
|
||||
SettingType.Spinner,
|
||||
PrefL.lpDefaultPostAccount,
|
||||
R.string.post_compose_button_default_account
|
||||
) {
|
||||
val lp = pref.cast<LongPref>()!!
|
||||
spinnerInitializer = { spinner ->
|
||||
launchAndShowError {
|
||||
val list = daoSavedAccount.loadRealAccounts()
|
||||
.sortedByNickname()
|
||||
val listAdapter = AccountAdapter(list)
|
||||
spinner.adapter = listAdapter
|
||||
spinner.setSelection(listAdapter.getIndexFromId(lp.value))
|
||||
}
|
||||
}
|
||||
spinnerOnSelected = { spinner, index ->
|
||||
spinner.adapter.cast<ActAppSetting.AccountAdapter>()
|
||||
?.getIdFromIndex(index)
|
||||
?.let { lp.value = it }
|
||||
}
|
||||
}
|
||||
|
||||
spinner(
|
||||
PrefI.ipRefreshAfterToot,
|
||||
R.string.refresh_after_toot,
|
||||
@ -451,28 +473,6 @@ val appSettingRoot = AppSettingItem(null, SettingType.Section, R.string.app_sett
|
||||
|
||||
text(PrefS.spColumnWidth, R.string.minimum_column_width, InputTypeEx.number)
|
||||
|
||||
item(
|
||||
SettingType.Spinner,
|
||||
PrefL.lpTabletTootDefaultAccount,
|
||||
R.string.toot_button_default_account
|
||||
) {
|
||||
val lp = pref.cast<LongPref>()!!
|
||||
spinnerInitializer = { spinner ->
|
||||
launchAndShowError {
|
||||
val list = daoSavedAccount.loadAccountList()
|
||||
.sortedByNickname()
|
||||
val adapter = AccountAdapter(list)
|
||||
spinner.adapter = adapter
|
||||
spinner.setSelection(adapter.getIndexFromId(lp.value))
|
||||
}
|
||||
}
|
||||
spinnerOnSelected = { spinner, index ->
|
||||
spinner.adapter.cast<ActAppSetting.AccountAdapter>()
|
||||
?.getIdFromIndex(index)
|
||||
?.let { lp.value = it }
|
||||
}
|
||||
}
|
||||
|
||||
sw(
|
||||
PrefB.bpQuickTootOmitAccountSelection,
|
||||
R.string.quick_toot_omit_account_selection
|
||||
|
@ -5,7 +5,7 @@ import jp.juggler.subwaytooter.pref.impl.LongPref
|
||||
object PrefL {
|
||||
|
||||
// long
|
||||
val lpTabletTootDefaultAccount = LongPref("tablet_toot_default_account", -1L)
|
||||
val lpDefaultPostAccount = LongPref("tablet_toot_default_account", -1L)
|
||||
|
||||
// long
|
||||
val lpThemeDefaultChangedWarnTime = LongPref("lpThemeDefaultChangedWarnTime", -1L)
|
||||
|
@ -534,22 +534,14 @@ class SavedAccount(
|
||||
this.extraJson = b.extraJson
|
||||
this.imageMaxMegabytes = b.imageMaxMegabytes
|
||||
this.imageResize = b.imageResize
|
||||
this.lang = b.lang
|
||||
this.movieMaxMegabytes = b.movieMaxMegabytes
|
||||
this.movieTranscodeBitrate = b.movieTranscodeBitrate
|
||||
this.movieTranscodeFramerate = b.movieTranscodeFramerate
|
||||
this.movieTranscodeMode = b.movieTranscodeMode
|
||||
this.movieTranscodeSquarePixels = b.movieTranscodeSquarePixels
|
||||
this.notificationBoost = b.notificationBoost
|
||||
this.notificationFavourite = b.notificationFavourite
|
||||
this.notificationFollow = b.notificationFollow
|
||||
this.notificationFollowRequest = b.notificationFollowRequest
|
||||
this.notificationMention = b.notificationMention
|
||||
this.notificationPost = b.notificationPost
|
||||
this.notificationPullEnable = b.notificationPullEnable
|
||||
this.notificationPushEnable = b.notificationPushEnable
|
||||
this.notificationReaction = b.notificationReaction
|
||||
this.notificationStatusReference = b.notificationStatusReference
|
||||
this.notificationUpdate = b.notificationUpdate
|
||||
this.notificationVote = b.notificationVote
|
||||
this.pushPolicy = b.pushPolicy
|
||||
|
@ -0,0 +1,70 @@
|
||||
package jp.juggler.subwaytooter.util
|
||||
|
||||
import android.content.Context
|
||||
import android.os.SystemClock
|
||||
import jp.juggler.subwaytooter.api.TootParser
|
||||
import jp.juggler.subwaytooter.api.auth.authRepo
|
||||
import jp.juggler.subwaytooter.api.entity.TootAccount
|
||||
import jp.juggler.subwaytooter.api.runApiTask2
|
||||
import jp.juggler.subwaytooter.table.SavedAccount
|
||||
import jp.juggler.util.coroutine.AppDispatchers
|
||||
import jp.juggler.util.log.LogCategory
|
||||
import jp.juggler.util.network.toPostRequestBuilder
|
||||
import kotlinx.coroutines.sync.Mutex
|
||||
import kotlinx.coroutines.sync.withLock
|
||||
import kotlinx.coroutines.withContext
|
||||
|
||||
object AccountCache {
|
||||
private val log = LogCategory("AccountCache")
|
||||
|
||||
private class CacheItem(val timeCached: Long, val result: TootAccount?)
|
||||
|
||||
private val cacheMutex = Mutex()
|
||||
private val map = HashMap<String, CacheItem>()
|
||||
private const val CACHE_EXPIRE_SUCCESS = 300_000L
|
||||
private const val CACHE_EXPIRE_ERROR = 120_000L
|
||||
|
||||
suspend fun load(context: Context, src: SavedAccount?): TootAccount? {
|
||||
src ?: return null
|
||||
return withContext(AppDispatchers.IO) {
|
||||
cacheMutex.withLock {
|
||||
val key = src.acct.ascii
|
||||
try {
|
||||
val cached = map[key]
|
||||
if (cached != null) {
|
||||
val now = SystemClock.elapsedRealtime()
|
||||
val expire =
|
||||
if (cached.result != null) CACHE_EXPIRE_SUCCESS else CACHE_EXPIRE_ERROR
|
||||
if (cached.timeCached >= now - expire) return@withLock cached.result
|
||||
}
|
||||
val newAccount = context.runApiTask2(src) { client ->
|
||||
val json = if (src.isMisskey) {
|
||||
val result = client.request(
|
||||
"/api/i",
|
||||
src.putMisskeyApiToken().toPostRequestBuilder()
|
||||
) ?: return@runApiTask2 null
|
||||
result.error?.let { error(it) }
|
||||
result.jsonObject
|
||||
} else {
|
||||
// 承認待ち状態のチェック
|
||||
authRepo.checkConfirmed(src, client)
|
||||
|
||||
val result = client.request(
|
||||
"/api/v1/accounts/verify_credentials"
|
||||
) ?: return@runApiTask2 null
|
||||
result.error?.let { error(it) }
|
||||
result.jsonObject
|
||||
}
|
||||
TootParser(this, src).account(json) ?: error("parse error.")
|
||||
}
|
||||
map[key] = CacheItem(SystemClock.elapsedRealtime(), newAccount)
|
||||
return@withLock newAccount
|
||||
} catch (ex: Throwable) {
|
||||
log.e(ex, "failed.")
|
||||
map[key] = CacheItem(SystemClock.elapsedRealtime(), null)
|
||||
return@withLock null
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
@ -116,19 +116,19 @@ class MyNetworkImageView : AppCompatImageView {
|
||||
|
||||
fun setImageUrl(
|
||||
r: Float,
|
||||
url: String?,
|
||||
animeUrl: String? = null,
|
||||
urlStatic: String?,
|
||||
urlAnime: String? = null,
|
||||
) {
|
||||
mCornerRadius = r
|
||||
if (PrefB.bpImageAnimationEnable.value) {
|
||||
animeUrl?.notEmpty()?.let {
|
||||
urlAnime?.notEmpty()?.let {
|
||||
mUrl = it
|
||||
mMayAnime = true
|
||||
loadImageIfNecessary()
|
||||
return
|
||||
}
|
||||
}
|
||||
mUrl = url
|
||||
mUrl = urlStatic
|
||||
mMayAnime = false
|
||||
loadImageIfNecessary()
|
||||
}
|
||||
@ -148,7 +148,7 @@ class MyNetworkImageView : AppCompatImageView {
|
||||
return null
|
||||
}
|
||||
|
||||
fun cancelLoading(defaultDrawable: Drawable? = null) {
|
||||
fun cancelLoading(defaultDrawable: Drawable? = mDefaultImage) {
|
||||
|
||||
val d = drawable
|
||||
if (d is Animatable) {
|
||||
|
@ -118,14 +118,22 @@
|
||||
android:id="@+id/etQuickToot"
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginEnd="6dp"
|
||||
android:layout_marginStart="6dp"
|
||||
android:layout_marginEnd="4dp"
|
||||
android:layout_marginStart="4dp"
|
||||
android:layout_weight="1"
|
||||
android:hint="@string/quick_toot_hint"
|
||||
android:imeOptions="actionSend"
|
||||
android:inputType="text"
|
||||
android:scrollbars="vertical" />
|
||||
|
||||
<jp.juggler.subwaytooter.view.MyNetworkImageView
|
||||
android:id="@+id/ivQuickTootAccount"
|
||||
android:layout_width="32dp"
|
||||
android:layout_height="32dp"
|
||||
android:layout_marginEnd="2dp"
|
||||
android:contentDescription="@string/quick_post_account"
|
||||
android:scaleType="fitCenter" />
|
||||
|
||||
<ImageButton
|
||||
android:id="@+id/btnQuickToot"
|
||||
android:layout_width="48dp"
|
||||
|
@ -86,6 +86,8 @@
|
||||
<LinearLayout
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:baselineAligned="false"
|
||||
android:gravity="center_vertical"
|
||||
android:orientation="horizontal">
|
||||
|
||||
<TextView
|
||||
@ -94,6 +96,14 @@
|
||||
android:layout_marginEnd="4dp"
|
||||
android:text="@string/post_from" />
|
||||
|
||||
<jp.juggler.subwaytooter.view.MyNetworkImageView
|
||||
android:id="@+id/ivAccount"
|
||||
android:layout_width="32dp"
|
||||
android:layout_height="32dp"
|
||||
android:layout_marginEnd="2dp"
|
||||
android:contentDescription="@string/quick_post_account"
|
||||
android:scaleType="fitCenter" />
|
||||
|
||||
<Button
|
||||
android:id="@+id/btnAccount"
|
||||
android:layout_width="0dp"
|
||||
|
@ -1,10 +1,8 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<CheckedTextView
|
||||
<CheckedTextView xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:id="@android:id/text1"
|
||||
style="?android:attr/spinnerDropDownItemStyle"
|
||||
xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:minHeight="48dp"
|
||||
android:background="@drawable/btn_bg_transparent_round6dp"
|
||||
/>
|
||||
android:minHeight="48dp" />
|
||||
|
8
app/src/main/res/layout/lv_spinner_wrap_text.xml
Normal file
8
app/src/main/res/layout/lv_spinner_wrap_text.xml
Normal file
@ -0,0 +1,8 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<TextView xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:id="@android:id/text1"
|
||||
style="?android:attr/spinnerDropDownItemStyle"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:minHeight="48dp"
|
||||
android:padding="4dp" />
|
@ -385,7 +385,7 @@
|
||||
<string name="behavior">Comportament</string>
|
||||
<string name="notification_on_off_desc">També es poden (des)activar notificacions de comptes concrets.</string>
|
||||
<string name="post">Publica</string>
|
||||
<string name="toot_button_default_account">Compte predeterminat en prémer \"Publica\"</string>
|
||||
<string name="post_compose_button_default_account">Compte predeterminat en prémer \"Publica\"</string>
|
||||
<string name="account_change_failed_old_draft_has_no_in_reply_to_url">No s\'ha pogut canviar de compte. Les dades de l\'antic esborrany no tenen in_reply_to_url i no es pot convertir in_reply_to al servidor escollit.</string>
|
||||
<string name="in_reply_to_id_conversion_failed">Ha fallat la conversió de la ID de \"in_reply_to\".</string>
|
||||
<string name="prior_chrome_custom_tabs">Prioritza Google Chrome (si està activat \"pestanyes personalitzades\")</string>
|
||||
|
@ -1003,7 +1003,7 @@
|
||||
<string name="url_omitted">(URL ausgelassen)</string>
|
||||
<string name="enable_speech">Aktiviert Sprachausgabe</string>
|
||||
<string name="account_change_failed_old_draft_has_no_in_reply_to_url" tools:ignore="Typos">Konnte Konto nicht wechseln. Alte Entwurfsdaten besitzen kein in_reply_to_url, kann für gewählten Server nicht in in_reply_to_url umgewandelt werden.</string>
|
||||
<string name="toot_button_default_account">Standardkonto, wenn der „Toot“-Button gedrückt wird</string>
|
||||
<string name="post_compose_button_default_account">Standardkonto, wenn der „Toot“-Button gedrückt wird</string>
|
||||
<string name="notification_on_off_desc">Es gibt auch eine Konteneinstellung, um Benachrichtigungen ein- und auszuschalten.</string>
|
||||
<string name="behavior">Verhalten</string>
|
||||
<string name="performance">Leistung</string>
|
||||
|
@ -359,7 +359,7 @@
|
||||
<string name="performance">Performance</string>
|
||||
<string name="tablet_mode">Mode tablette</string>
|
||||
<string name="post">Publication</string>
|
||||
<string name="toot_button_default_account">Compte par défaut lorsque le bouton \"Pouet\" est appuyé</string>
|
||||
<string name="post_compose_button_default_account">Compte par défaut lorsque le bouton \"Pouet\" est appuyé</string>
|
||||
<string name="account_change_failed_old_draft_has_no_in_reply_to_url">Impossible de changer de compte. Les anciennes données de brouillon n\'ont pas in_reply_to_url, ne peuvent pas convertir in_reply_to_to pour le serveur sélectionné.</string>
|
||||
<string name="in_reply_to_id_conversion_failed">La conversion de l\'ID «in-reply-to» a échoué.</string>
|
||||
<string name="prior_chrome_custom_tabs">Prioriser Google Chrome (si les «onglets personnalisés» sont activés)</string>
|
||||
|
@ -419,7 +419,7 @@
|
||||
<string name="behavior">התנהגות</string>
|
||||
<string name="notification_on_off_desc">יש בנוסף הגדרת חשבון להדלקה/כיבוי התראות.</string>
|
||||
<string name="post">פרסום</string>
|
||||
<string name="toot_button_default_account">חשבון ברירת מחדל לצורך לחיצה על כפתור \"תרועה\"</string>
|
||||
<string name="post_compose_button_default_account">חשבון ברירת מחדל לצורך לחיצה על כפתור \"תרועה\"</string>
|
||||
<string name="enable_speech">אפשר דיבור</string>
|
||||
<string name="url_omitted">(כתובת URL הושמטה)</string>
|
||||
<string name="delete_this_notification">מחק התראה זו</string>
|
||||
|
@ -718,7 +718,7 @@
|
||||
<string name="token_exported">アプリデータのエクスポート、インポート、バックアップからの復元などでアクセストークンが他のデバイスでも使われている可能性があります。アクセストークンの更新をおすすめします。</string>
|
||||
<string name="token_not_specified">アクセストークンを入力してください</string>
|
||||
<string name="toot">トゥート</string>
|
||||
<string name="toot_button_default_account">トゥートボタンを押した時のデフォルトアカウント</string>
|
||||
<string name="post_compose_button_default_account">投稿作成ボタンを押した時のデフォルトアカウント</string>
|
||||
<string name="toot_context_parse_failed">会話データのデコードに失敗</string>
|
||||
<string name="toot_count">トゥート数</string>
|
||||
<string name="toot_default_text">トゥート作成時のデフォルトテキスト (簡易投稿や投稿画面でのアカウント切り替えには影響しません)</string>
|
||||
@ -1245,4 +1245,6 @@
|
||||
<string name="removing_old_unified_push_url">期限切れのUnifiedPushエンドポイントをアプリサーバから削除しています…</string>
|
||||
<string name="sending_push_distributor_info_to_app_server">アプリサーバにプッシュサービスの情報を送信しています…</string>
|
||||
<string name="push_distributor_not_available">プッシュ配送サービスを利用できません。UnifiedPush対応のプッシュ配送アプリをインストールすることで、プッシュ通知を受け取ることができます。詳細 https://unifiedpush.org/</string>
|
||||
<string name="default_post_account_default_action">表示カラムのアカウント(スマホ),または毎回尋ねる(タブレット)</string>
|
||||
<string name="quick_post_account">簡易投稿のアカウント</string>
|
||||
</resources>
|
||||
|
@ -368,7 +368,7 @@
|
||||
<string name="behavior">행동</string>
|
||||
<string name="notification_on_off_desc">알림을 끄고 켜는 계정 설정도 있습니다.</string>
|
||||
<string name="post">게시</string>
|
||||
<string name="toot_button_default_account">툿 버튼이 눌러졌을 때의 기본 계정</string>
|
||||
<string name="post_compose_button_default_account">툿 버튼이 눌러졌을 때의 기본 계정</string>
|
||||
<string name="account_change_failed_old_draft_has_no_in_reply_to_url">계정을 전환하지 못함. 구 초안 데이터는 in_reply_to_url이 없어 선택된 서버에 대해 in_reply_to를 변환할 수 없습니다.</string>
|
||||
<string name="in_reply_to_id_conversion_failed">in_reply_to ID 변환 실패.</string>
|
||||
<string name="prior_chrome_custom_tabs">구글 크롬을 우선적으로 선택 (맞춤 탭이 켜져 있으면)</string>
|
||||
|
@ -293,7 +293,7 @@
|
||||
<string name="performance">Ytelse</string>
|
||||
<string name="behavior">Oppførsel</string>
|
||||
<string name="post">Post</string>
|
||||
<string name="toot_button_default_account">Forvalgt konto når tut-knappen trykkes</string>
|
||||
<string name="post_compose_button_default_account">Forvalgt konto når tut-knappen trykkes</string>
|
||||
<string name="url_omitted">(Nettadresse ikke tatt med)</string>
|
||||
<string name="blocked_domains">Blokkerte domener</string>
|
||||
<string name="block_domain_that">Blokker hele domenet \"%1$s\"</string>
|
||||
|
@ -375,7 +375,7 @@
|
||||
<string name="behavior">Gedrag</string>
|
||||
<string name="notification_on_off_desc">Het is ook mogelijk om notificaties per account aan/uit te zetten.</string>
|
||||
<string name="post">Post</string>
|
||||
<string name="toot_button_default_account">Standaadaccount wanneer de \"Toot\" knop is ingedrukt</string>
|
||||
<string name="post_compose_button_default_account">Standaadaccount wanneer de \"Toot\" knop is ingedrukt</string>
|
||||
<string name="account_change_failed_old_draft_has_no_in_reply_to_url">Kon niet van account wisselen. Oud concept heeft geen in_reply_to_url, kon in_reply_to niet omzetten voor de geselecteerde server.</string>
|
||||
<string name="in_reply_to_id_conversion_failed">\"in_reply_to\" ID kon niet omgezet worden.</string>
|
||||
<string name="prior_chrome_custom_tabs">Geef Google Chrome prioriteit (wanneer \"Custom tabs\" ingeschakeld zijn)</string>
|
||||
|
@ -102,7 +102,7 @@
|
||||
<string name="enable_speech">启用语音</string>
|
||||
<string name="in_reply_to_id_conversion_failed">\"in_reply_to \"ID转换失败.</string>
|
||||
<string name="account_change_failed_old_draft_has_no_in_reply_to_url">无法切换账号.旧的草稿数据没有in_reply_to_url,无法转换所选服务器的in_reply_to.</string>
|
||||
<string name="toot_button_default_account">点击 \"发嘟文 \"按钮时的默认发送账户</string>
|
||||
<string name="post_compose_button_default_account">点击 \"发嘟文 \"按钮时的默认发送账户</string>
|
||||
<string name="post">发布</string>
|
||||
<string name="notification_on_off_desc">还有一个账户设置可以关闭/开启通知.</string>
|
||||
<string name="behavior">性能</string>
|
||||
|
@ -388,7 +388,7 @@
|
||||
<string name="behavior">Behavior</string>
|
||||
<string name="notification_on_off_desc">There is also an account setting to turn notifications off/on.</string>
|
||||
<string name="post">Post</string>
|
||||
<string name="toot_button_default_account">Default account when \"Toot\" button tapped</string>
|
||||
<string name="post_compose_button_default_account">Default account when compose post button tapped</string>
|
||||
<string name="account_change_failed_old_draft_has_no_in_reply_to_url">Could not switch account. Old draft data has no in_reply_to_url, can\'t convert in_reply_to for selected server.</string>
|
||||
<string name="in_reply_to_id_conversion_failed">\"in_reply_to\" ID conversion failed.</string>
|
||||
<string name="prior_chrome_custom_tabs">Prioritise Google Chrome (if \"Custom Tabs\" is turned on)</string>
|
||||
@ -1262,4 +1262,6 @@
|
||||
<string name="sending_push_distributor_info_to_app_server">Sending push service information to app server…</string>
|
||||
<string name="push_distributor_not_available">Push distributor is not available. You can receive push notifications by installing a UnifiedPush compatible push delivery app. see https://unifiedpush.org/</string>
|
||||
<string name="glide_test">glide test</string>
|
||||
<string name="default_post_account_default_action">viewing column account(phone), or ask always(tablet)</string>
|
||||
<string name="quick_post_account">Quick post account</string>
|
||||
</resources>
|
||||
|
Loading…
x
Reference in New Issue
Block a user