「アプリ設定/挙動/Webブラウザ」を追加
This commit is contained in:
parent
70dd21bf41
commit
35deaf985f
|
@ -20,6 +20,18 @@
|
|||
<category android:name="android.intent.category.BROWSABLE" />
|
||||
</intent>
|
||||
|
||||
<intent>
|
||||
<action android:name="android.intent.action.VIEW" />
|
||||
<category android:name="android.intent.category.BROWSABLE" />
|
||||
<data android:scheme="https" />
|
||||
</intent>
|
||||
|
||||
<intent>
|
||||
<action android:name="android.intent.action.VIEW" />
|
||||
<category android:name="android.intent.category.BROWSABLE" />
|
||||
<data android:scheme="http" />
|
||||
</intent>
|
||||
|
||||
<!-- Chrome Custom Tabs の存在確認 -->
|
||||
<intent>
|
||||
<action android:name="android.support.customtabs.action.CustomTabsService" />
|
||||
|
|
|
@ -2,6 +2,7 @@ package jp.juggler.subwaytooter
|
|||
|
||||
import android.content.Intent
|
||||
import android.content.SharedPreferences
|
||||
import android.content.pm.ResolveInfo
|
||||
import android.graphics.Color
|
||||
import android.graphics.Typeface
|
||||
import android.net.Uri
|
||||
|
@ -21,13 +22,14 @@ import androidx.core.content.ContextCompat
|
|||
import androidx.core.content.FileProvider
|
||||
import com.jrummyapps.android.colorpicker.ColorPickerDialog
|
||||
import com.jrummyapps.android.colorpicker.ColorPickerDialogListener
|
||||
import jp.juggler.subwaytooter.util.CustomShare
|
||||
import jp.juggler.subwaytooter.util.CustomShareTarget
|
||||
import jp.juggler.subwaytooter.dialog.DlgAppPicker
|
||||
import jp.juggler.subwaytooter.notification.PollingWorker
|
||||
import jp.juggler.subwaytooter.table.AcctColor
|
||||
import jp.juggler.subwaytooter.table.SavedAccount
|
||||
import jp.juggler.subwaytooter.util.AsyncActivity
|
||||
import jp.juggler.subwaytooter.util.CustomShare
|
||||
import jp.juggler.subwaytooter.util.CustomShareTarget
|
||||
import jp.juggler.subwaytooter.util.cn
|
||||
import jp.juggler.util.*
|
||||
import org.apache.commons.io.IOUtils
|
||||
import java.io.File
|
||||
|
@ -1127,7 +1129,7 @@ class ActAppSetting : AsyncActivity(), ColorPickerDialogListener, View.OnClickLi
|
|||
return list.size
|
||||
}
|
||||
|
||||
override fun getItem(position : Int) : Any? {
|
||||
override fun getItem(position : Int) : Any {
|
||||
return list[position]
|
||||
}
|
||||
|
||||
|
@ -1164,16 +1166,17 @@ class ActAppSetting : AsyncActivity(), ColorPickerDialogListener, View.OnClickLi
|
|||
}
|
||||
}
|
||||
|
||||
fun openCustomShareChooser(target : CustomShareTarget) {
|
||||
fun openCustomShareChooser(appSettingItem: AppSettingItem,target : CustomShareTarget) {
|
||||
try {
|
||||
val rv = DlgAppPicker(
|
||||
this,
|
||||
Intent().apply {
|
||||
intent = Intent().apply {
|
||||
action = Intent.ACTION_SEND
|
||||
type = "text/plain"
|
||||
putExtra(Intent.EXTRA_TEXT, getString(R.string.content_sample))
|
||||
}
|
||||
) { setCustomShare(target, it) }
|
||||
},
|
||||
addCopyAction = true
|
||||
) { setCustomShare(appSettingItem,target, it) }
|
||||
.show()
|
||||
if(! rv) showToast(true, "share target app is not installed.")
|
||||
} catch(ex : Throwable) {
|
||||
|
@ -1182,22 +1185,11 @@ class ActAppSetting : AsyncActivity(), ColorPickerDialogListener, View.OnClickLi
|
|||
}
|
||||
}
|
||||
|
||||
fun setCustomShare(target : CustomShareTarget?, value : String) {
|
||||
|
||||
target ?: return
|
||||
|
||||
val item = when(target) {
|
||||
CustomShareTarget.Translate -> AppSettingItem.CUSTOM_TRANSLATE
|
||||
CustomShareTarget.CustomShare1 -> AppSettingItem.CUSTOM_SHARE_1
|
||||
CustomShareTarget.CustomShare2 -> AppSettingItem.CUSTOM_SHARE_2
|
||||
CustomShareTarget.CustomShare3 -> AppSettingItem.CUSTOM_SHARE_3
|
||||
}
|
||||
?: error("setCustomShare $target has no setting item.")
|
||||
|
||||
val sp : StringPref = item.pref.cast() ?: error("$target: not StringPref")
|
||||
fun setCustomShare(appSettingItem: AppSettingItem,target : CustomShareTarget, value : String) {
|
||||
val sp : StringPref = appSettingItem.pref.cast() ?: error("$target: not StringPref")
|
||||
pref.edit().put(sp, value).apply()
|
||||
|
||||
showCustomShareIcon(findItemViewHolder(item)?.textView1, target)
|
||||
showCustomShareIcon(findItemViewHolder(appSettingItem)?.textView1, target)
|
||||
}
|
||||
|
||||
fun showCustomShareIcon(tv : TextView?, target : CustomShareTarget) {
|
||||
|
@ -1209,4 +1201,35 @@ class ActAppSetting : AsyncActivity(), ColorPickerDialogListener, View.OnClickLi
|
|||
tv.compoundDrawablePadding = (resources.displayMetrics.density * 4f + 0.5f).toInt()
|
||||
}
|
||||
|
||||
fun openWebBrowserChooser(appSettingItem: AppSettingItem, intent:Intent, filter: (ResolveInfo) -> Boolean ) {
|
||||
try {
|
||||
val rv = DlgAppPicker(
|
||||
this,
|
||||
intent=intent,
|
||||
filter = filter,
|
||||
addCopyAction = false
|
||||
) { setWebBrowser( appSettingItem,it) }
|
||||
.show()
|
||||
if(! rv) showToast(true, "share target app is not installed.")
|
||||
} catch(ex : Throwable) {
|
||||
log.trace(ex)
|
||||
showToast(ex, "openCustomShareChooser failed.")
|
||||
}
|
||||
}
|
||||
|
||||
fun setWebBrowser(appSettingItem: AppSettingItem, value : String) {
|
||||
val sp : StringPref = appSettingItem.pref.cast() ?: error("${getString(appSettingItem.caption)}: not StringPref")
|
||||
pref.edit().put(sp, value).apply()
|
||||
|
||||
showWebBrowser(findItemViewHolder(appSettingItem)?.textView1, value )
|
||||
}
|
||||
|
||||
fun showWebBrowser(tv : TextView?,prefValue:String) {
|
||||
tv ?: return
|
||||
val cn =prefValue.cn()
|
||||
val (label, icon) = CustomShare.getInfo(this, cn)
|
||||
tv.text = label ?: getString(R.string.not_selected)
|
||||
tv.setCompoundDrawablesRelativeWithIntrinsicBounds(icon, null, null, null)
|
||||
tv.compoundDrawablePadding = (resources.displayMetrics.density * 4f + 0.5f).toInt()
|
||||
}
|
||||
}
|
|
@ -14,7 +14,7 @@ import jp.juggler.subwaytooter.util.openBrowser
|
|||
import jp.juggler.util.*
|
||||
import org.jetbrains.anko.backgroundDrawable
|
||||
|
||||
enum class SettingType(val id : Int) {
|
||||
enum class SettingType(val id: Int) {
|
||||
Path(0),
|
||||
Divider(1),
|
||||
Switch(2),
|
||||
|
@ -31,177 +31,172 @@ enum class SettingType(val id : Int) {
|
|||
}
|
||||
|
||||
class AppSettingItem(
|
||||
val parent : AppSettingItem?,
|
||||
val type : SettingType,
|
||||
@StringRes val caption : Int,
|
||||
val pref : BasePref<*>? = null
|
||||
val parent: AppSettingItem?,
|
||||
val type: SettingType,
|
||||
@StringRes val caption: Int,
|
||||
val pref: BasePref<*>? = null
|
||||
) {
|
||||
|
||||
@StringRes
|
||||
var desc : Int = 0
|
||||
var desc: Int = 0
|
||||
var descClickSet = false
|
||||
var descClick : ActAppSetting.() -> Unit = {}
|
||||
var descClick: ActAppSetting.() -> Unit = {}
|
||||
set(value) {
|
||||
field = value
|
||||
descClickSet = true
|
||||
}
|
||||
|
||||
var getError : ActAppSetting.(String) -> String? = { null }
|
||||
var getError: ActAppSetting.(String) -> String? = { null }
|
||||
|
||||
// may be open exportAppData() or importAppData()
|
||||
var action : ActAppSetting.() -> Unit = {}
|
||||
var action: ActAppSetting.() -> Unit = {}
|
||||
|
||||
var changed : ActAppSetting.() -> Unit = {}
|
||||
var changed: ActAppSetting.() -> Unit = {}
|
||||
|
||||
// used for EditText
|
||||
var inputType = InputTypeEx.text
|
||||
|
||||
var sampleLayoutId : Int = 0
|
||||
var sampleUpdate : (ActAppSetting, View) -> Unit = { _, _ -> }
|
||||
var sampleLayoutId: Int = 0
|
||||
var sampleUpdate: (ActAppSetting, View) -> Unit = { _, _ -> }
|
||||
|
||||
var spinnerArgs : IntArray? = null
|
||||
var spinnerArgsProc : (ActAppSetting) -> List<String> = { _ -> emptyList() }
|
||||
var spinnerInitializer : ActAppSetting.(Spinner) -> Unit = {}
|
||||
var spinnerOnSelected : ActAppSetting.(Spinner, Int) -> Unit = { _, _ -> }
|
||||
var spinnerArgs: IntArray? = null
|
||||
var spinnerArgsProc: (ActAppSetting) -> List<String> = { _ -> emptyList() }
|
||||
var spinnerInitializer: ActAppSetting.(Spinner) -> Unit = {}
|
||||
var spinnerOnSelected: ActAppSetting.(Spinner, Int) -> Unit = { _, _ -> }
|
||||
|
||||
var enabled : Boolean = true
|
||||
var enabled: Boolean = true
|
||||
|
||||
var onClickEdit : ActAppSetting.() -> Unit = {}
|
||||
var onClickReset : ActAppSetting.() -> Unit = {}
|
||||
var showTextView : ActAppSetting.(TextView) -> Unit = {}
|
||||
var onClickEdit: ActAppSetting.() -> Unit = {}
|
||||
var onClickReset: ActAppSetting.() -> Unit = {}
|
||||
var showTextView: ActAppSetting.(TextView) -> Unit = {}
|
||||
|
||||
// for EditText
|
||||
var hint : String? = null
|
||||
var filter : (String) -> String = { it.trim() }
|
||||
var captionFontSize : ActAppSetting.() -> Float? = { null }
|
||||
var captionSpacing : ActAppSetting.() -> Float? = { null }
|
||||
var hint: String? = null
|
||||
var filter: (String) -> String = { it.trim() }
|
||||
var captionFontSize: ActAppSetting.() -> Float? = { null }
|
||||
var captionSpacing: ActAppSetting.() -> Float? = { null }
|
||||
|
||||
// cast before save
|
||||
var toFloat : ActAppSetting.(String) -> Float = { 0f }
|
||||
var fromFloat : ActAppSetting.(Float) -> String = { it.toString() }
|
||||
var toFloat: ActAppSetting.(String) -> Float = { 0f }
|
||||
var fromFloat: ActAppSetting.(Float) -> String = { it.toString() }
|
||||
|
||||
val items = ArrayList<AppSettingItem>()
|
||||
|
||||
fun section(
|
||||
@StringRes caption : Int,
|
||||
initializer : AppSettingItem.() -> Unit = {}
|
||||
@StringRes caption: Int,
|
||||
initializer: AppSettingItem.() -> Unit = {}
|
||||
) {
|
||||
items.add(AppSettingItem(this, SettingType.Section, caption).apply { initializer() })
|
||||
}
|
||||
|
||||
fun group(
|
||||
@StringRes caption : Int,
|
||||
initializer : AppSettingItem.() -> Unit = {}
|
||||
@StringRes caption: Int,
|
||||
initializer: AppSettingItem.() -> Unit = {}
|
||||
) {
|
||||
items.add(AppSettingItem(this, SettingType.Group, caption).apply { initializer() })
|
||||
}
|
||||
|
||||
fun item(
|
||||
type : SettingType,
|
||||
pref : BasePref<*>?,
|
||||
@StringRes caption : Int,
|
||||
initializer : AppSettingItem.() -> Unit = {}
|
||||
) : AppSettingItem {
|
||||
type: SettingType,
|
||||
pref: BasePref<*>?,
|
||||
@StringRes caption: Int,
|
||||
initializer: AppSettingItem.() -> Unit = {}
|
||||
): AppSettingItem {
|
||||
val item = AppSettingItem(this, type, caption, pref).apply { initializer() }
|
||||
items.add(item)
|
||||
return item
|
||||
}
|
||||
|
||||
fun spinner(
|
||||
pref : IntPref,
|
||||
@StringRes caption : Int,
|
||||
vararg args : Int
|
||||
pref: IntPref,
|
||||
@StringRes caption: Int,
|
||||
vararg args: Int
|
||||
) = item(SettingType.Spinner, pref, caption) {
|
||||
spinnerArgs = args
|
||||
}
|
||||
|
||||
fun spinner(
|
||||
pref : IntPref,
|
||||
@StringRes caption : Int,
|
||||
argsProc : (ActAppSetting) -> List<String>
|
||||
pref: IntPref,
|
||||
@StringRes caption: Int,
|
||||
argsProc: (ActAppSetting) -> List<String>
|
||||
) = item(SettingType.Spinner, pref, caption) {
|
||||
spinnerArgsProc = argsProc
|
||||
}
|
||||
|
||||
fun sw(
|
||||
pref : BooleanPref,
|
||||
@StringRes caption : Int,
|
||||
initializer : AppSettingItem.() -> Unit = {}
|
||||
pref: BooleanPref,
|
||||
@StringRes caption: Int,
|
||||
initializer: AppSettingItem.() -> Unit = {}
|
||||
) = item(SettingType.Switch, pref, caption, initializer)
|
||||
|
||||
fun checkbox(
|
||||
pref : BooleanPref,
|
||||
@StringRes caption : Int,
|
||||
initializer : AppSettingItem.() -> Unit = {}
|
||||
pref: BooleanPref,
|
||||
@StringRes caption: Int,
|
||||
initializer: AppSettingItem.() -> Unit = {}
|
||||
) = item(SettingType.CheckBox, pref, caption, initializer)
|
||||
|
||||
fun action(
|
||||
@StringRes caption : Int,
|
||||
initializer : AppSettingItem.() -> Unit = {}
|
||||
@StringRes caption: Int,
|
||||
initializer: AppSettingItem.() -> Unit = {}
|
||||
) = item(SettingType.Action, null, caption, initializer)
|
||||
|
||||
fun colorOpaque(
|
||||
pref : IntPref,
|
||||
@StringRes caption : Int,
|
||||
initializer : AppSettingItem.() -> Unit = {}
|
||||
pref: IntPref,
|
||||
@StringRes caption: Int,
|
||||
initializer: AppSettingItem.() -> Unit = {}
|
||||
) = item(SettingType.ColorOpaque, pref, caption, initializer)
|
||||
|
||||
fun colorAlpha(
|
||||
pref : IntPref,
|
||||
@StringRes caption : Int,
|
||||
initializer : AppSettingItem.() -> Unit = {}
|
||||
pref: IntPref,
|
||||
@StringRes caption: Int,
|
||||
initializer: AppSettingItem.() -> Unit = {}
|
||||
) = item(SettingType.ColorAlpha, pref, caption, initializer)
|
||||
|
||||
fun text(
|
||||
pref : StringPref,
|
||||
@StringRes caption : Int,
|
||||
inputType : Int,
|
||||
initializer : AppSettingItem.() -> Unit = {}
|
||||
pref: StringPref,
|
||||
@StringRes caption: Int,
|
||||
inputType: Int,
|
||||
initializer: AppSettingItem.() -> Unit = {}
|
||||
) = item(SettingType.EditText, pref, caption) {
|
||||
this.inputType = inputType
|
||||
this.initializer()
|
||||
}
|
||||
|
||||
fun textX(
|
||||
pref : BasePref<*>,
|
||||
@StringRes caption : Int,
|
||||
inputType : Int,
|
||||
initializer : AppSettingItem.() -> Unit = {}
|
||||
pref: BasePref<*>,
|
||||
@StringRes caption: Int,
|
||||
inputType: Int,
|
||||
initializer: AppSettingItem.() -> Unit = {}
|
||||
) = item(SettingType.EditText, pref, caption) {
|
||||
this.inputType = inputType
|
||||
this.initializer()
|
||||
}
|
||||
|
||||
fun sample(
|
||||
sampleLayoutId : Int = 0,
|
||||
sampleUpdate : (ActAppSetting, View) -> Unit = { _, _ -> }
|
||||
sampleLayoutId: Int = 0,
|
||||
sampleUpdate: (ActAppSetting, View) -> Unit = { _, _ -> }
|
||||
// ,initializer : AppSettingItem.() -> Unit = {}
|
||||
) = item(SettingType.Sample, pref, caption) {
|
||||
this.sampleLayoutId = sampleLayoutId
|
||||
this.sampleUpdate = sampleUpdate
|
||||
}
|
||||
|
||||
fun scan(block : (AppSettingItem) -> Unit) {
|
||||
fun scan(block: (AppSettingItem) -> Unit) {
|
||||
block(this)
|
||||
for(item in items) item.scan(block)
|
||||
for (item in items) item.scan(block)
|
||||
}
|
||||
|
||||
companion object {
|
||||
|
||||
var SAMPLE_CCD_HEADER : AppSettingItem? = null
|
||||
var SAMPLE_CCD_BODY : AppSettingItem? = null
|
||||
var SAMPLE_FOOTER : AppSettingItem? = null
|
||||
var SAMPLE_CCD_HEADER: AppSettingItem? = null
|
||||
var SAMPLE_CCD_BODY: AppSettingItem? = null
|
||||
var SAMPLE_FOOTER: AppSettingItem? = null
|
||||
|
||||
var CUSTOM_TRANSLATE : AppSettingItem? = null
|
||||
var CUSTOM_SHARE_1 : AppSettingItem? = null
|
||||
var CUSTOM_SHARE_2 : AppSettingItem? = null
|
||||
var CUSTOM_SHARE_3 : AppSettingItem? = null
|
||||
var TIMELINE_FONT: AppSettingItem? = null
|
||||
var TIMELINE_FONT_BOLD: AppSettingItem? = null
|
||||
|
||||
var TIMELINE_FONT : AppSettingItem? = null
|
||||
var TIMELINE_FONT_BOLD : AppSettingItem? = null
|
||||
|
||||
var FONT_SIZE_TIMELINE : AppSettingItem? = null
|
||||
var FONT_SIZE_NOTIFICATION_TL : AppSettingItem? = null
|
||||
var FONT_SIZE_TIMELINE: AppSettingItem? = null
|
||||
var FONT_SIZE_NOTIFICATION_TL: AppSettingItem? = null
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -259,6 +254,44 @@ val appSettingRoot = AppSettingItem(null, SettingType.Section, R.string.app_sett
|
|||
sw(Pref.bpDontScreenOff, R.string.dont_screen_off)
|
||||
sw(Pref.bpDontUseCustomTabs, R.string.dont_use_custom_tabs)
|
||||
sw(Pref.bpPriorChrome, R.string.prior_chrome_custom_tabs)
|
||||
|
||||
item(
|
||||
SettingType.TextWithSelector,
|
||||
Pref.spWebBrowser,
|
||||
R.string.web_browser
|
||||
) {
|
||||
onClickEdit = {
|
||||
openWebBrowserChooser(
|
||||
this@item,
|
||||
intent = Intent(Intent.ACTION_VIEW, "https://joinmastodon.org/".toUri()).apply {
|
||||
addFlags(Intent.FLAG_ACTIVITY_NEW_TASK)
|
||||
addCategory(Intent.CATEGORY_BROWSABLE)
|
||||
},
|
||||
filter = {
|
||||
when {
|
||||
it.activityInfo.packageName == packageName -> false
|
||||
!it.activityInfo.exported -> false
|
||||
|
||||
// Huaweiの謎Activityのせいでうまく働かないことがある
|
||||
-1 != it.activityInfo.packageName.indexOf("com.huawei.android.internal") -> false
|
||||
|
||||
// 標準アプリが設定されていない場合、アプリを選択するためのActivityが出てくる場合がある
|
||||
it.activityInfo.packageName == "android" -> false
|
||||
it.activityInfo.javaClass.name.startsWith("com.android.internal") -> false
|
||||
it.activityInfo.javaClass.name.startsWith("com.android.systemui") -> false
|
||||
|
||||
// たぶんChromeとかfirefoxとか
|
||||
else -> true
|
||||
}
|
||||
}
|
||||
)
|
||||
}
|
||||
onClickReset = { setWebBrowser(this@item, "") }
|
||||
showTextView = {
|
||||
showWebBrowser(it, this@item.pref.cast<StringPref>()!!.invoke(pref))
|
||||
}
|
||||
}
|
||||
|
||||
sw(Pref.bpAllowColumnDuplication, R.string.allow_column_duplication)
|
||||
sw(Pref.bpForceGap, R.string.force_gap_when_refresh)
|
||||
spinner(
|
||||
|
@ -280,7 +313,7 @@ val appSettingRoot = AppSettingItem(null, SettingType.Section, R.string.app_sett
|
|||
filter = { it.replace(ActAppSetting.reLinefeed, " ").trim() }
|
||||
getError = {
|
||||
val m = App1.reNotAllowedInUserAgent.matcher(it)
|
||||
when(m.find()) {
|
||||
when (m.find()) {
|
||||
true -> getString(R.string.user_agent_error, m.group())
|
||||
else -> null
|
||||
}
|
||||
|
@ -291,45 +324,46 @@ val appSettingRoot = AppSettingItem(null, SettingType.Section, R.string.app_sett
|
|||
sw(Pref.bpCustomEmojiSeparatorZwsp, R.string.custom_emoji_separator_zwsp)
|
||||
sw(Pref.bpShowTranslateButton, R.string.show_translate_button)
|
||||
|
||||
AppSettingItem.CUSTOM_TRANSLATE = item(
|
||||
item(
|
||||
SettingType.TextWithSelector,
|
||||
Pref.spTranslateAppComponent,
|
||||
R.string.translation_app
|
||||
) {
|
||||
val target = CustomShareTarget.Translate
|
||||
onClickEdit = { openCustomShareChooser(target) }
|
||||
onClickReset = { setCustomShare(target, "") }
|
||||
onClickEdit = { openCustomShareChooser(this@item, target) }
|
||||
onClickReset = { setCustomShare(this@item, target, "") }
|
||||
showTextView = { showCustomShareIcon(it, target) }
|
||||
}
|
||||
|
||||
AppSettingItem.CUSTOM_SHARE_1 = item(
|
||||
item(
|
||||
SettingType.TextWithSelector,
|
||||
Pref.spCustomShare1,
|
||||
R.string.custom_share_button_1
|
||||
) {
|
||||
val target = CustomShareTarget.CustomShare1
|
||||
onClickEdit = { openCustomShareChooser(target) }
|
||||
onClickReset = { setCustomShare(target, "") }
|
||||
onClickEdit = { openCustomShareChooser(this@item, target) }
|
||||
onClickReset = { setCustomShare(this@item, target, "") }
|
||||
showTextView = { showCustomShareIcon(it, target) }
|
||||
}
|
||||
AppSettingItem.CUSTOM_SHARE_2 = item(
|
||||
|
||||
item(
|
||||
SettingType.TextWithSelector,
|
||||
Pref.spCustomShare2,
|
||||
R.string.custom_share_button_2
|
||||
) {
|
||||
val target = CustomShareTarget.CustomShare2
|
||||
onClickEdit = { openCustomShareChooser(target) }
|
||||
onClickReset = { setCustomShare(target, "") }
|
||||
onClickEdit = { openCustomShareChooser(this@item, target) }
|
||||
onClickReset = { setCustomShare(this@item, target, "") }
|
||||
showTextView = { showCustomShareIcon(it, target) }
|
||||
}
|
||||
AppSettingItem.CUSTOM_SHARE_3 = item(
|
||||
item(
|
||||
SettingType.TextWithSelector,
|
||||
Pref.spCustomShare3,
|
||||
R.string.custom_share_button_3
|
||||
) {
|
||||
val target = CustomShareTarget.CustomShare3
|
||||
onClickEdit = { openCustomShareChooser(target) }
|
||||
onClickReset = { setCustomShare(target, "") }
|
||||
onClickEdit = { openCustomShareChooser(this@item, target) }
|
||||
onClickReset = { setCustomShare(this@item, target, "") }
|
||||
showTextView = { showCustomShareIcon(it, target) }
|
||||
}
|
||||
|
||||
|
@ -351,7 +385,7 @@ val appSettingRoot = AppSettingItem(null, SettingType.Section, R.string.app_sett
|
|||
|
||||
spinner(Pref.ipResizeImage, R.string.resize_image) { activity ->
|
||||
ActPost.resizeConfigList.map {
|
||||
when(it.type) {
|
||||
when (it.type) {
|
||||
ResizeType.None -> activity.getString(R.string.dont_resize)
|
||||
ResizeType.LongSide -> activity.getString(R.string.long_side_pixel, it.size)
|
||||
ResizeType.SquarePixel -> activity.getString(
|
||||
|
@ -426,7 +460,7 @@ val appSettingRoot = AppSettingItem(null, SettingType.Section, R.string.app_sett
|
|||
Pref.lpTabletTootDefaultAccount,
|
||||
R.string.toot_button_default_account
|
||||
) {
|
||||
val lp = pref.cast<LongPref>() !!
|
||||
val lp = pref.cast<LongPref>()!!
|
||||
spinnerInitializer = { spinner ->
|
||||
val adapter = AccountAdapter()
|
||||
spinner.adapter = adapter
|
||||
|
@ -479,7 +513,7 @@ val appSettingRoot = AppSettingItem(null, SettingType.Section, R.string.app_sett
|
|||
Pref.spTimeZone,
|
||||
R.string.timezone
|
||||
) {
|
||||
val sp : StringPref = pref.cast() !!
|
||||
val sp: StringPref = pref.cast()!!
|
||||
spinnerInitializer = { spinner ->
|
||||
val adapter = TimeZoneAdapter()
|
||||
spinner.adapter = adapter
|
||||
|
@ -537,7 +571,7 @@ val appSettingRoot = AppSettingItem(null, SettingType.Section, R.string.app_sett
|
|||
try {
|
||||
val intent = intentOpenDocument("*/*")
|
||||
startActivityForResult(intent, ActAppSetting.REQUEST_CODE_TIMELINE_FONT)
|
||||
} catch(ex : Throwable) {
|
||||
} catch (ex: Throwable) {
|
||||
showToast(ex, "could not open picker for font")
|
||||
}
|
||||
}
|
||||
|
@ -559,7 +593,7 @@ val appSettingRoot = AppSettingItem(null, SettingType.Section, R.string.app_sett
|
|||
try {
|
||||
val intent = intentOpenDocument("*/*")
|
||||
startActivityForResult(intent, ActAppSetting.REQUEST_CODE_TIMELINE_FONT_BOLD)
|
||||
} catch(ex : Throwable) {
|
||||
} catch (ex: Throwable) {
|
||||
showToast(ex, "could not open picker for font")
|
||||
}
|
||||
}
|
||||
|
@ -577,7 +611,7 @@ val appSettingRoot = AppSettingItem(null, SettingType.Section, R.string.app_sett
|
|||
) {
|
||||
|
||||
val item = this
|
||||
val fp : FloatPref = item.pref.cast() !!
|
||||
val fp: FloatPref = item.pref.cast()!!
|
||||
|
||||
toFloat = { parseFontSize(it) }
|
||||
fromFloat = { formatFontSize(it) }
|
||||
|
@ -585,7 +619,7 @@ val appSettingRoot = AppSettingItem(null, SettingType.Section, R.string.app_sett
|
|||
captionFontSize = {
|
||||
val fv = fp(pref)
|
||||
when {
|
||||
! fv.isFinite() -> Pref.default_timeline_font_size
|
||||
!fv.isFinite() -> Pref.default_timeline_font_size
|
||||
fv < 1f -> 1f
|
||||
else -> fv
|
||||
}
|
||||
|
@ -600,7 +634,7 @@ val appSettingRoot = AppSettingItem(null, SettingType.Section, R.string.app_sett
|
|||
|
||||
textX(Pref.fpAcctFontSize, R.string.acct_font_size, InputTypeEx.numberDecimal) {
|
||||
val item = this
|
||||
val fp : FloatPref = item.pref.cast() !!
|
||||
val fp: FloatPref = item.pref.cast()!!
|
||||
|
||||
toFloat = { parseFontSize(it) }
|
||||
fromFloat = { formatFontSize(it) }
|
||||
|
@ -608,7 +642,7 @@ val appSettingRoot = AppSettingItem(null, SettingType.Section, R.string.app_sett
|
|||
captionFontSize = {
|
||||
val fv = fp(pref)
|
||||
when {
|
||||
! fv.isFinite() -> Pref.default_acct_font_size
|
||||
!fv.isFinite() -> Pref.default_acct_font_size
|
||||
fv < 1f -> 1f
|
||||
else -> fv
|
||||
}
|
||||
|
@ -623,7 +657,7 @@ val appSettingRoot = AppSettingItem(null, SettingType.Section, R.string.app_sett
|
|||
InputTypeEx.numberDecimal
|
||||
) {
|
||||
val item = this
|
||||
val fp : FloatPref = item.pref.cast() !!
|
||||
val fp: FloatPref = item.pref.cast()!!
|
||||
|
||||
toFloat = { parseFontSize(it) }
|
||||
fromFloat = { formatFontSize(it) }
|
||||
|
@ -631,7 +665,7 @@ val appSettingRoot = AppSettingItem(null, SettingType.Section, R.string.app_sett
|
|||
captionFontSize = {
|
||||
val fv = fp(pref)
|
||||
when {
|
||||
! fv.isFinite() -> Pref.default_notification_tl_font_size
|
||||
!fv.isFinite() -> Pref.default_notification_tl_font_size
|
||||
fv < 1f -> 1f
|
||||
else -> fv
|
||||
}
|
||||
|
@ -674,7 +708,7 @@ val appSettingRoot = AppSettingItem(null, SettingType.Section, R.string.app_sett
|
|||
text(Pref.spHeaderIconSize, R.string.header_icon_size, InputTypeEx.numberDecimal)
|
||||
textX(Pref.fpHeaderTextSize, R.string.header_text_size, InputTypeEx.numberDecimal) {
|
||||
val item = this
|
||||
val fp : FloatPref = item.pref.cast() !!
|
||||
val fp: FloatPref = item.pref.cast()!!
|
||||
|
||||
toFloat = { parseFontSize(it) }
|
||||
fromFloat = { formatFontSize(it) }
|
||||
|
@ -682,7 +716,7 @@ val appSettingRoot = AppSettingItem(null, SettingType.Section, R.string.app_sett
|
|||
captionFontSize = {
|
||||
val fv = fp(pref)
|
||||
when {
|
||||
! fv.isFinite() -> Pref.default_header_font_size
|
||||
!fv.isFinite() -> Pref.default_header_font_size
|
||||
fv < 1f -> 1f
|
||||
else -> fv
|
||||
}
|
||||
|
@ -701,7 +735,7 @@ val appSettingRoot = AppSettingItem(null, SettingType.Section, R.string.app_sett
|
|||
|
||||
sw(Pref.bpOpenSticker, R.string.show_open_sticker) {
|
||||
desc = R.string.powered_by_open_sticker
|
||||
descClick = {openBrowser("https://github.com/cutls/OpenSticker") }
|
||||
descClick = { openBrowser("https://github.com/cutls/OpenSticker") }
|
||||
}
|
||||
|
||||
sw(Pref.bpLinksInContextMenu, R.string.show_links_in_context_menu)
|
||||
|
@ -787,9 +821,9 @@ val appSettingRoot = AppSettingItem(null, SettingType.Section, R.string.app_sett
|
|||
AppSettingItem.SAMPLE_CCD_HEADER =
|
||||
sample(R.layout.setting_sample_column_header) { activity, viewRoot ->
|
||||
|
||||
val llColumnHeader : View = viewRoot.findViewById(R.id.llColumnHeader)
|
||||
val ivColumnHeader : ImageView = viewRoot.findViewById(R.id.ivColumnHeader)
|
||||
val tvColumnName : TextView = viewRoot.findViewById(R.id.tvColumnName)
|
||||
val llColumnHeader: View = viewRoot.findViewById(R.id.llColumnHeader)
|
||||
val ivColumnHeader: ImageView = viewRoot.findViewById(R.id.ivColumnHeader)
|
||||
val tvColumnName: TextView = viewRoot.findViewById(R.id.tvColumnName)
|
||||
|
||||
val color_column_header_bg = Pref.ipCcdHeaderBg(activity.pref)
|
||||
val color_column_header_fg = Pref.ipCcdHeaderFg(activity.pref)
|
||||
|
@ -820,9 +854,9 @@ val appSettingRoot = AppSettingItem(null, SettingType.Section, R.string.app_sett
|
|||
|
||||
AppSettingItem.SAMPLE_CCD_BODY =
|
||||
sample(R.layout.setting_sample_column_body) { activity, viewRoot ->
|
||||
val flColumnBackground : View = viewRoot.findViewById(R.id.flColumnBackground)
|
||||
val tvSampleAcct : TextView = viewRoot.findViewById(R.id.tvSampleAcct)
|
||||
val tvSampleContent : TextView = viewRoot.findViewById(R.id.tvSampleContent)
|
||||
val flColumnBackground: View = viewRoot.findViewById(R.id.flColumnBackground)
|
||||
val tvSampleAcct: TextView = viewRoot.findViewById(R.id.tvSampleAcct)
|
||||
val tvSampleContent: TextView = viewRoot.findViewById(R.id.tvSampleContent)
|
||||
|
||||
val color_column_bg = Pref.ipCcdContentBg(activity.pref)
|
||||
val color_column_acct = Pref.ipCcdContentAcct(activity.pref)
|
||||
|
@ -858,12 +892,12 @@ val appSettingRoot = AppSettingItem(null, SettingType.Section, R.string.app_sett
|
|||
AppSettingItem.SAMPLE_FOOTER =
|
||||
sample(R.layout.setting_sample_footer) { activity, viewRoot ->
|
||||
val pref = activity.pref
|
||||
val ivFooterToot : AppCompatImageView = viewRoot.findViewById(R.id.ivFooterToot)
|
||||
val ivFooterMenu : AppCompatImageView = viewRoot.findViewById(R.id.ivFooterMenu)
|
||||
val llFooterBG : View = viewRoot.findViewById(R.id.llFooterBG)
|
||||
val vFooterDivider1 : View = viewRoot.findViewById(R.id.vFooterDivider1)
|
||||
val vFooterDivider2 : View = viewRoot.findViewById(R.id.vFooterDivider2)
|
||||
val vIndicator : View = viewRoot.findViewById(R.id.vIndicator)
|
||||
val ivFooterToot: AppCompatImageView = viewRoot.findViewById(R.id.ivFooterToot)
|
||||
val ivFooterMenu: AppCompatImageView = viewRoot.findViewById(R.id.ivFooterMenu)
|
||||
val llFooterBG: View = viewRoot.findViewById(R.id.llFooterBG)
|
||||
val vFooterDivider1: View = viewRoot.findViewById(R.id.vFooterDivider1)
|
||||
val vFooterDivider2: View = viewRoot.findViewById(R.id.vFooterDivider2)
|
||||
val vIndicator: View = viewRoot.findViewById(R.id.vIndicator)
|
||||
|
||||
val footer_button_bg_color = Pref.ipFooterButtonBgColor(pref)
|
||||
val footer_button_fg_color = Pref.ipFooterButtonFgColor(pref)
|
||||
|
@ -960,7 +994,7 @@ val appSettingRoot = AppSettingItem(null, SettingType.Section, R.string.app_sett
|
|||
}
|
||||
action(R.string.exit_reasons) {
|
||||
action = {
|
||||
if(Build.VERSION.SDK_INT >= 30) {
|
||||
if (Build.VERSION.SDK_INT >= 30) {
|
||||
startActivity(Intent(this, ActExitReasons::class.java))
|
||||
} else {
|
||||
showToast(false, "this feature requires Android 11")
|
||||
|
|
|
@ -591,6 +591,7 @@ object Pref {
|
|||
val spCustomShare1 = StringPref("CustomShare1", "")
|
||||
val spCustomShare2 = StringPref("CustomShare2", "")
|
||||
val spCustomShare3 = StringPref("CustomShare3", "")
|
||||
val spWebBrowser = StringPref("WebBrowser", "")
|
||||
|
||||
val spTimelineSpacing = StringPref("TimelineSpacing", "")
|
||||
|
||||
|
|
|
@ -21,8 +21,9 @@ class DlgAppPicker(
|
|||
val activity: Activity,
|
||||
val intent: Intent,
|
||||
val autoSelect: Boolean = false,
|
||||
val addCopyAction:Boolean= false,
|
||||
val filter: (ResolveInfo) -> Boolean = { true },
|
||||
val callback: (String) -> Unit
|
||||
val callback: (String) -> Unit,
|
||||
) {
|
||||
|
||||
companion object {
|
||||
|
@ -55,7 +56,7 @@ class DlgAppPicker(
|
|||
}
|
||||
|
||||
// 自動選択オフの場合、末尾にクリップボード項目を追加する
|
||||
if (!autoSelect) {
|
||||
if (addCopyAction && !autoSelect) {
|
||||
val (label, icon) = CustomShare.getInfo(activity, CustomShare.CN_CLIPBOARD.cn())
|
||||
add(ListItem(icon, label.toString(), CustomShare.CN_CLIPBOARD))
|
||||
}
|
||||
|
|
|
@ -8,6 +8,7 @@ import android.net.Uri
|
|||
import android.os.Build
|
||||
import android.os.Bundle
|
||||
import android.app.Activity
|
||||
import android.content.SharedPreferences
|
||||
import androidx.browser.customtabs.CustomTabColorSchemeParams
|
||||
import androidx.browser.customtabs.CustomTabsIntent
|
||||
import jp.juggler.subwaytooter.ActMain
|
||||
|
@ -40,15 +41,23 @@ private val log = LogCategory("AppOpener")
|
|||
// returns true if activity is opened.
|
||||
// returns false if fallback required
|
||||
private fun Activity.startActivityExcludeMyApp(
|
||||
pref:SharedPreferences,
|
||||
intent: Intent,
|
||||
startAnimationBundle: Bundle? = null
|
||||
): Boolean {
|
||||
try {
|
||||
if( intent.component == null){
|
||||
val cn = Pref.spWebBrowser(pref).cn()
|
||||
if( cn?.exists(this) == true){
|
||||
intent.component = cn
|
||||
}
|
||||
}
|
||||
|
||||
// このアプリのパッケージ名
|
||||
val myName = packageName
|
||||
|
||||
val filter: (ResolveInfo) -> Boolean = {
|
||||
when{
|
||||
when {
|
||||
it.activityInfo.packageName == myName -> false
|
||||
!it.activityInfo.exported -> false
|
||||
|
||||
|
@ -57,7 +66,7 @@ private fun Activity.startActivityExcludeMyApp(
|
|||
|
||||
// 標準アプリが設定されていない場合、アプリを選択するためのActivityが出てくる場合がある
|
||||
it.activityInfo.packageName == "android" -> false
|
||||
it.activityInfo.javaClass.name.startsWith( "com.android.internal") -> false
|
||||
it.activityInfo.javaClass.name.startsWith("com.android.internal") -> false
|
||||
it.activityInfo.javaClass.name.startsWith("com.android.systemui") -> false
|
||||
|
||||
// たぶんChromeとかfirefoxとか
|
||||
|
@ -89,7 +98,8 @@ private fun Activity.startActivityExcludeMyApp(
|
|||
this,
|
||||
intent,
|
||||
autoSelect = true,
|
||||
filter = filter
|
||||
filter = filter,
|
||||
addCopyAction = false
|
||||
) {
|
||||
try {
|
||||
intent.component = it.cn()
|
||||
|
@ -108,16 +118,20 @@ private fun Activity.startActivityExcludeMyApp(
|
|||
}
|
||||
}
|
||||
|
||||
fun Activity.openBrowser(uri: Uri?) {
|
||||
fun Activity.openBrowser(uri: Uri? , pref:SharedPreferences = pref()) {
|
||||
uri ?: return
|
||||
val rv = startActivityExcludeMyApp(Intent(Intent.ACTION_VIEW, uri))
|
||||
val rv = startActivityExcludeMyApp(
|
||||
pref,
|
||||
Intent(Intent.ACTION_VIEW, uri)
|
||||
.apply { addCategory(Intent.CATEGORY_BROWSABLE) }
|
||||
)
|
||||
if (!rv) showToast(true, "there is no app that can open $uri")
|
||||
}
|
||||
|
||||
fun Activity.openBrowser(url: String?) = openBrowser(url.mayUri())
|
||||
fun Activity.openBrowser(url: String?, pref:SharedPreferences = pref()) = openBrowser(url.mayUri(),pref)
|
||||
|
||||
// Chrome Custom Tab を開く
|
||||
fun Activity.openCustomTab(url: String?) {
|
||||
fun Activity.openCustomTab(url: String?, pref:SharedPreferences = pref()) {
|
||||
url ?: return
|
||||
|
||||
if (url.isEmpty()) {
|
||||
|
@ -125,9 +139,8 @@ fun Activity.openCustomTab(url: String?) {
|
|||
return
|
||||
}
|
||||
|
||||
val pref = pref()
|
||||
if (Pref.bpDontUseCustomTabs(pref)) {
|
||||
openBrowser(url)
|
||||
openBrowser(url,pref)
|
||||
return
|
||||
}
|
||||
|
||||
|
@ -144,6 +157,7 @@ fun Activity.openCustomTab(url: String?) {
|
|||
.let {
|
||||
log.w("startCustomTabIntent ComponentName=$cn")
|
||||
startActivityExcludeMyApp(
|
||||
pref,
|
||||
it.intent.also { intent ->
|
||||
if (cn != null) intent.component = cn
|
||||
intent.data = url.toUri()
|
||||
|
|
|
@ -31,12 +31,12 @@ object CustomShare {
|
|||
"com.google.android.apps.translate/com.google.android.apps.translate.TranslateActivity"
|
||||
|
||||
fun getCustomShareComponentName(
|
||||
pref : SharedPreferences,
|
||||
target : CustomShareTarget
|
||||
) : ComponentName? {
|
||||
val src : String
|
||||
val defaultComponentName : String?
|
||||
when(target) {
|
||||
pref: SharedPreferences,
|
||||
target: CustomShareTarget
|
||||
): ComponentName? {
|
||||
val src: String
|
||||
val defaultComponentName: String?
|
||||
when (target) {
|
||||
CustomShareTarget.Translate -> {
|
||||
src = Pref.spTranslateAppComponent(pref)
|
||||
defaultComponentName = translate_app_component_default
|
||||
|
@ -60,14 +60,14 @@ object CustomShare {
|
|||
return src.cn() ?: defaultComponentName?.cn()
|
||||
}
|
||||
|
||||
fun getInfo(context : Context, cn : ComponentName?) : Pair<CharSequence?, Drawable?> {
|
||||
var label : CharSequence? = null
|
||||
var icon : Drawable? = null
|
||||
fun getInfo(context: Context, cn: ComponentName?): Pair<CharSequence?, Drawable?> {
|
||||
var label: CharSequence? = null
|
||||
var icon: Drawable? = null
|
||||
try {
|
||||
if(cn != null) {
|
||||
if (cn != null) {
|
||||
val cnStr = "${cn.packageName}/${cn.className}"
|
||||
label = cnStr
|
||||
if(cnStr == CN_CLIPBOARD) {
|
||||
if (cnStr == CN_CLIPBOARD) {
|
||||
label =
|
||||
"${context.getString(R.string.copy_to_clipboard)}(${context.getString(R.string.app_name)})"
|
||||
icon = ContextCompat.getDrawable(context, R.drawable.ic_copy)?.mutate()?.apply {
|
||||
|
@ -77,44 +77,44 @@ object CustomShare {
|
|||
} else {
|
||||
val pm = context.packageManager
|
||||
val ri = pm.resolveActivity(Intent().apply { component = cn }, 0)
|
||||
if(ri != null) {
|
||||
if (ri != null) {
|
||||
try {
|
||||
label = ri.loadLabel(pm)
|
||||
} catch(ex : Throwable) {
|
||||
} catch (ex: Throwable) {
|
||||
log.e(ex, "loadLabel failed.")
|
||||
}
|
||||
try {
|
||||
icon = ri.loadIcon(pm)
|
||||
} catch(ex : Throwable) {
|
||||
} catch (ex: Throwable) {
|
||||
log.e(ex, "loadIcon failed.")
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
} catch(ex : Throwable) {
|
||||
} catch (ex: Throwable) {
|
||||
log.e(ex, "getInfo failed.")
|
||||
}
|
||||
return Pair(label, icon)
|
||||
}
|
||||
|
||||
fun invoke(
|
||||
context : Context,
|
||||
text : String,
|
||||
target : CustomShareTarget
|
||||
context: Context,
|
||||
text: String,
|
||||
target: CustomShareTarget
|
||||
) {
|
||||
// convert "pkgName/className" string to ComponentName object.
|
||||
val cn = getCustomShareComponentName(App1.pref, target)
|
||||
if(cn == null) {
|
||||
if (cn == null) {
|
||||
context.showToast(true, R.string.custom_share_app_not_found)
|
||||
return
|
||||
}
|
||||
val cnStr = "${cn.packageName}/${cn.className}"
|
||||
if(cnStr == CN_CLIPBOARD) {
|
||||
if (cnStr == CN_CLIPBOARD) {
|
||||
try {
|
||||
val cm : ClipboardManager = systemService(context) !!
|
||||
val cm: ClipboardManager = systemService(context)!!
|
||||
cm.setPrimaryClip(ClipData.newPlainText("", text))
|
||||
context.showToast(false, R.string.copied_to_clipboard)
|
||||
} catch(ex : Throwable) {
|
||||
} catch (ex: Throwable) {
|
||||
context.showToast(ex, "copy to clipboard failed.")
|
||||
}
|
||||
return
|
||||
|
@ -126,10 +126,10 @@ object CustomShare {
|
|||
intent.putExtra(Intent.EXTRA_TEXT, text)
|
||||
intent.component = cn
|
||||
context.startActivity(intent)
|
||||
} catch(ex : ActivityNotFoundException) {
|
||||
} catch (ex: ActivityNotFoundException) {
|
||||
log.trace(ex)
|
||||
context.showToast(true, R.string.custom_share_app_not_found)
|
||||
} catch(ex : Throwable) {
|
||||
} catch (ex: Throwable) {
|
||||
log.trace(ex)
|
||||
context.showToast(ex, "invoke() failed.")
|
||||
}
|
||||
|
@ -137,23 +137,23 @@ object CustomShare {
|
|||
}
|
||||
|
||||
fun invoke(
|
||||
context : Context,
|
||||
access_info : SavedAccount,
|
||||
status : TootStatus?,
|
||||
target : CustomShareTarget
|
||||
context: Context,
|
||||
access_info: SavedAccount,
|
||||
status: TootStatus?,
|
||||
target: CustomShareTarget
|
||||
) {
|
||||
status ?: return
|
||||
try {
|
||||
// convert "pkgName/className" string to ComponentName object.
|
||||
val cn = getCustomShareComponentName(App1.pref, target)
|
||||
if(cn == null) {
|
||||
if (cn == null) {
|
||||
context.showToast(true, R.string.custom_share_app_not_found)
|
||||
return
|
||||
}
|
||||
|
||||
val sv = TootTextEncoder.encodeStatusForTranslate(context, access_info, status)
|
||||
invoke(context, sv, target)
|
||||
} catch(ex : Throwable) {
|
||||
} catch (ex: Throwable) {
|
||||
log.trace(ex)
|
||||
context.showToast(ex, "invoke() failed.")
|
||||
}
|
||||
|
@ -161,9 +161,9 @@ object CustomShare {
|
|||
|
||||
private val cache = HashMap<CustomShareTarget, Pair<CharSequence?, Drawable?>>()
|
||||
|
||||
fun getCache(target : CustomShareTarget) = cache[target]
|
||||
fun getCache(target: CustomShareTarget) = cache[target]
|
||||
|
||||
fun reloadCache(context : Context, pref : SharedPreferences) {
|
||||
fun reloadCache(context: Context, pref: SharedPreferences) {
|
||||
CustomShareTarget.values().forEach { target ->
|
||||
val cn = getCustomShareComponentName(pref, target)
|
||||
val pair = getInfo(context, cn)
|
||||
|
@ -173,12 +173,21 @@ object CustomShare {
|
|||
}
|
||||
|
||||
// convert "pkgName/className" string to ComponentName object.
|
||||
fun String.cn() : ComponentName? {
|
||||
fun String.cn(): ComponentName? {
|
||||
try {
|
||||
val idx = indexOf('/')
|
||||
if(idx >= 1) return ComponentName(substring(0 until idx), substring(idx + 1))
|
||||
} catch(ex : Throwable) {
|
||||
if (idx >= 1) return ComponentName(substring(0 until idx), substring(idx + 1))
|
||||
} catch (ex: Throwable) {
|
||||
CustomShare.log.e(ex, "incorrect component name $this")
|
||||
}
|
||||
return null
|
||||
}
|
||||
|
||||
fun ComponentName.exists(context: Context): Boolean {
|
||||
return try {
|
||||
context.packageManager.resolveActivity(Intent().apply { component = this@exists }, 0)
|
||||
?.activityInfo?.exported ?: false
|
||||
} catch (_: Throwable) {
|
||||
false
|
||||
}
|
||||
}
|
|
@ -1065,5 +1065,6 @@
|
|||
<string name="username_not_need_atmark">ユーザ名に@や/ を含めることはできません</string>
|
||||
<string name="speech">読み上げ</string>
|
||||
<string name="reset_notification_tracking_status">既読状態をリセット</string>
|
||||
<string name="web_browser">Webブラウザー</string>
|
||||
|
||||
</resources>
|
||||
|
|
|
@ -1076,4 +1076,5 @@
|
|||
<string name="toot_search_notestock_of">notestock search \"%1$s\"</string>
|
||||
<string name="update_push_subscription_not_force" translatable="false">Update push subscription(not force)</string>
|
||||
<string name="reset_notification_tracking_status">Reset notification tracking status</string>
|
||||
<string name="web_browser">Web browser</string>
|
||||
</resources>
|
||||
|
|
Loading…
Reference in New Issue