2021-06-28 09:09:00 +02:00
|
|
|
package jp.juggler.subwaytooter.actmain
|
2019-08-23 14:50:04 +02:00
|
|
|
|
2020-08-28 02:25:48 +02:00
|
|
|
import android.content.Context
|
2019-08-23 14:50:04 +02:00
|
|
|
import android.content.Intent
|
|
|
|
import android.graphics.drawable.StateListDrawable
|
2022-07-16 23:44:58 +02:00
|
|
|
import android.os.Build
|
2020-08-28 02:25:48 +02:00
|
|
|
import android.os.Handler
|
2019-11-14 02:30:39 +01:00
|
|
|
import android.text.Spannable
|
|
|
|
import android.text.SpannableStringBuilder
|
2020-08-28 02:25:48 +02:00
|
|
|
import android.text.TextPaint
|
|
|
|
import android.text.method.LinkMovementMethod
|
|
|
|
import android.text.style.ClickableSpan
|
2019-11-14 02:30:39 +01:00
|
|
|
import android.text.style.ForegroundColorSpan
|
2022-07-16 23:44:58 +02:00
|
|
|
import android.text.style.UnderlineSpan
|
2019-08-23 14:50:04 +02:00
|
|
|
import android.view.View
|
|
|
|
import android.view.ViewGroup
|
|
|
|
import android.widget.BaseAdapter
|
|
|
|
import android.widget.FrameLayout
|
|
|
|
import android.widget.ListView
|
|
|
|
import android.widget.TextView
|
|
|
|
import androidx.core.view.GravityCompat
|
|
|
|
import androidx.drawerlayout.widget.DrawerLayout
|
2021-06-28 09:09:00 +02:00
|
|
|
import jp.juggler.subwaytooter.*
|
2021-05-27 04:15:59 +02:00
|
|
|
import jp.juggler.subwaytooter.action.*
|
2020-08-28 02:25:48 +02:00
|
|
|
import jp.juggler.subwaytooter.api.entity.TootStatus
|
2021-06-28 09:09:00 +02:00
|
|
|
import jp.juggler.subwaytooter.column.ColumnType
|
2021-05-27 04:15:59 +02:00
|
|
|
import jp.juggler.subwaytooter.dialog.pickAccount
|
2021-11-06 04:00:29 +01:00
|
|
|
import jp.juggler.subwaytooter.pref.PrefB
|
2023-02-08 10:55:49 +01:00
|
|
|
import jp.juggler.subwaytooter.pref.PrefDevice.Companion.PUSH_DISTRIBUTOR_NONE
|
2021-11-14 14:23:17 +01:00
|
|
|
import jp.juggler.subwaytooter.pref.PrefS
|
2023-02-08 10:55:49 +01:00
|
|
|
import jp.juggler.subwaytooter.pref.prefDevice
|
|
|
|
import jp.juggler.subwaytooter.push.fcmHandler
|
2019-08-23 14:50:04 +02:00
|
|
|
import jp.juggler.subwaytooter.table.SavedAccount
|
2023-02-04 21:52:26 +01:00
|
|
|
import jp.juggler.subwaytooter.table.accountListCanSeeMyReactions
|
2020-08-28 02:25:48 +02:00
|
|
|
import jp.juggler.subwaytooter.util.VersionString
|
2020-09-29 19:44:56 +02:00
|
|
|
import jp.juggler.subwaytooter.util.openBrowser
|
2023-01-13 13:22:25 +01:00
|
|
|
import jp.juggler.util.coroutine.AppDispatchers
|
2023-02-04 21:52:26 +01:00
|
|
|
import jp.juggler.util.coroutine.launchAndShowError
|
2023-01-13 13:22:25 +01:00
|
|
|
import jp.juggler.util.coroutine.launchIO
|
|
|
|
import jp.juggler.util.data.JsonObject
|
|
|
|
import jp.juggler.util.data.decodeJsonObject
|
|
|
|
import jp.juggler.util.data.decodeUTF8
|
|
|
|
import jp.juggler.util.data.notEmpty
|
|
|
|
import jp.juggler.util.getPackageInfoCompat
|
|
|
|
import jp.juggler.util.log.LogCategory
|
|
|
|
import jp.juggler.util.log.showToast
|
|
|
|
import jp.juggler.util.ui.activity
|
|
|
|
import jp.juggler.util.ui.attrColor
|
|
|
|
import jp.juggler.util.ui.createColoredDrawable
|
2022-07-16 23:44:58 +02:00
|
|
|
import kotlinx.coroutines.withContext
|
2019-08-23 14:50:04 +02:00
|
|
|
import org.jetbrains.anko.backgroundColor
|
2020-08-28 02:25:48 +02:00
|
|
|
import java.lang.ref.WeakReference
|
2021-11-14 14:23:17 +01:00
|
|
|
import java.util.*
|
|
|
|
import java.util.concurrent.TimeUnit
|
|
|
|
import kotlin.math.abs
|
2019-08-23 14:50:04 +02:00
|
|
|
|
|
|
|
class SideMenuAdapter(
|
2021-05-22 00:03:16 +02:00
|
|
|
private val actMain: ActMain,
|
|
|
|
val handler: Handler,
|
|
|
|
navigationView: ViewGroup,
|
2022-03-11 00:11:49 +01:00
|
|
|
private val drawer: DrawerLayout,
|
2019-08-23 14:50:04 +02:00
|
|
|
) : BaseAdapter() {
|
2021-05-22 00:03:16 +02:00
|
|
|
|
|
|
|
companion object {
|
2022-03-11 00:11:49 +01:00
|
|
|
private val log = LogCategory("SideMenuAdapter")
|
2021-05-22 00:03:16 +02:00
|
|
|
|
2022-07-16 23:44:58 +02:00
|
|
|
private const val urlAppVersion =
|
|
|
|
"https://mastodon-msg.juggler.jp/appVersion/appVersion.json"
|
|
|
|
private const val urlGithubReleases =
|
|
|
|
"https://github.com/tateisu/SubwayTooter/releases"
|
|
|
|
private const val urlOlderDevices =
|
|
|
|
"https://github.com/tateisu/SubwayTooter/discussions/192"
|
|
|
|
|
2021-05-22 00:03:16 +02:00
|
|
|
private val itemTypeCount = ItemType.values().size
|
|
|
|
|
|
|
|
private var lastVersionView: WeakReference<TextView>? = null
|
|
|
|
|
2022-07-16 23:44:58 +02:00
|
|
|
private var versionText = SpannableStringBuilder("")
|
2021-05-22 00:03:16 +02:00
|
|
|
|
|
|
|
private var releaseInfo: JsonObject? = null
|
|
|
|
|
2022-07-16 23:44:58 +02:00
|
|
|
private fun clickableSpan(
|
|
|
|
url: String,
|
|
|
|
showUnderline: Boolean = false,
|
|
|
|
) = object : ClickableSpan() {
|
|
|
|
override fun onClick(widget: View) {
|
|
|
|
widget.activity?.openBrowser(url)
|
|
|
|
}
|
2021-05-22 00:03:16 +02:00
|
|
|
|
2022-07-16 23:44:58 +02:00
|
|
|
override fun updateDrawState(ds: TextPaint) {
|
|
|
|
super.updateDrawState(ds)
|
|
|
|
ds.isUnderlineText = showUnderline
|
2021-05-22 00:03:16 +02:00
|
|
|
}
|
2022-07-16 23:44:58 +02:00
|
|
|
}
|
2021-05-22 00:03:16 +02:00
|
|
|
|
2022-07-16 23:44:58 +02:00
|
|
|
private fun SpannableStringBuilder.appendSpanLine(
|
|
|
|
text: String,
|
|
|
|
vararg spans: Any,
|
|
|
|
) = this.apply {
|
|
|
|
if (isNotEmpty()) {
|
|
|
|
append("\n")
|
|
|
|
}
|
|
|
|
val start = length
|
|
|
|
append(text)
|
|
|
|
for (span in spans) {
|
|
|
|
setSpan(span, start, length, Spannable.SPAN_EXCLUSIVE_EXCLUSIVE)
|
|
|
|
}
|
|
|
|
}
|
2021-05-22 00:03:16 +02:00
|
|
|
|
2022-07-16 23:44:58 +02:00
|
|
|
// バージョン情報と更新履歴と新リリース告知の文字列を組み立てる
|
|
|
|
// メインスレッドでもそれ以外でも動作すること
|
|
|
|
private fun Context.createVersionRow() = SpannableStringBuilder().apply {
|
|
|
|
val currentVersion = try {
|
2022-09-10 23:09:26 +02:00
|
|
|
packageManager.getPackageInfoCompat(packageName)!!.versionName
|
|
|
|
} catch (ignored: Throwable) {
|
2022-07-16 23:44:58 +02:00
|
|
|
"??"
|
|
|
|
}
|
2021-05-22 00:03:16 +02:00
|
|
|
|
2022-07-16 23:44:58 +02:00
|
|
|
append(
|
|
|
|
getString(
|
|
|
|
R.string.app_name_with_version,
|
|
|
|
getString(R.string.app_name),
|
|
|
|
currentVersion
|
|
|
|
)
|
|
|
|
)
|
|
|
|
val newRelease = releaseInfo?.jsonObject(
|
2023-02-04 21:52:26 +01:00
|
|
|
if (PrefB.bpCheckBetaVersion.value) "beta" else "stable"
|
2022-07-16 23:44:58 +02:00
|
|
|
)
|
2021-05-22 00:03:16 +02:00
|
|
|
|
2022-07-16 23:44:58 +02:00
|
|
|
// 使用中のアプリバージョンより新しいリリースがある?
|
|
|
|
val newVersion =
|
|
|
|
(newRelease?.string("name")?.notEmpty() ?: newRelease?.string("tag_name"))
|
2022-07-17 00:06:34 +02:00
|
|
|
?.replace("""(v(ersion)?)\s*""".toRegex(RegexOption.IGNORE_CASE), "")
|
2022-07-16 23:44:58 +02:00
|
|
|
?.trim()
|
|
|
|
?.notEmpty()
|
2022-07-17 00:06:34 +02:00
|
|
|
?.takeIf {
|
|
|
|
log.i("newVersion=$it, currentVersion=$currentVersion")
|
|
|
|
VersionString(it) > VersionString(currentVersion)
|
|
|
|
}
|
2022-07-16 23:44:58 +02:00
|
|
|
|
|
|
|
val releaseMinSdkVersion = newRelease?.int("minSdkVersion")
|
|
|
|
?: Build.VERSION.SDK_INT
|
|
|
|
val releaseMinSdkVersionScheduled = newRelease?.int("minSdkVersionScheduled")
|
|
|
|
?: Build.VERSION.SDK_INT
|
|
|
|
|
|
|
|
when {
|
|
|
|
// 新しいバージョンがある
|
|
|
|
// それはこの端末にインストール可能である
|
|
|
|
newVersion != null && Build.VERSION.SDK_INT >= releaseMinSdkVersion -> {
|
|
|
|
appendSpanLine(
|
|
|
|
getString(
|
2021-05-27 04:15:59 +02:00
|
|
|
R.string.new_version_available,
|
|
|
|
newVersion
|
2022-07-16 23:44:58 +02:00
|
|
|
),
|
2021-05-27 04:15:59 +02:00
|
|
|
ForegroundColorSpan(
|
2022-07-16 23:44:58 +02:00
|
|
|
attrColor(R.attr.colorRegexFilterError)
|
2021-05-27 04:15:59 +02:00
|
|
|
),
|
2021-05-22 00:03:16 +02:00
|
|
|
)
|
2022-07-16 23:44:58 +02:00
|
|
|
newRelease?.string("html_url")?.let {
|
|
|
|
appendSpanLine(
|
|
|
|
getString(R.string.release_note_with_assets),
|
|
|
|
clickableSpan(it)
|
2021-05-22 00:03:16 +02:00
|
|
|
)
|
|
|
|
}
|
|
|
|
}
|
2021-05-27 04:15:59 +02:00
|
|
|
|
2022-07-16 23:44:58 +02:00
|
|
|
// 通常時は更新履歴へのリンク
|
|
|
|
else -> appendSpanLine(
|
|
|
|
getString(R.string.release_note),
|
|
|
|
UnderlineSpan(),
|
|
|
|
clickableSpan(urlGithubReleases),
|
|
|
|
)
|
2021-05-27 04:15:59 +02:00
|
|
|
}
|
|
|
|
|
2022-07-16 23:44:58 +02:00
|
|
|
// 端末のOSバージョンがサポートから外れる予定なら、サイドメニューにリンクを追加する
|
|
|
|
if (Build.VERSION.SDK_INT < releaseMinSdkVersionScheduled) {
|
|
|
|
appendSpanLine(
|
|
|
|
getString(R.string.old_devices_warning),
|
|
|
|
clickableSpan(urlOlderDevices, showUnderline = true),
|
2021-05-27 04:15:59 +02:00
|
|
|
)
|
2021-05-22 00:03:16 +02:00
|
|
|
}
|
2022-07-16 23:44:58 +02:00
|
|
|
}
|
2021-05-22 00:03:16 +02:00
|
|
|
|
2022-07-16 23:44:58 +02:00
|
|
|
// メインスレッドから呼ばれる
|
|
|
|
private fun Context.checkVersion() {
|
|
|
|
// サイドメニューから参照されるバージョン文字列を初期化する
|
|
|
|
// この時点ではreleaseInfoはnullかもしれない
|
|
|
|
versionText = createVersionRow()
|
|
|
|
|
|
|
|
// releaseInfoが既にあり、更新時刻が十分に新しいなら情報を取得し直す必要はない
|
|
|
|
releaseInfo?.string("updated_at")
|
|
|
|
?.let { TootStatus.parseTime(it) }
|
|
|
|
?.takeIf { it >= System.currentTimeMillis() - 86400000L }
|
|
|
|
?.let { return }
|
|
|
|
|
|
|
|
// リリース情報を取得し直す
|
|
|
|
launchIO {
|
|
|
|
try {
|
|
|
|
val json = App1.getHttpCached(urlAppVersion)
|
|
|
|
?.decodeUTF8()
|
|
|
|
?.decodeJsonObject()
|
|
|
|
?: error("missing appVersion json")
|
|
|
|
releaseInfo = json
|
|
|
|
versionText = createVersionRow()
|
2023-01-17 13:42:47 +01:00
|
|
|
withContext(AppDispatchers.MainImmediate) {
|
2022-07-16 23:44:58 +02:00
|
|
|
lastVersionView?.get()?.text = versionText
|
2021-05-22 00:03:16 +02:00
|
|
|
}
|
2022-07-16 23:44:58 +02:00
|
|
|
} catch (ex: Throwable) {
|
|
|
|
log.e(ex, "checkVersion failed")
|
2021-05-22 00:03:16 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
private enum class ItemType(val id: Int) {
|
|
|
|
IT_NORMAL(0),
|
|
|
|
IT_GROUP_HEADER(1),
|
|
|
|
IT_DIVIDER(2),
|
2021-11-14 14:23:17 +01:00
|
|
|
IT_VERSION(3),
|
2023-02-05 19:08:48 +01:00
|
|
|
IT_TIMEZONE(4),
|
|
|
|
IT_NOTIFICATION_PERMISSION(5),
|
2021-05-22 00:03:16 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
private class Item(
|
2021-11-14 14:23:17 +01:00
|
|
|
// 項目の文字列リソース or 0: divider, 1: バージョン表記, 2: タイムゾーン
|
2021-05-22 00:03:16 +02:00
|
|
|
val title: Int = 0,
|
|
|
|
val icon: Int = 0,
|
2022-03-11 00:11:49 +01:00
|
|
|
val action: ActMain.() -> Unit = {},
|
2021-05-22 00:03:16 +02:00
|
|
|
) {
|
|
|
|
|
|
|
|
val itemType: ItemType
|
|
|
|
get() = when {
|
|
|
|
title == 0 -> ItemType.IT_DIVIDER
|
|
|
|
title == 1 -> ItemType.IT_VERSION
|
2021-11-14 14:23:17 +01:00
|
|
|
title == 2 -> ItemType.IT_TIMEZONE
|
2023-02-05 19:08:48 +01:00
|
|
|
title == 3 -> ItemType.IT_NOTIFICATION_PERMISSION
|
2021-05-22 00:03:16 +02:00
|
|
|
icon == 0 -> ItemType.IT_GROUP_HEADER
|
|
|
|
else -> ItemType.IT_NORMAL
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
no title => section divider
|
|
|
|
else no icon => section header with title
|
|
|
|
else => menu item with icon and title
|
|
|
|
*/
|
2023-02-05 19:08:48 +01:00
|
|
|
private val originalList = listOf(
|
2021-05-22 00:03:16 +02:00
|
|
|
|
2023-01-07 03:22:00 +01:00
|
|
|
Item(icon = R.drawable.ic_info_outline, title = 1),
|
|
|
|
Item(icon = R.drawable.ic_info_outline, title = 2),
|
2023-02-05 19:08:48 +01:00
|
|
|
Item(icon = R.drawable.ic_info_outline, title = 3),
|
2021-05-22 00:03:16 +02:00
|
|
|
|
|
|
|
Item(),
|
|
|
|
Item(title = R.string.account),
|
|
|
|
|
2023-01-07 03:22:00 +01:00
|
|
|
Item(title = R.string.account_add, icon = R.drawable.ic_person_add) {
|
2021-05-27 04:15:59 +02:00
|
|
|
accountAdd()
|
2021-05-22 00:03:16 +02:00
|
|
|
},
|
|
|
|
|
|
|
|
Item(icon = R.drawable.ic_settings, title = R.string.account_setting) {
|
2021-05-27 04:15:59 +02:00
|
|
|
accountOpenSetting()
|
2021-05-22 00:03:16 +02:00
|
|
|
},
|
|
|
|
|
2023-02-05 16:44:28 +01:00
|
|
|
Item(icon = R.drawable.outline_delivery_dining_24, title = R.string.push_message_history) {
|
|
|
|
startActivity(Intent(this, ActPushMessageList::class.java))
|
|
|
|
},
|
|
|
|
|
2021-05-22 00:03:16 +02:00
|
|
|
Item(),
|
|
|
|
Item(title = R.string.column),
|
|
|
|
|
|
|
|
Item(icon = R.drawable.ic_list_numbered, title = R.string.column_list) {
|
2021-05-27 04:15:59 +02:00
|
|
|
openColumnList()
|
2021-05-22 00:03:16 +02:00
|
|
|
},
|
|
|
|
|
|
|
|
Item(icon = R.drawable.ic_close, title = R.string.close_all_columns) {
|
|
|
|
closeColumnAll()
|
|
|
|
},
|
|
|
|
|
2021-11-16 14:05:08 +01:00
|
|
|
Item(icon = R.drawable.ic_paste, title = R.string.open_column_from_url) {
|
|
|
|
openColumnFromUrl()
|
|
|
|
},
|
|
|
|
|
2021-05-22 00:03:16 +02:00
|
|
|
Item(icon = R.drawable.ic_home, title = R.string.home) {
|
2021-05-27 04:15:59 +02:00
|
|
|
timeline(defaultInsertPosition, ColumnType.HOME)
|
2021-05-22 00:03:16 +02:00
|
|
|
},
|
|
|
|
|
|
|
|
Item(icon = R.drawable.ic_announcement, title = R.string.notifications) {
|
2021-05-27 04:15:59 +02:00
|
|
|
timeline(defaultInsertPosition, ColumnType.NOTIFICATIONS)
|
2021-05-22 00:03:16 +02:00
|
|
|
},
|
|
|
|
|
|
|
|
Item(icon = R.drawable.ic_mail, title = R.string.direct_messages) {
|
2021-05-27 04:15:59 +02:00
|
|
|
timeline(defaultInsertPosition, ColumnType.DIRECT_MESSAGES)
|
2021-05-22 00:03:16 +02:00
|
|
|
},
|
|
|
|
|
|
|
|
Item(icon = R.drawable.ic_share, title = R.string.misskey_hybrid_timeline_long) {
|
2021-05-27 04:15:59 +02:00
|
|
|
timeline(defaultInsertPosition, ColumnType.MISSKEY_HYBRID)
|
2021-05-22 00:03:16 +02:00
|
|
|
},
|
|
|
|
|
|
|
|
Item(icon = R.drawable.ic_run, title = R.string.local_timeline) {
|
2021-05-27 04:15:59 +02:00
|
|
|
timeline(defaultInsertPosition, ColumnType.LOCAL)
|
2021-05-22 00:03:16 +02:00
|
|
|
},
|
|
|
|
|
|
|
|
Item(icon = R.drawable.ic_bike, title = R.string.federate_timeline) {
|
2021-05-27 04:15:59 +02:00
|
|
|
timeline(defaultInsertPosition, ColumnType.FEDERATE)
|
2021-05-22 00:03:16 +02:00
|
|
|
},
|
|
|
|
|
|
|
|
Item(icon = R.drawable.ic_list_list, title = R.string.lists) {
|
2021-05-27 04:15:59 +02:00
|
|
|
timeline(defaultInsertPosition, ColumnType.LIST_LIST)
|
2021-05-22 00:03:16 +02:00
|
|
|
},
|
|
|
|
|
|
|
|
Item(icon = R.drawable.ic_satellite, title = R.string.antenna_list_misskey) {
|
2021-05-27 04:15:59 +02:00
|
|
|
timeline(defaultInsertPosition, ColumnType.MISSKEY_ANTENNA_LIST)
|
2021-05-22 00:03:16 +02:00
|
|
|
},
|
|
|
|
|
2022-07-20 06:27:19 +02:00
|
|
|
Item(icon = R.drawable.ic_hashtag, title = R.string.followed_tags) {
|
|
|
|
timeline(defaultInsertPosition, ColumnType.FOLLOWED_HASHTAGS)
|
|
|
|
},
|
|
|
|
|
2021-05-22 00:03:16 +02:00
|
|
|
Item(icon = R.drawable.ic_search, title = R.string.search) {
|
2021-05-27 04:15:59 +02:00
|
|
|
timeline(defaultInsertPosition, ColumnType.SEARCH, args = arrayOf("", false))
|
2021-05-22 00:03:16 +02:00
|
|
|
},
|
|
|
|
|
2022-03-16 06:08:54 +01:00
|
|
|
Item(icon = R.drawable.ic_trend, title = R.string.trend_tag) {
|
2021-05-27 04:15:59 +02:00
|
|
|
timeline(defaultInsertPosition, ColumnType.TREND_TAG)
|
2021-05-22 00:03:16 +02:00
|
|
|
},
|
2022-03-16 06:08:54 +01:00
|
|
|
Item(icon = R.drawable.ic_trend, title = R.string.trend_link) {
|
|
|
|
timeline(defaultInsertPosition, ColumnType.TREND_LINK)
|
|
|
|
},
|
|
|
|
Item(icon = R.drawable.ic_trend, title = R.string.trend_post) {
|
|
|
|
timeline(defaultInsertPosition, ColumnType.TREND_POST)
|
|
|
|
},
|
2023-01-07 03:22:00 +01:00
|
|
|
Item(icon = R.drawable.ic_star_outline, title = R.string.favourites) {
|
2021-05-27 04:15:59 +02:00
|
|
|
timeline(defaultInsertPosition, ColumnType.FAVOURITES)
|
2021-05-22 00:03:16 +02:00
|
|
|
},
|
|
|
|
|
|
|
|
Item(icon = R.drawable.ic_bookmark, title = R.string.bookmarks) {
|
2021-05-27 04:15:59 +02:00
|
|
|
timeline(defaultInsertPosition, ColumnType.BOOKMARKS)
|
2021-05-22 00:03:16 +02:00
|
|
|
},
|
2021-05-22 14:02:55 +02:00
|
|
|
Item(icon = R.drawable.ic_face, title = R.string.reactioned_posts) {
|
2023-02-04 21:52:26 +01:00
|
|
|
launchAndShowError {
|
2021-05-27 04:15:59 +02:00
|
|
|
accountListCanSeeMyReactions()?.let { list ->
|
|
|
|
if (list.isEmpty()) {
|
|
|
|
showToast(false, R.string.not_available_for_current_accounts)
|
|
|
|
} else {
|
|
|
|
val columnType = ColumnType.REACTIONS
|
|
|
|
pickAccount(
|
|
|
|
accountListArg = list.toMutableList(),
|
|
|
|
bAuto = true,
|
|
|
|
message = getString(
|
|
|
|
R.string.account_picker_add_timeline_of,
|
|
|
|
columnType.name1(applicationContext)
|
|
|
|
)
|
|
|
|
)?.let { addColumn(defaultInsertPosition, it, columnType) }
|
|
|
|
}
|
2021-05-22 00:03:16 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
},
|
|
|
|
|
|
|
|
Item(icon = R.drawable.ic_account_box, title = R.string.profile) {
|
2021-05-27 04:15:59 +02:00
|
|
|
timeline(defaultInsertPosition, ColumnType.PROFILE)
|
2021-05-22 00:03:16 +02:00
|
|
|
},
|
|
|
|
|
|
|
|
Item(icon = R.drawable.ic_follow_wait, title = R.string.follow_requests) {
|
2021-05-27 04:15:59 +02:00
|
|
|
timeline(defaultInsertPosition, ColumnType.FOLLOW_REQUESTS)
|
2021-05-22 00:03:16 +02:00
|
|
|
},
|
|
|
|
|
2023-01-07 03:22:00 +01:00
|
|
|
Item(icon = R.drawable.ic_person_add, title = R.string.follow_suggestion) {
|
2021-05-27 04:15:59 +02:00
|
|
|
timeline(defaultInsertPosition, ColumnType.FOLLOW_SUGGESTION)
|
2021-05-22 00:03:16 +02:00
|
|
|
},
|
|
|
|
|
2023-01-07 03:22:00 +01:00
|
|
|
Item(icon = R.drawable.ic_person_add, title = R.string.endorse_set) {
|
2021-05-27 04:15:59 +02:00
|
|
|
timeline(defaultInsertPosition, ColumnType.ENDORSEMENT)
|
2021-05-22 00:03:16 +02:00
|
|
|
},
|
|
|
|
|
2023-01-07 03:22:00 +01:00
|
|
|
Item(icon = R.drawable.ic_person_add, title = R.string.profile_directory) {
|
2021-05-27 04:15:59 +02:00
|
|
|
serverProfileDirectoryFromSideMenu()
|
2021-05-22 00:03:16 +02:00
|
|
|
},
|
|
|
|
|
|
|
|
Item(icon = R.drawable.ic_volume_off, title = R.string.muted_users) {
|
2021-05-27 04:15:59 +02:00
|
|
|
timeline(defaultInsertPosition, ColumnType.MUTES)
|
2021-05-22 00:03:16 +02:00
|
|
|
},
|
|
|
|
|
|
|
|
Item(icon = R.drawable.ic_block, title = R.string.blocked_users) {
|
2021-05-27 04:15:59 +02:00
|
|
|
timeline(defaultInsertPosition, ColumnType.BLOCKS)
|
2021-05-22 00:03:16 +02:00
|
|
|
},
|
|
|
|
|
|
|
|
Item(icon = R.drawable.ic_volume_off, title = R.string.keyword_filters) {
|
2021-05-27 04:15:59 +02:00
|
|
|
timeline(defaultInsertPosition, ColumnType.KEYWORD_FILTER)
|
2021-05-22 00:03:16 +02:00
|
|
|
},
|
|
|
|
|
|
|
|
Item(icon = R.drawable.ic_cloud_off, title = R.string.blocked_domains) {
|
2021-05-27 04:15:59 +02:00
|
|
|
timeline(defaultInsertPosition, ColumnType.DOMAIN_BLOCKS)
|
2021-05-22 00:03:16 +02:00
|
|
|
},
|
|
|
|
|
|
|
|
Item(icon = R.drawable.ic_timer, title = R.string.scheduled_status_list) {
|
2021-05-27 04:15:59 +02:00
|
|
|
timeline(defaultInsertPosition, ColumnType.SCHEDULED_STATUS)
|
2021-05-22 00:03:16 +02:00
|
|
|
},
|
|
|
|
|
|
|
|
Item(),
|
|
|
|
Item(title = R.string.toot_search),
|
|
|
|
|
2022-12-27 07:16:02 +01:00
|
|
|
// Item(icon = R.drawable.ic_search, title = R.string.mastodon_search_portal) {
|
|
|
|
// addColumn(defaultInsertPosition, SavedAccount.na, ColumnType.SEARCH_MSP, "")
|
|
|
|
// },
|
2022-12-26 16:04:32 +01:00
|
|
|
// Item(icon = R.drawable.ic_search, title = R.string.tootsearch) {
|
|
|
|
// addColumn(defaultInsertPosition, SavedAccount.na, ColumnType.SEARCH_TS, "")
|
|
|
|
// },
|
2023-01-05 07:17:09 +01:00
|
|
|
|
2021-05-22 00:03:16 +02:00
|
|
|
Item(icon = R.drawable.ic_search, title = R.string.notestock) {
|
2023-02-08 10:55:49 +01:00
|
|
|
addColumn(
|
|
|
|
defaultInsertPosition,
|
|
|
|
SavedAccount.na,
|
|
|
|
ColumnType.SEARCH_NOTESTOCK,
|
|
|
|
params = arrayOf("")
|
|
|
|
)
|
2021-05-22 00:03:16 +02:00
|
|
|
},
|
|
|
|
|
|
|
|
Item(),
|
|
|
|
Item(title = R.string.setting),
|
|
|
|
|
|
|
|
Item(icon = R.drawable.ic_settings, title = R.string.app_setting) {
|
|
|
|
arAppSetting.launch(
|
|
|
|
ActAppSetting.createIntent(this)
|
|
|
|
)
|
|
|
|
},
|
|
|
|
|
|
|
|
Item(icon = R.drawable.ic_settings, title = R.string.highlight_word) {
|
|
|
|
startActivity(Intent(this, ActHighlightWordList::class.java))
|
|
|
|
},
|
|
|
|
|
|
|
|
Item(icon = R.drawable.ic_volume_off, title = R.string.muted_app) {
|
|
|
|
startActivity(Intent(this, ActMutedApp::class.java))
|
|
|
|
},
|
|
|
|
|
|
|
|
Item(icon = R.drawable.ic_volume_off, title = R.string.muted_word) {
|
|
|
|
startActivity(Intent(this, ActMutedWord::class.java))
|
|
|
|
},
|
|
|
|
|
|
|
|
Item(icon = R.drawable.ic_volume_off, title = R.string.fav_muted_user) {
|
|
|
|
startActivity(Intent(this, ActFavMute::class.java))
|
|
|
|
},
|
|
|
|
|
|
|
|
Item(
|
|
|
|
icon = R.drawable.ic_volume_off,
|
|
|
|
title = R.string.muted_users_from_pseudo_account
|
|
|
|
) {
|
|
|
|
startActivity(Intent(this, ActMutedPseudoAccount::class.java))
|
|
|
|
},
|
|
|
|
|
2023-01-07 03:22:00 +01:00
|
|
|
Item(icon = R.drawable.ic_info_outline, title = R.string.app_about) {
|
2021-05-22 00:03:16 +02:00
|
|
|
|
|
|
|
arAbout.launch(
|
|
|
|
Intent(this, ActAbout::class.java)
|
|
|
|
)
|
|
|
|
},
|
|
|
|
|
2023-01-07 03:22:00 +01:00
|
|
|
Item(icon = R.drawable.ic_info_outline, title = R.string.oss_license) {
|
2021-05-22 00:03:16 +02:00
|
|
|
startActivity(Intent(this, ActOSSLicense::class.java))
|
|
|
|
},
|
|
|
|
|
|
|
|
Item(icon = R.drawable.ic_hot_tub, title = R.string.app_exit) {
|
|
|
|
finish()
|
|
|
|
}
|
|
|
|
)
|
|
|
|
|
2023-02-05 19:08:48 +01:00
|
|
|
private var list = originalList
|
|
|
|
|
2021-05-22 00:03:16 +02:00
|
|
|
private val iconColor = actMain.attrColor(R.attr.colorTimeSmall)
|
|
|
|
|
|
|
|
override fun getCount(): Int = list.size
|
|
|
|
override fun getItem(position: Int): Any = list[position]
|
|
|
|
override fun getItemId(position: Int): Long = 0L
|
|
|
|
|
|
|
|
override fun getViewTypeCount(): Int = itemTypeCount
|
|
|
|
override fun getItemViewType(position: Int): Int = list[position].itemType.id
|
|
|
|
|
|
|
|
private inline fun <reified T : View> viewOrInflate(
|
|
|
|
view: View?,
|
|
|
|
parent: ViewGroup?,
|
2022-03-11 00:11:49 +01:00
|
|
|
resId: Int,
|
2021-05-22 00:03:16 +02:00
|
|
|
): T =
|
|
|
|
(view ?: actMain.layoutInflater.inflate(resId, parent, false))
|
2021-11-14 14:23:17 +01:00
|
|
|
as? T ?: error("invalid view type! ${T::class.java.simpleName}")
|
2021-05-22 00:03:16 +02:00
|
|
|
|
|
|
|
override fun getView(position: Int, view: View?, parent: ViewGroup?): View =
|
|
|
|
list[position].run {
|
|
|
|
when (itemType) {
|
|
|
|
ItemType.IT_DIVIDER ->
|
|
|
|
viewOrInflate(view, parent, R.layout.lv_sidemenu_separator)
|
|
|
|
ItemType.IT_GROUP_HEADER ->
|
|
|
|
viewOrInflate<TextView>(view, parent, R.layout.lv_sidemenu_group).apply {
|
|
|
|
text = actMain.getString(title)
|
|
|
|
}
|
|
|
|
ItemType.IT_NORMAL ->
|
|
|
|
viewOrInflate<TextView>(view, parent, R.layout.lv_sidemenu_item).apply {
|
|
|
|
isAllCaps = false
|
|
|
|
text = actMain.getString(title)
|
|
|
|
val drawable = createColoredDrawable(actMain, icon, iconColor, 1f)
|
|
|
|
setCompoundDrawablesRelativeWithIntrinsicBounds(
|
|
|
|
drawable,
|
|
|
|
null,
|
|
|
|
null,
|
|
|
|
null
|
|
|
|
)
|
|
|
|
|
|
|
|
setOnClickListener {
|
|
|
|
action(actMain)
|
|
|
|
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
|
2022-07-16 23:44:58 +02:00
|
|
|
setLineSpacing(
|
|
|
|
1f,
|
|
|
|
1.1f
|
|
|
|
)
|
2021-05-22 00:03:16 +02:00
|
|
|
background = null
|
2022-07-16 23:44:58 +02:00
|
|
|
text = versionText
|
2021-05-22 00:03:16 +02:00
|
|
|
}
|
2021-11-14 14:23:17 +01:00
|
|
|
ItemType.IT_TIMEZONE ->
|
|
|
|
viewOrInflate<TextView>(view, parent, R.layout.lv_sidemenu_item).apply {
|
|
|
|
textSize = 14f
|
|
|
|
isAllCaps = false
|
|
|
|
background = null
|
|
|
|
text = getTimeZoneString(context)
|
|
|
|
}
|
2023-02-05 19:08:48 +01:00
|
|
|
ItemType.IT_NOTIFICATION_PERMISSION ->
|
|
|
|
viewOrInflate<TextView>(view, parent, R.layout.lv_sidemenu_item).apply {
|
|
|
|
isAllCaps = false
|
2023-02-08 10:55:49 +01:00
|
|
|
val action = notificationActionRecommend() ?: return@apply
|
|
|
|
text = actMain.getString(action.first)
|
2023-02-05 19:08:48 +01:00
|
|
|
val drawable = createColoredDrawable(actMain, icon, iconColor, 1f)
|
|
|
|
setCompoundDrawablesRelativeWithIntrinsicBounds(
|
|
|
|
drawable,
|
|
|
|
null,
|
|
|
|
null,
|
|
|
|
null
|
|
|
|
)
|
|
|
|
setOnClickListener {
|
|
|
|
drawer.closeDrawer(GravityCompat.START)
|
2023-02-08 10:55:49 +01:00
|
|
|
notificationActionRecommend()?.second?.invoke()
|
|
|
|
filterListItems()
|
2023-02-05 19:08:48 +01:00
|
|
|
}
|
|
|
|
}
|
2021-11-14 14:23:17 +01:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
private fun getTimeZoneString(context: Context): String {
|
|
|
|
try {
|
|
|
|
var tz = TimeZone.getDefault()
|
2023-02-04 21:52:26 +01:00
|
|
|
val tzId = PrefS.spTimeZone.value
|
2021-11-14 14:23:17 +01:00
|
|
|
if (tzId.isBlank()) {
|
2021-11-16 14:05:08 +01:00
|
|
|
return tz.displayName + "(" + context.getString(R.string.device_timezone) + ")"
|
2021-11-14 14:23:17 +01:00
|
|
|
}
|
|
|
|
tz = TimeZone.getTimeZone(tzId)
|
|
|
|
var offset = tz.rawOffset.toLong()
|
|
|
|
return when (offset) {
|
|
|
|
0L -> "(UTC\u00B100:00) ${tz.id} ${tz.displayName}"
|
|
|
|
else -> {
|
|
|
|
|
|
|
|
val format = when {
|
|
|
|
offset > 0 -> "(UTC+%02d:%02d) %s %s"
|
|
|
|
else -> "(UTC-%02d:%02d) %s %s"
|
|
|
|
}
|
|
|
|
|
|
|
|
offset = abs(offset)
|
|
|
|
|
|
|
|
val hours = TimeUnit.MILLISECONDS.toHours(offset)
|
|
|
|
val minutes =
|
|
|
|
TimeUnit.MILLISECONDS.toMinutes(offset) - TimeUnit.HOURS.toMinutes(hours)
|
|
|
|
|
|
|
|
String.format(format, hours, minutes, tz.id, tz.displayName)
|
|
|
|
}
|
2021-05-22 00:03:16 +02:00
|
|
|
}
|
2021-11-14 14:23:17 +01:00
|
|
|
} catch (ex: Throwable) {
|
2023-01-05 07:17:09 +01:00
|
|
|
log.w(ex, "getTimeZoneString failed.")
|
2021-11-14 14:23:17 +01:00
|
|
|
return "(incorrect TimeZone)"
|
2021-05-22 00:03:16 +02:00
|
|
|
}
|
2021-11-14 14:23:17 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
fun onActivityStart() {
|
|
|
|
this.notifyDataSetChanged()
|
|
|
|
}
|
2021-05-22 00:03:16 +02:00
|
|
|
|
2023-02-08 10:55:49 +01:00
|
|
|
private fun notificationActionRecommend(): Pair<Int, () -> Unit>? = when {
|
2023-02-09 17:23:29 +01:00
|
|
|
// 通知権限がない場合の警告とアクション
|
2023-02-08 10:55:49 +01:00
|
|
|
actMain.prNotification.spec.listNotGranded(actMain).isNotEmpty() ->
|
|
|
|
Pair(R.string.notification_permission_not_granted) {
|
|
|
|
actMain.prNotification.openAppSetting(actMain)
|
|
|
|
}
|
2023-02-09 17:23:29 +01:00
|
|
|
// プッシュ配送が選択されていない場合の警告とアクション
|
|
|
|
(actMain.prefDevice.pushDistributor.isNullOrEmpty() && fcmHandler.noFcm(actMain)) ||
|
2023-02-08 10:55:49 +01:00
|
|
|
actMain.prefDevice.pushDistributor == PUSH_DISTRIBUTOR_NONE ->
|
|
|
|
Pair(R.string.notification_push_distributor_disabled) {
|
|
|
|
actMain.selectPushDistributor()
|
|
|
|
}
|
|
|
|
else -> null
|
|
|
|
}
|
|
|
|
|
2023-03-31 04:17:11 +02:00
|
|
|
fun filterListItems(notify: Boolean = true) {
|
2023-02-20 12:14:26 +01:00
|
|
|
log.i("filterListItems notify=$notify")
|
2023-02-05 19:08:48 +01:00
|
|
|
list = originalList.filter {
|
|
|
|
when (it.itemType) {
|
|
|
|
ItemType.IT_NOTIFICATION_PERMISSION ->
|
2023-02-08 10:55:49 +01:00
|
|
|
notificationActionRecommend() != null
|
2023-02-20 12:14:26 +01:00
|
|
|
|
|
|
|
ItemType.IT_NORMAL -> when (it.title) {
|
|
|
|
R.string.antenna_list_misskey,
|
|
|
|
R.string.misskey_hybrid_timeline_long,
|
|
|
|
-> PrefB.bpEnableDeprecatedSomething.value
|
|
|
|
|
|
|
|
else -> true
|
|
|
|
}
|
2023-02-05 19:08:48 +01:00
|
|
|
else -> true
|
|
|
|
}
|
|
|
|
}
|
2023-03-31 04:17:11 +02:00
|
|
|
if (notify) notifyDataSetChanged()
|
2023-02-05 19:08:48 +01:00
|
|
|
}
|
|
|
|
|
2021-05-22 00:03:16 +02:00
|
|
|
init {
|
2022-07-16 23:44:58 +02:00
|
|
|
actMain.applicationContext.checkVersion()
|
2023-02-20 12:14:26 +01:00
|
|
|
filterListItems(notify = false)
|
2021-05-22 00:03:16 +02:00
|
|
|
|
|
|
|
ListView(actMain).apply {
|
|
|
|
adapter = this@SideMenuAdapter
|
|
|
|
layoutParams = FrameLayout.LayoutParams(
|
|
|
|
FrameLayout.LayoutParams.MATCH_PARENT,
|
|
|
|
FrameLayout.LayoutParams.MATCH_PARENT
|
|
|
|
)
|
|
|
|
backgroundColor = actMain.attrColor(R.attr.colorWindowBackground)
|
|
|
|
selector = StateListDrawable()
|
|
|
|
divider = null
|
|
|
|
dividerHeight = 0
|
|
|
|
isScrollbarFadingEnabled = false
|
|
|
|
|
2021-06-20 15:12:25 +02:00
|
|
|
val padV = (actMain.density * 12f + 0.5f).toInt()
|
|
|
|
setPadding(0, padV, 0, padV)
|
2021-05-22 00:03:16 +02:00
|
|
|
clipToPadding = false
|
|
|
|
scrollBarStyle = ListView.SCROLLBARS_OUTSIDE_OVERLAY
|
|
|
|
|
|
|
|
navigationView.addView(this)
|
|
|
|
}
|
|
|
|
}
|
2019-08-23 14:50:04 +02:00
|
|
|
}
|