- テーマ設定が変わったのでガイドのダイアログを出す

- アプリ設定画面のhttps://stackoverflow.com/questions/13614101/fatal-crash-focus-search-returned-a-view-that-wasnt-able-to-take-focus の対策
- 「アプリ設定/タブレット/スクロール時にカラム端と画面端を揃える」を追加。デフォルトON。
This commit is contained in:
tateisu 2023-01-16 14:58:23 +09:00
parent 29f68216cf
commit 28aacd3a7f
17 changed files with 126 additions and 26 deletions

View File

@ -11,10 +11,14 @@ import android.os.Handler
import android.text.Editable
import android.text.TextWatcher
import android.util.JsonWriter
import android.view.KeyEvent
import android.view.View
import android.view.View.FOCUS_FORWARD
import android.view.ViewGroup
import android.view.Window
import android.view.inputmethod.EditorInfo
import android.widget.*
import android.widget.TextView.OnEditorActionListener
import androidx.annotation.ColorInt
import androidx.appcompat.app.AlertDialog
import androidx.appcompat.app.AppCompatActivity
@ -217,7 +221,10 @@ class ActAppSetting : AppCompatActivity(), ColorPickerDialogListener, View.OnCli
val e = pref.edit()
var changed = false
appSettingRoot.scan {
if (it.pref?.removeDefault(pref, e) == true) changed = true
when {
(it.pref as? IntPref)?.noRemove == true -> Unit
it.pref?.removeDefault(pref, e) == true -> changed = true
}
}
if (changed) e.apply()
}
@ -228,6 +235,13 @@ class ActAppSetting : AppCompatActivity(), ColorPickerDialogListener, View.OnCli
if (sv != null) outState.putString(STATE_CHOOSE_INTENT_TARGET, sv)
}
override fun dispatchKeyEvent(event: KeyEvent) = try {
super.dispatchKeyEvent(event)
} catch (ex: Throwable) {
log.e(ex, "dispatchKeyEvent error")
false
}
override fun onStop() {
super.onStop()
@ -482,6 +496,17 @@ class ActAppSetting : AppCompatActivity(), ColorPickerDialogListener, View.OnCli
views.swSwitch.setOnCheckedChangeListener(this)
views.spSpinner.onItemSelectedListener = this
views.etEditText.addTextChangedListener(this)
// https://stackoverflow.com/questions/13614101/fatal-crash-focus-search-returned-a-view-that-wasnt-able-to-take-focus
views.etEditText.setOnEditorActionListener(OnEditorActionListener { textView, actionId, event ->
if (actionId == EditorInfo.IME_ACTION_NEXT) {
@Suppress("WrongConstant")
textView.focusSearch(FOCUS_FORWARD)?.requestFocus(FOCUS_FORWARD)
// 結果に関わらずこのアクションを処理したとみなす
return@OnEditorActionListener true
}
false
})
}
private val tvDesc = views.tvDesc
@ -627,21 +652,20 @@ class ActAppSetting : AppCompatActivity(), ColorPickerDialogListener, View.OnCli
SettingType.EditText -> {
showCaption(name)
views.etEditText.vg(true)
?: error("EditText must have preference.")
views.etEditText.inputType = item.inputType
val text = when (val pi = item.pref) {
is FloatPref ->
item.fromFloat.invoke(actAppSetting, pi(pref))
is StringPref ->
pi(pref)
else -> error("EditText han incorrect pref $pi")
views.etEditText.vg(true)?.let { etEditText ->
val text = when (val pi = item.pref) {
is FloatPref ->
item.fromFloat.invoke(actAppSetting, pi(pref))
is StringPref ->
pi(pref)
else -> error("EditText has incorrect pref $pi")
}
etEditText.hint = item.hint ?: ""
etEditText.inputType = item.inputType
etEditText.setText(text)
etEditText.setSelection(0, text.length)
}
views.etEditText.setText(text)
views.etEditText.setSelection(0, text.length)
item.hint?.let { views.etEditText.hint = it }
updateErrorView()
}

View File

@ -455,6 +455,7 @@ class ActMain : AppCompatActivity(),
handler.postDelayed(onStartAfter, 1L)
prNotification.checkOrLaunch()
themeDefaultChangedDialog()
}
}

View File

@ -1,5 +1,6 @@
package jp.juggler.subwaytooter.actmain
import android.app.AlertDialog
import android.text.Spannable
import android.view.View
import android.widget.TextView
@ -10,6 +11,7 @@ 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.appsetting.appSettingRoot
import jp.juggler.subwaytooter.column.Column
import jp.juggler.subwaytooter.columnviewholder.ColumnViewHolder
import jp.juggler.subwaytooter.columnviewholder.TabletColumnViewHolder
@ -17,8 +19,7 @@ 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.pref.PrefB
import jp.juggler.subwaytooter.pref.PrefI
import jp.juggler.subwaytooter.pref.*
import jp.juggler.subwaytooter.span.MyClickableSpan
import jp.juggler.subwaytooter.util.openCustomTab
import jp.juggler.util.data.addTo
@ -26,6 +27,7 @@ import jp.juggler.util.data.cast
import jp.juggler.util.data.notEmpty
import jp.juggler.util.log.LogCategory
import jp.juggler.util.log.showToast
import java.util.concurrent.TimeUnit
private val log = LogCategory("ActMainActions")
@ -175,3 +177,43 @@ fun ActMain.onMyClickableSpanClickedImpl(viewClicked: View, span: MyClickableSpa
linkInfo = linkInfo
)
}
fun ActMain.themeDefaultChangedDialog() {
val lpThemeDefaultChangedWarnTime = PrefL.lpThemeDefaultChangedWarnTime
val ipUiTheme = PrefI.ipUiTheme
val now = System.currentTimeMillis()
// テーマが未定義でなければ警告しない
if (pref.getInt(ipUiTheme.key, -1) != -1) {
log.i("themeDefaultChangedDialog: theme was set.")
return
}
// 頻繁には警告しない
if (now - lpThemeDefaultChangedWarnTime.invoke(pref) < TimeUnit.DAYS.toMillis(60L)) {
log.i("themeDefaultChangedDialog: avoid frequently check.")
return
}
pref.edit().put(lpThemeDefaultChangedWarnTime, now).apply()
// 色がすべてデフォルトなら警告不要
val customizedKeys = ArrayList<String>()
appSettingRoot.items.find { it.caption == R.string.color }?.scan { item ->
item.pref?.let { p ->
when {
p == PrefS.spBoostAlpha -> Unit
p.hasNonDefaultValue(pref) -> customizedKeys.add(p.key)
}
}
}
log.w("themeDefaultChangedDialog: customizedKeys=${customizedKeys.joinToString(",")}")
if (customizedKeys.isEmpty()) {
pref.edit().put(ipUiTheme, ipUiTheme.defVal).apply()
return
}
AlertDialog.Builder(this)
.setMessage(R.string.color_theme_changed)
.setPositiveButton(android.R.string.ok, null)
.show()
}

View File

@ -5,6 +5,7 @@ import androidx.recyclerview.widget.LinearLayoutManager
import androidx.recyclerview.widget.RecyclerView
import jp.juggler.subwaytooter.ActMain
import jp.juggler.subwaytooter.column.Column
import jp.juggler.subwaytooter.pref.PrefB
import jp.juggler.subwaytooter.view.GravitySnapHelper
import jp.juggler.util.data.clip
import kotlin.math.abs
@ -14,7 +15,6 @@ class ActMainTabletViews(val actMain: ActMain) {
internal lateinit var tabletPager: RecyclerView
internal lateinit var tabletPagerAdapter: TabletColumnPagerAdapter
internal lateinit var tabletLayoutManager: LinearLayoutManager
private lateinit var tabletSnapHelper: GravitySnapHelper
val visibleColumnsIndices: IntRange
get() {
@ -92,8 +92,8 @@ class ActMainTabletViews(val actMain: ActMain) {
// if( animator is DefaultItemAnimator){
// animator.supportsChangeAnimations = false
// }
this.tabletSnapHelper = GravitySnapHelper(Gravity.START)
this.tabletSnapHelper.attachToRecyclerView(this.tabletPager)
if(PrefB.bpTabletSnap()){
GravitySnapHelper(Gravity.START).attachToRecyclerView(this.tabletPager)
}
}
}

View File

@ -479,6 +479,10 @@ val appSettingRoot = AppSettingItem(null, SettingType.Section, R.string.app_sett
PrefB.bpManyWindowPost,
R.string.many_window_post
)
sw(
PrefB.bpTabletSnap,
R.string.tablet_snap
)
}
section(R.string.media_attachment) {

View File

@ -338,6 +338,10 @@ object PrefB {
"ManyWindowPost",
false
)
val bpTabletSnap = BooleanPref(
"bpTabletSnap",
true
)
val bpMfmDecorationEnabled = BooleanPref(
"MfmDecorationEnabled",

View File

@ -12,6 +12,7 @@ fun SharedPreferences.Editor.remove(item: BasePref<*>): SharedPreferences.Editor
return this
}
// 戻り値はEditor
fun SharedPreferences.Editor.put(item: BooleanPref, v: Boolean) =
this.apply { item.put(this, v) }

View File

@ -15,7 +15,7 @@ object PrefI {
const val BACK_OPEN_COLUMN_LIST = 2
const val BACK_EXIT_APP = 3
val ipUiTheme = IntPref("ui_theme", 2)
val ipUiTheme = IntPref("ui_theme", 2, noRemove = true)
// val ipResizeImage = IntPref("resize_image", 4)

View File

@ -6,4 +6,7 @@ object PrefL {
// long
val lpTabletTootDefaultAccount = LongPref("tablet_toot_default_account", -1L)
}
// long
val lpThemeDefaultChangedWarnTime = LongPref("lpThemeDefaultChangedWarnTime", -1L)
}

View File

@ -46,4 +46,6 @@ abstract class BasePref<T>(val key: String, val defVal: T) {
} else {
false
}
abstract fun hasNonDefaultValue(pref: SharedPreferences): Boolean
}

View File

@ -11,4 +11,7 @@ class BooleanPref(key: String, defVal: Boolean) : BasePref<Boolean>(key, defVal)
override fun put(editor: SharedPreferences.Editor, v: Boolean) {
if (v == defVal) editor.remove(key) else editor.putBoolean(key, v)
}
}
override fun hasNonDefaultValue(pref: SharedPreferences) =
defVal != pref.getBoolean(key, defVal)
}

View File

@ -10,4 +10,7 @@ class FloatPref(key: String, defVal: Float) : BasePref<Float>(key, defVal) {
override fun put(editor: SharedPreferences.Editor, v: Float) {
if (v == defVal) editor.remove(key) else editor.putFloat(key, v)
}
override fun hasNonDefaultValue(pref: SharedPreferences) =
defVal != pref.getFloat(key, defVal)
}

View File

@ -2,12 +2,15 @@ package jp.juggler.subwaytooter.pref.impl
import android.content.SharedPreferences
class IntPref(key: String, defVal: Int) : BasePref<Int>(key, defVal) {
class IntPref(key: String, defVal: Int, val noRemove:Boolean = false) : BasePref<Int>(key, defVal) {
override operator fun invoke(pref: SharedPreferences): Int =
pref.getInt(key, defVal)
override fun put(editor: SharedPreferences.Editor, v: Int) {
if (v == defVal) editor.remove(key) else editor.putInt(key, v)
if (!noRemove && v == defVal) editor.remove(key) else editor.putInt(key, v)
}
override fun hasNonDefaultValue(pref: SharedPreferences) =
defVal != pref.getInt(key, defVal)
}

View File

@ -10,4 +10,7 @@ class LongPref(key: String, defVal: Long) : BasePref<Long>(key, defVal) {
override fun put(editor: SharedPreferences.Editor, v: Long) {
if (v == defVal) editor.remove(key) else editor.putLong(key, v)
}
override fun hasNonDefaultValue(pref: SharedPreferences) =
defVal != pref.getLong(key, defVal)
}

View File

@ -15,5 +15,8 @@ class StringPref(
if (v == defVal) editor.remove(key) else editor.putString(key, v)
}
override fun hasNonDefaultValue(pref: SharedPreferences) =
defVal != pref.getString(key, defVal)
fun toInt(pref: SharedPreferences) = invoke(pref).toIntOrNull() ?: defVal.toInt()
}

View File

@ -1178,5 +1178,7 @@
<string name="filter_title_empty">フィルタ名がカラです</string>
<string name="acct_customize">Acct customize</string>
<string name="delete_confirm">「%1$s」を削除しますか?</string>
<string name="color_theme_changed">色テーマのデフォルトが変わりました。カスタマイズ済の色設定と競合する場合があります。 アプリ設定の色セクションを確認することをお勧めします。</string>
<string name="tablet_snap">スクロール時にカラム端と画面端を揃える (アプリ再起動が必要)</string>
</resources>

View File

@ -1185,4 +1185,6 @@
<string name="filter_title_empty">filter title is empty.</string>
<string name="acct_customize">Acct customize</string>
<string name="delete_confirm">delete \"%1$s\" ?</string>
<string name="color_theme_changed">Default color theme has been updated. This may conflict with your customized color settings. We recommend reviewing the colors section in app settings.</string>
<string name="tablet_snap" >Align column edge to screen edge when scrolling (app restart required)</string>
</resources>