1
0
mirror of https://github.com/tateisu/SubwayTooter synced 2025-02-08 08:09:02 +01:00

デフォルトの投稿アカウントの設定をタブレットセクションから投稿セクションに移動。簡易投稿と投稿作成画面に投稿者のアイコンを表示。

This commit is contained in:
tateisu 2023-02-10 19:50:20 +09:00
parent 657302ea14
commit a5f030e9e9
31 changed files with 281 additions and 125 deletions

View File

@ -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
}

View File

@ -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)
}

View File

@ -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) }

View File

@ -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>,

View File

@ -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

View File

@ -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) {

View File

@ -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()

View File

@ -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)

View File

@ -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 {

View File

@ -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,

View File

@ -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)

View File

@ -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
}
}

View File

@ -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

View File

@ -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)

View File

@ -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

View File

@ -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
}
}
}
}
}

View File

@ -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) {

View File

@ -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"

View File

@ -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"

View File

@ -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" />

View 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" />

View File

@ -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>

View File

@ -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>

View File

@ -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>

View File

@ -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>

View File

@ -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>

View File

@ -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>

View File

@ -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>

View File

@ -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>

View File

@ -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>

View File

@ -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>