サイドメニューにバージョン表記。アップデートの有無を確認して表示。

This commit is contained in:
tateisu 2020-08-28 09:25:48 +09:00
parent 1aa15618c9
commit 52a5ad4eaa
7 changed files with 200 additions and 84 deletions

2
.gitignore vendored
View File

@ -4,6 +4,8 @@
/.idea/workspace.xml /.idea/workspace.xml
/.idea/libraries /.idea/libraries
/.idea/assetWizardSettings.xml /.idea/assetWizardSettings.xml
/.idea/jarRepositories.xml
.DS_Store .DS_Store
/build /build
/captures /captures

View File

@ -1340,7 +1340,7 @@ class ActMain : AsyncActivity()
SideMenuAdapter(this, findViewById(R.id.nav_view), drawer) SideMenuAdapter(this, handler, findViewById(R.id.nav_view), drawer)
btnMenu = findViewById(R.id.btnMenu) btnMenu = findViewById(R.id.btnMenu)
btnToot = findViewById(R.id.btnToot) btnToot = findViewById(R.id.btnToot)

View File

@ -947,6 +947,8 @@ val appSettingRoot = AppSettingItem(null, SettingType.Section, R.string.app_sett
action(R.string.drawable_list) { action(R.string.drawable_list) {
action = { startActivity(Intent(this, ActDrawableList::class.java)) } action = { startActivity(Intent(this, ActDrawableList::class.java)) }
} }
sw(Pref.bpCheckBetaVersion, R.string.check_beta_release)
} }
action(R.string.app_data_export) { action(R.string.app_data_export) {

View File

@ -431,6 +431,12 @@ object Pref {
"EmojiPickerCloseOnSelected", "EmojiPickerCloseOnSelected",
true true
) )
val bpCheckBetaVersion = BooleanPref(
"CheckBetaVersion",
false
)
// int // int
val ipBackButtonAction = IntPref("back_button_action", 0) val ipBackButtonAction = IntPref("back_button_action", 0)
@ -558,9 +564,7 @@ object Pref {
val spBoostAlpha = StringPref("BoostAlpha", "60") val spBoostAlpha = StringPref("BoostAlpha", "60")
val spScreenBottomPadding = StringPref("ScreenBottomPadding", "0") val spScreenBottomPadding = StringPref("ScreenBottomPadding", "0")
val spVersionNameWhenReleaseNoteTap = StringPref("VersionNameWhenReleaseNoteTap", "")
val spPullNotificationCheckInterval = StringPref("PullNotificationCheckInterval", "15") val spPullNotificationCheckInterval = StringPref("PullNotificationCheckInterval", "15")
val spUserAgent = StringPref("UserAgent", "") val spUserAgent = StringPref("UserAgent", "")

View File

@ -1,10 +1,15 @@
package jp.juggler.subwaytooter package jp.juggler.subwaytooter
import android.content.Context
import android.content.Intent import android.content.Intent
import android.content.pm.PackageManager import android.content.pm.PackageManager
import android.graphics.drawable.StateListDrawable import android.graphics.drawable.StateListDrawable
import android.os.Handler
import android.text.Spannable import android.text.Spannable
import android.text.SpannableStringBuilder import android.text.SpannableStringBuilder
import android.text.TextPaint
import android.text.method.LinkMovementMethod
import android.text.style.ClickableSpan
import android.text.style.ForegroundColorSpan import android.text.style.ForegroundColorSpan
import android.view.View import android.view.View
import android.view.ViewGroup import android.view.ViewGroup
@ -17,17 +22,152 @@ import androidx.drawerlayout.widget.DrawerLayout
import jp.juggler.subwaytooter.action.Action_Account import jp.juggler.subwaytooter.action.Action_Account
import jp.juggler.subwaytooter.action.Action_App import jp.juggler.subwaytooter.action.Action_App
import jp.juggler.subwaytooter.action.Action_Instance import jp.juggler.subwaytooter.action.Action_Instance
import jp.juggler.subwaytooter.api.entity.TootStatus
import jp.juggler.subwaytooter.table.SavedAccount import jp.juggler.subwaytooter.table.SavedAccount
import jp.juggler.util.createColoredDrawable import jp.juggler.subwaytooter.util.VersionString
import jp.juggler.util.getAttributeColor import jp.juggler.util.*
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.GlobalScope
import kotlinx.coroutines.launch
import org.jetbrains.anko.backgroundColor import org.jetbrains.anko.backgroundColor
import java.lang.ref.WeakReference
class SideMenuAdapter( class SideMenuAdapter(
val activity : ActMain, private val actMain : ActMain,
val handler : Handler,
navigationView : ViewGroup, navigationView : ViewGroup,
private val drawer : DrawerLayout private val drawer : DrawerLayout
) : BaseAdapter() { ) : BaseAdapter() {
companion object {
private val itemTypeCount = ItemType.values().size
private var lastVersionView : WeakReference<TextView>? = null
private var versionRow = SpannableStringBuilder("")
private fun getVersionRow() = versionRow
private var releaseInfo : JsonObject? = null
private fun checkVersion(appContext : Context, handler : Handler) {
val currentVersion = try {
val pInfo = appContext.packageManager.getPackageInfo(appContext.packageName, 0)
pInfo.versionName
} catch(ex : PackageManager.NameNotFoundException) {
"??"
}
versionRow = SpannableStringBuilder().apply {
append(
appContext.getString(
R.string.app_name_with_version,
appContext.getString(R.string.app_name),
currentVersion
)
)
}
fun afterGet() {
versionRow = SpannableStringBuilder().apply {
append(
appContext.getString(
R.string.app_name_with_version,
appContext.getString(R.string.app_name),
currentVersion
)
)
val newRelease = when(Pref.bpCheckBetaVersion(Pref.pref(appContext))){
false -> releaseInfo ?.jsonObject("stable")
else -> releaseInfo ?.jsonObject("beta")
}
val newVersion = newRelease
?.string("name")
?.replace("""version\s*""".toRegex(RegexOption.IGNORE_CASE), "")
?.trim()
if( newVersion?.isNotEmpty() != true || VersionString(currentVersion) >= VersionString(newVersion) ) {
val url = "https://github.com/tateisu/SubwayTooter/releases"
append("\n")
val start = length
append(appContext.getString(R.string.release_note))
setSpan(
object:ClickableSpan() {
override fun onClick(widget : View) {
App1.openBrowser(widget.activity as ActMain, url)
}
override fun updateDrawState(ds : TextPaint) {
super.updateDrawState(ds)
ds.isUnderlineText = false
}
},
start, length,Spannable.SPAN_EXCLUSIVE_EXCLUSIVE
)
} else {
append("\n")
var start = length
append(
appContext.getString(
R.string.new_version_available,
newVersion
)
)
setSpan(
ForegroundColorSpan(
getAttributeColor(
appContext,
R.attr.colorRegexFilterError
)
),
start, length,
Spannable.SPAN_EXCLUSIVE_EXCLUSIVE
)
newRelease.string("html_url")?.let{url->
append("\n")
start = length
append(appContext.getString(R.string.release_note_with_assets))
setSpan(
object:ClickableSpan() {
override fun onClick(widget : View) {
App1.openBrowser(widget.activity as ActMain, url)
}
override fun updateDrawState(ds : TextPaint) {
super.updateDrawState(ds)
ds.isUnderlineText = false
}
},
start, length,Spannable.SPAN_EXCLUSIVE_EXCLUSIVE
)
}
}
}
handler.post { lastVersionView?.get()?.let { it.text = versionRow } }
}
val lastUpdated = releaseInfo?.string("updated_at")?.let { TootStatus.parseTime(it) }
if(lastUpdated != null && System.currentTimeMillis() - lastUpdated < 86400000L) {
afterGet()
} else {
GlobalScope.launch(Dispatchers.IO) {
val json =
App1.getHttpCached("https://mastodon-msg.juggler.jp/appVersion/appVersion.json")
?.decodeUTF8()?.decodeJsonObject()
if(json != null) {
releaseInfo = json
afterGet()
}
}
}
}
}
private enum class ItemType(val id : Int) { private enum class ItemType(val id : Int) {
IT_NORMAL(0), IT_NORMAL(0),
IT_GROUP_HEADER(1), IT_GROUP_HEADER(1),
@ -35,10 +175,6 @@ class SideMenuAdapter(
IT_VERSION(3) IT_VERSION(3)
} }
companion object {
private val itemTypeCount = ItemType.values().size
}
private class Item( private class Item(
val title : Int = 0, val title : Int = 0,
val icon : Int = 0, val icon : Int = 0,
@ -62,6 +198,9 @@ class SideMenuAdapter(
private val list = arrayOf( private val list = arrayOf(
Item(icon = R.drawable.ic_info, title = 1) ,
Item(),
Item(title = R.string.account), Item(title = R.string.account),
Item(title = R.string.account_add, icon = R.drawable.ic_account_add) { Item(title = R.string.account_add, icon = R.drawable.ic_account_add) {
@ -220,10 +359,6 @@ class SideMenuAdapter(
) )
}, },
Item(icon = R.drawable.ic_info, title = 1) {
App1.openCustomTab(this, "https://github.com/tateisu/SubwayTooter/releases")
},
Item(icon = R.drawable.ic_info, title = R.string.oss_license) { Item(icon = R.drawable.ic_info, title = R.string.oss_license) {
startActivity(Intent(this, ActOSSLicense::class.java)) startActivity(Intent(this, ActOSSLicense::class.java))
}, },
@ -233,14 +368,7 @@ class SideMenuAdapter(
} }
) )
private val iconColor = getAttributeColor(activity, R.attr.colorTimeSmall) private val iconColor = getAttributeColor(actMain, R.attr.colorTimeSmall)
private val currentVersion = try {
val pInfo = activity.packageManager.getPackageInfo(activity.packageName, 0)
pInfo.versionName
} catch(ex : PackageManager.NameNotFoundException) {
"??"
}
override fun getCount() : Int = list.size override fun getCount() : Int = list.size
override fun getItem(position : Int) : Any = list[position] override fun getItem(position : Int) : Any = list[position]
@ -254,7 +382,7 @@ class SideMenuAdapter(
parent : ViewGroup?, parent : ViewGroup?,
resId : Int resId : Int
) : T = ) : T =
(view ?: activity.layoutInflater.inflate(resId, parent, false)) (view ?: actMain.layoutInflater.inflate(resId, parent, false))
as? T ?: error("invalid view type! ${T::class.java.simpleName}") as? T ?: error("invalid view type! ${T::class.java.simpleName}")
override fun getView(position : Int, view : View?, parent : ViewGroup?) : View = override fun getView(position : Int, view : View?, parent : ViewGroup?) : View =
@ -263,97 +391,67 @@ class SideMenuAdapter(
ItemType.IT_DIVIDER -> ItemType.IT_DIVIDER ->
viewOrInflate(view, parent, R.layout.lv_sidemenu_separator) viewOrInflate(view, parent, R.layout.lv_sidemenu_separator)
ItemType.IT_GROUP_HEADER -> ItemType.IT_GROUP_HEADER ->
viewOrInflate<TextView>(view, parent, R.layout.lv_sidemenu_group) viewOrInflate<TextView>(view, parent, R.layout.lv_sidemenu_group).apply {
.apply { text = actMain.getString(title)
text = activity.getString(title) }
}
ItemType.IT_NORMAL -> ItemType.IT_NORMAL ->
viewOrInflate<TextView>(view, parent, R.layout.lv_sidemenu_item)
.apply {
isAllCaps = false
text = activity.getString(title)
val drawable = createColoredDrawable(activity, icon, iconColor, 1f)
setCompoundDrawablesRelativeWithIntrinsicBounds(
drawable,
null,
null,
null
)
setOnClickListener {
action(activity)
drawer.closeDrawer(GravityCompat.START)
}
}
ItemType.IT_VERSION ->
viewOrInflate<TextView>(view, parent, R.layout.lv_sidemenu_item).apply { viewOrInflate<TextView>(view, parent, R.layout.lv_sidemenu_item).apply {
text = SpannableStringBuilder().apply {
val lastVersion = Pref.spVersionNameWhenReleaseNoteTap(activity.pref)
if(lastVersion.isNotEmpty() && lastVersion != currentVersion) {
append(
activity.getString(
R.string.release_notes_updated,
lastVersion,
currentVersion
)
)
setSpan(
ForegroundColorSpan(
getAttributeColor(
activity,
R.attr.colorRegexFilterError
)
),
0, length,
Spannable.SPAN_EXCLUSIVE_EXCLUSIVE
)
} else {
append(
activity.getString(
R.string.release_notes_latest,
currentVersion
)
)
}
}
isAllCaps = false isAllCaps = false
val drawable = createColoredDrawable(activity, icon, iconColor, 1f) text = actMain.getString(title)
val drawable = createColoredDrawable(actMain, icon, iconColor, 1f)
setCompoundDrawablesRelativeWithIntrinsicBounds( setCompoundDrawablesRelativeWithIntrinsicBounds(
drawable, drawable,
null, null,
null, null,
null null
) )
setOnClickListener { setOnClickListener {
activity.pref.edit() action(actMain)
.put(Pref.spVersionNameWhenReleaseNoteTap, currentVersion)
.apply()
notifyDataSetChanged()
action(activity)
drawer.closeDrawer(GravityCompat.START) drawer.closeDrawer(GravityCompat.START)
} }
} }
ItemType.IT_VERSION ->
viewOrInflate<TextView>(view, parent, R.layout.lv_sidemenu_item).apply {
lastVersionView = WeakReference(this)
movementMethod = LinkMovementMethod.getInstance();
textSize = 18f
isAllCaps = false
background= null
// val drawable = createColoredDrawable(actMain, icon, iconColor, 1f)
// setCompoundDrawablesRelativeWithIntrinsicBounds(
// drawable,
// null,
// null,
// null
// )
text = getVersionRow()
}
} }
} }
init { init {
ListView(activity).apply { checkVersion(actMain.applicationContext, handler)
ListView(actMain).apply {
adapter = this@SideMenuAdapter adapter = this@SideMenuAdapter
layoutParams = FrameLayout.LayoutParams( layoutParams = FrameLayout.LayoutParams(
FrameLayout.LayoutParams.MATCH_PARENT, FrameLayout.LayoutParams.MATCH_PARENT,
FrameLayout.LayoutParams.MATCH_PARENT FrameLayout.LayoutParams.MATCH_PARENT
) )
backgroundColor = getAttributeColor(activity, R.attr.colorWindowBackground) backgroundColor = getAttributeColor(actMain, R.attr.colorWindowBackground)
selector = StateListDrawable() selector = StateListDrawable()
divider = null divider = null
dividerHeight = 0 dividerHeight = 0
val pad_tb = (activity.density * 12f + 0.5f).toInt() val pad_tb = (actMain.density * 12f + 0.5f).toInt()
setPadding(0, pad_tb, 0, pad_tb) setPadding(0, pad_tb, 0, pad_tb)
clipToPadding = false clipToPadding = false
scrollBarStyle = ListView.SCROLLBARS_OUTSIDE_OVERLAY scrollBarStyle = ListView.SCROLLBARS_OUTSIDE_OVERLAY
navigationView.addView(this) navigationView.addView(this)
} }
} }
} }

View File

@ -1032,4 +1032,9 @@
<string name="personal_notes_of">%1$sに関する覚え書き</string> <string name="personal_notes_of">%1$sに関する覚え書き</string>
<string name="custom_thumbnail">カスタムサムネイル</string> <string name="custom_thumbnail">カスタムサムネイル</string>
<string name="close_emoji_picker_when_selected">絵文字を選択したら絵文字ピッカーを閉じる</string> <string name="close_emoji_picker_when_selected">絵文字を選択したら絵文字ピッカーを閉じる</string>
<string name="new_version_available">新バージョンがあります %1$s</string>
<string name="app_name_with_version">%1$s %2$s</string>
<string name="release_note_with_assets">更新履歴 (AssetsセクションにAPKファイルがあります)</string>
<string name="release_note">更新履歴</string>
<string name="check_beta_release">ベータ版を確認する</string>
</resources> </resources>

View File

@ -1039,4 +1039,9 @@
<string name="personal_notes_of">Personal notes of %1$s</string> <string name="personal_notes_of">Personal notes of %1$s</string>
<string name="custom_thumbnail">Custom thumbnail</string> <string name="custom_thumbnail">Custom thumbnail</string>
<string name="close_emoji_picker_when_selected">Close emoji picker after selecting emoji</string> <string name="close_emoji_picker_when_selected">Close emoji picker after selecting emoji</string>
<string name="new_version_available">New version available! %1$s</string>
<string name="app_name_with_version">%1$s %2$s</string>
<string name="release_note_with_assets">Release note (Please find the APK file in assets section.)</string>
<string name="release_note">Release note</string>
<string name="check_beta_release">Check beta release</string>
</resources> </resources>