mirror of
https://github.com/tateisu/SubwayTooter
synced 2025-02-01 11:26:48 +01:00
- テーマ設定が変わったのでガイドのダイアログを出す
- アプリ設定画面のhttps://stackoverflow.com/questions/13614101/fatal-crash-focus-search-returned-a-view-that-wasnt-able-to-take-focus の対策 - 「アプリ設定/タブレット/スクロール時にカラム端と画面端を揃える」を追加。デフォルトON。
This commit is contained in:
parent
29f68216cf
commit
28aacd3a7f
@ -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()
|
||||
}
|
||||
|
||||
|
@ -455,6 +455,7 @@ class ActMain : AppCompatActivity(),
|
||||
handler.postDelayed(onStartAfter, 1L)
|
||||
|
||||
prNotification.checkOrLaunch()
|
||||
themeDefaultChangedDialog()
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -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()
|
||||
}
|
||||
|
@ -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)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -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) {
|
||||
|
@ -338,6 +338,10 @@ object PrefB {
|
||||
"ManyWindowPost",
|
||||
false
|
||||
)
|
||||
val bpTabletSnap = BooleanPref(
|
||||
"bpTabletSnap",
|
||||
true
|
||||
)
|
||||
|
||||
val bpMfmDecorationEnabled = BooleanPref(
|
||||
"MfmDecorationEnabled",
|
||||
|
@ -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) }
|
||||
|
||||
|
@ -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)
|
||||
|
||||
|
@ -6,4 +6,7 @@ object PrefL {
|
||||
|
||||
// long
|
||||
val lpTabletTootDefaultAccount = LongPref("tablet_toot_default_account", -1L)
|
||||
|
||||
// long
|
||||
val lpThemeDefaultChangedWarnTime = LongPref("lpThemeDefaultChangedWarnTime", -1L)
|
||||
}
|
@ -46,4 +46,6 @@ abstract class BasePref<T>(val key: String, val defVal: T) {
|
||||
} else {
|
||||
false
|
||||
}
|
||||
|
||||
abstract fun hasNonDefaultValue(pref: SharedPreferences): Boolean
|
||||
}
|
@ -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)
|
||||
}
|
@ -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)
|
||||
}
|
@ -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)
|
||||
}
|
||||
|
@ -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)
|
||||
}
|
@ -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()
|
||||
}
|
@ -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>
|
||||
|
@ -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>
|
||||
|
Loading…
x
Reference in New Issue
Block a user