diff --git a/app/src/main/java/jp/juggler/subwaytooter/ActAbout.kt b/app/src/main/java/jp/juggler/subwaytooter/ActAbout.kt index 48d27a84..2cc3e1cf 100644 --- a/app/src/main/java/jp/juggler/subwaytooter/ActAbout.kt +++ b/app/src/main/java/jp/juggler/subwaytooter/ActAbout.kt @@ -9,17 +9,19 @@ import android.widget.Button import android.widget.LinearLayout import android.widget.TextView import androidx.appcompat.app.AppCompatActivity +import jp.juggler.subwaytooter.util.openBrowser import jp.juggler.util.LogCategory class ActAbout : AppCompatActivity() { class Translators( - val name:String, - val acct:String?, - val lang:String + val name : String, + val acct : String?, + val lang : String ) companion object { + val log = LogCategory("ActAbout") const val EXTRA_SEARCH = "search" @@ -33,22 +35,22 @@ class ActAbout : AppCompatActivity() { // git log --pretty=format:"%an %s" |grep "Translated using Weblate"|sort|uniq val translators = arrayOf( - Translators("Allan Nordhøy",null,"English & Norwegian Bokmål"), - Translators("ButterflyOfFire","@ButterflyOfFire@mstdn.fr", "Arabic & French"), - Translators("Ch",null,"Korean"), - Translators("Elizabeth Sherrock",null,"Chinese (Simplified)"), - Translators("Gennady Archangorodsky",null,"Hebrew"), - Translators("inqbs Siina",null,"Korean"), - Translators("Jeong Arm","@jarm@qdon.space","Korean"), - Translators("Joan Pujolar","@jpujolar@mastodont.cat","Catalan"), - Translators("Kai Zhang","@bearzk@mastodon.social","Chinese (Simplified)"), - Translators("lptprjh",null,"Korean"), - Translators("mynameismonkey",null,"Welsh"), - Translators("Nathan",null,"French"), - Translators("Owain Rhys Lewis",null,"Welsh"), - Translators("Swann Martinet",null,"French"), - Translators("takubunn",null,"Chinese (Simplified)"), - Translators("배태길",null,"Korea") + Translators("Allan Nordhøy", null, "English & Norwegian Bokmål"), + Translators("ButterflyOfFire", "@ButterflyOfFire@mstdn.fr", "Arabic & French"), + Translators("Ch", null, "Korean"), + Translators("Elizabeth Sherrock", null, "Chinese (Simplified)"), + Translators("Gennady Archangorodsky", null, "Hebrew"), + Translators("inqbs Siina", null, "Korean"), + Translators("Jeong Arm", "@jarm@qdon.space", "Korean"), + Translators("Joan Pujolar", "@jpujolar@mastodont.cat", "Catalan"), + Translators("Kai Zhang", "@bearzk@mastodon.social", "Chinese (Simplified)"), + Translators("lptprjh", null, "Korean"), + Translators("mynameismonkey", null, "Welsh"), + Translators("Nathan", null, "French"), + Translators("Owain Rhys Lewis", null, "Welsh"), + Translators("Swann Martinet", null, "French"), + Translators("takubunn", null, "Chinese (Simplified)"), + Translators("배태길", null, "Korea") ) } @@ -69,7 +71,7 @@ class ActAbout : AppCompatActivity() { log.trace(ex, "getPackageInfo failed.") } - fun setButton(btnId : Int, caption : String, onClick : () -> Unit ) { + fun setButton(btnId : Int, caption : String, onClick : () -> Unit) { val b : Button = findViewById(btnId) b.text = caption b.setOnClickListener { onClick() } @@ -80,9 +82,6 @@ class ActAbout : AppCompatActivity() { finish() } - fun openUrl(url : String) { - App1.openBrowser(this@ActAbout, url) - } setButton( R.id.btnDeveloper, @@ -94,10 +93,14 @@ class ActAbout : AppCompatActivity() { getString(R.string.search_for, official_acct) ) { searchAcct(official_acct) } + setButton(R.id.btnReleaseNote, url_release) + { openBrowser(url_release) } - setButton(R.id.btnReleaseNote, url_release) { openUrl(url_release) } - // setButton(R.id.btnIconDesign, url_futaba) { openUrl(url_futaba) } - setButton(R.id.btnWeblate, getString(R.string.please_help_translation) ) { openUrl(url_weblate) } + // setButton(R.id.btnIconDesign, url_futaba) + // { openUrl(url_futaba) } + + setButton(R.id.btnWeblate, getString(R.string.please_help_translation)) + { openBrowser(url_weblate) } val ll = findViewById(R.id.llContributors) val density = resources.displayMetrics.density @@ -117,7 +120,7 @@ class ActAbout : AppCompatActivity() { setBackgroundResource(R.drawable.btn_bg_transparent_round6dp) setPadding(padding, padding, padding, padding) isAllCaps = false - + // val acct = who.acct ?: "@?@?" text = "${who.name}\n$acct\n${getString(R.string.thanks_for, who.lang)}" diff --git a/app/src/main/java/jp/juggler/subwaytooter/ActAccountSetting.kt b/app/src/main/java/jp/juggler/subwaytooter/ActAccountSetting.kt index ba1439da..212e892a 100644 --- a/app/src/main/java/jp/juggler/subwaytooter/ActAccountSetting.kt +++ b/app/src/main/java/jp/juggler/subwaytooter/ActAccountSetting.kt @@ -262,7 +262,7 @@ class ActAccountSetting : AsyncActivity(), View.OnClickListener, Styler.fixHorizontalPadding(root) - setSwitchColor(this, pref, root) + setSwitchColor(pref, root) tvInstance = findViewById(R.id.tvInstance) tvUser = findViewById(R.id.tvUser) @@ -529,7 +529,7 @@ class ActAccountSetting : AsyncActivity(), View.OnClickListener, tvUserCustom.backgroundColor = ac.color_bg tvUserCustom.text = ac.nickname tvUserCustom.textColor = ac.color_fg.notZero() - ?: getAttributeColor(this, R.attr.colorTimeSmall) + ?: getAttributeColor(R.attr.colorTimeSmall) } private fun saveUIToData() { @@ -590,10 +590,7 @@ class ActAccountSetting : AsyncActivity(), View.OnClickListener, R.id.btnAccountRemove -> performAccountRemove() R.id.btnLoadPreference -> performLoadPreference() R.id.btnVisibility -> performVisibility() - R.id.btnOpenBrowser -> App1.openBrowser( - this@ActAccountSetting, - "https://${account.apiHost.ascii}/" - ) + R.id.btnOpenBrowser -> openBrowser("https://${account.apiHost.ascii}/") R.id.btnPushSubscription -> startTest() R.id.btnUserCustom -> ActNickname.open( @@ -694,7 +691,7 @@ class ActAccountSetting : AsyncActivity(), View.OnClickListener, val json = result.jsonObject if(json == null) { - showToast(this@ActAccountSetting, true, result.error) + showToast(true, result.error) return } @@ -745,7 +742,7 @@ class ActAccountSetting : AsyncActivity(), View.OnClickListener, .setPositiveButton(R.string.ok) { _, _ -> account.delete() - val pref = Pref.pref(this@ActAccountSetting) + val pref = pref() if(account.db_id == Pref.lpTabletTootDefaultAccount(pref)) { pref.edit().put(Pref.lpTabletTootDefaultAccount, - 1L).apply() } @@ -810,7 +807,7 @@ class ActAccountSetting : AsyncActivity(), View.OnClickListener, } error != null -> { - showToast(this@ActAccountSetting, true, error) + showToast(true, error) log.e("can't get oauth browser URL. $error") } } @@ -921,7 +918,7 @@ class ActAccountSetting : AsyncActivity(), View.OnClickListener, if(data != null) { showProfile(data) } else { - showToast(this@ActAccountSetting, true, result.error) + showToast(true, result.error) } } @@ -1248,7 +1245,7 @@ class ActAccountSetting : AsyncActivity(), View.OnClickListener, if(data != null) { showProfile(data) } else { - showToast(this@ActAccountSetting, true, result.error) + showToast(true, result.error) for(arg in args) { val key = arg.first val value = arg.second @@ -1401,7 +1398,7 @@ class ActAccountSetting : AsyncActivity(), View.OnClickListener, ) return } - showToast(this, true, R.string.missing_permission_to_access_media) + showToast(true, R.string.missing_permission_to_access_media) } override fun onRequestPermissionsResult( @@ -1413,7 +1410,7 @@ class ActAccountSetting : AsyncActivity(), View.OnClickListener, if(grantResults.isNotEmpty() && grantResults[0] == PackageManager.PERMISSION_GRANTED) { openPicker(requestCode) } else { - showToast(this, true, R.string.missing_permission_to_access_media) + showToast(true, R.string.missing_permission_to_access_media) } } } @@ -1424,7 +1421,7 @@ class ActAccountSetting : AsyncActivity(), View.OnClickListener, startActivityForResult(intent, request_code) } catch(ex : Throwable) { log.trace(ex, "performAttachment failed.") - showToast(this, ex, "performAttachment failed.") + showToast(ex, "performAttachment failed.") } } @@ -1446,7 +1443,7 @@ class ActAccountSetting : AsyncActivity(), View.OnClickListener, startActivityForResult(intent, request_code) } catch(ex : Throwable) { log.trace(ex, "opening camera app failed.") - showToast(this, ex, "opening camera app failed.") + showToast(ex, "opening camera app failed.") } } @@ -1483,7 +1480,7 @@ class ActAccountSetting : AsyncActivity(), View.OnClickListener, try { val cache_dir = externalCacheDir if(cache_dir == null) { - showToast(this, false, "getExternalCacheDir returns null.") + showToast(false, "getExternalCacheDir returns null.") break } @@ -1522,7 +1519,7 @@ class ActAccountSetting : AsyncActivity(), View.OnClickListener, } catch(ex : Throwable) { log.trace(ex, "Resizing image failed.") - showToast(this, ex, "Resizing image failed.") + showToast(ex, "Resizing image failed.") } break @@ -1549,12 +1546,12 @@ class ActAccountSetting : AsyncActivity(), View.OnClickListener, private fun addAttachment(request_code : Int, uri : Uri, mime_type : String?) { if(mime_type == null) { - showToast(this, false, "mime type is not provided.") + showToast(false, "mime type is not provided.") return } if(! mime_type.startsWith("image/")) { - showToast(this, false, "mime type is not image.") + showToast(false, "mime type is not image.") return } @@ -1583,7 +1580,7 @@ class ActAccountSetting : AsyncActivity(), View.OnClickListener, ) override fun background(client : TootApiClient) : TootApiResult? { - return wps.updateSubscription(client,true) + return wps.updateSubscription(client, true) } override fun handleResult(result : TootApiResult?) { diff --git a/app/src/main/java/jp/juggler/subwaytooter/ActAppSetting.kt b/app/src/main/java/jp/juggler/subwaytooter/ActAppSetting.kt index 3f1626c6..f27f808f 100644 --- a/app/src/main/java/jp/juggler/subwaytooter/ActAppSetting.kt +++ b/app/src/main/java/jp/juggler/subwaytooter/ActAppSetting.kt @@ -81,7 +81,7 @@ class ActAppSetting : AsyncActivity(), ColorPickerDialogListener, View.OnClickLi App1.setActivityTheme(this, noActionBar = true) this.handler = App1.getAppState(this).handler - this.pref = Pref.pref(this) + this.pref = pref() // val intent = this.intent // val layoutId = intent.getIntExtra(EXTRA_LAYOUT_ID, 0) @@ -373,7 +373,7 @@ class ActAppSetting : AsyncActivity(), ColorPickerDialogListener, View.OnClickLi val margin_tb = dip(6) setMargins(margin_lr, margin_tb, margin_lr, margin_tb) } - setBackgroundColor(getAttributeColor(context, R.attr.colorSettingDivider)) + setBackgroundColor(context.getAttributeColor(R.attr.colorSettingDivider)) }) } @@ -538,7 +538,7 @@ class ActAppSetting : AsyncActivity(), ColorPickerDialogListener, View.OnClickLi item.pref.cast() ?: error("$name has no boolean pref") showCaption(name) swSwitch.vg(false) // skip animation - setSwitchColor(activity, pref, swSwitch) + setSwitchColor(pref, swSwitch) swSwitch.isEnabled = item.enabled swSwitch.isChecked = bp(pref) swSwitch.vg(true) @@ -840,7 +840,7 @@ class ActAppSetting : AsyncActivity(), ColorPickerDialogListener, View.OnClickLi val intent = intentOpenDocument("*/*") startActivityForResult(intent, REQUEST_CODE_APP_DATA_IMPORT) } catch(ex : Throwable) { - showToast(this, ex, "importAppData(1) failed.") + showToast(ex, "importAppData(1) failed.") } } @@ -884,7 +884,7 @@ class ActAppSetting : AsyncActivity(), ColorPickerDialogListener, View.OnClickLi } fun setSwitchColor() = - setSwitchColor(this@ActAppSetting, pref, lvList) + setSwitchColor(pref, lvList) ////////////////////////////////////////////////////// @@ -955,7 +955,7 @@ class ActAppSetting : AsyncActivity(), ColorPickerDialogListener, View.OnClickLi private fun saveTimelineFont(uri : Uri?, file_name : String) : File? { try { if(uri == null) { - showToast(this, false, "missing uri.") + showToast(false, "missing uri.") return null } @@ -969,7 +969,7 @@ class ActAppSetting : AsyncActivity(), ColorPickerDialogListener, View.OnClickLi val source : InputStream? = contentResolver.openInputStream(uri) if(source == null) { - showToast(this, false, "openInputStream returns null. uri=%s", uri) + showToast(false, "openInputStream returns null. uri=%s", uri) return null } else { source.use { inStream -> @@ -981,20 +981,20 @@ class ActAppSetting : AsyncActivity(), ColorPickerDialogListener, View.OnClickLi val face = Typeface.createFromFile(tmp_file) if(face == null) { - showToast(this, false, "Typeface.createFromFile() failed.") + showToast(false, "Typeface.createFromFile() failed.") return null } val file = File(dir, file_name) if(! tmp_file.renameTo(file)) { - showToast(this, false, "File operation failed.") + showToast(false, "File operation failed.") return null } return file } catch(ex : Throwable) { log.trace(ex) - showToast(this, ex, "saveTimelineFont failed.") + showToast(ex, "saveTimelineFont failed.") return null } @@ -1177,10 +1177,10 @@ class ActAppSetting : AsyncActivity(), ColorPickerDialogListener, View.OnClickLi } ) { setCustomShare(target, it) } .show() - if(! rv) showToast(this, true, "share target app is not installed.") + if(! rv) showToast(true, "share target app is not installed.") } catch(ex : Throwable) { log.trace(ex) - showToast(this, ex, "openCustomShareChooser failed.") + showToast(ex, "openCustomShareChooser failed.") } } diff --git a/app/src/main/java/jp/juggler/subwaytooter/ActColumnCustomize.kt b/app/src/main/java/jp/juggler/subwaytooter/ActColumnCustomize.kt index 49b1c621..7372339c 100644 --- a/app/src/main/java/jp/juggler/subwaytooter/ActColumnCustomize.kt +++ b/app/src/main/java/jp/juggler/subwaytooter/ActColumnCustomize.kt @@ -33,6 +33,7 @@ import kotlin.math.max class ActColumnCustomize : AppCompatActivity(), View.OnClickListener, ColorPickerDialogListener { companion object { + internal val log = LogCategory("ActColumnCustomize") internal const val EXTRA_COLUMN_INDEX = "column_index" @@ -298,7 +299,7 @@ class ActColumnCustomize : AppCompatActivity(), View.OnClickListener, ColorPicke show() } - else -> showToast(this@ActColumnCustomize, true, result.error ?: "?") + else -> showToast(true, result.error ?: "?") } } }) @@ -395,18 +396,18 @@ class ActColumnCustomize : AppCompatActivity(), View.OnClickListener, ColorPicke } }) - etAlpha.setOnEditorActionListener{ _, actionId, _-> + etAlpha.setOnEditorActionListener { _, actionId, _ -> when(actionId) { EditorInfo.IME_ACTION_DONE -> { etAlpha.hideKeyboard() true } + else -> false } } } - private fun show() { try { loading_busy = true diff --git a/app/src/main/java/jp/juggler/subwaytooter/ActColumnList.kt b/app/src/main/java/jp/juggler/subwaytooter/ActColumnList.kt index d13f3f8e..94b840fc 100644 --- a/app/src/main/java/jp/juggler/subwaytooter/ActColumnList.kt +++ b/app/src/main/java/jp/juggler/subwaytooter/ActColumnList.kt @@ -21,6 +21,7 @@ import java.util.* class ActColumnList : AppCompatActivity() { companion object { + private val log = LogCategory("ActColumnList") internal const val TMP_FILE_COLUMN_LIST = "tmp_column_list" @@ -119,11 +120,7 @@ class ActColumnList : AppCompatActivity() { if(swipedDirection == ListSwipeItem.SwipeDirection.LEFT) { val adapterItem = item.tag as MyItem if(adapterItem.json.optBoolean(Column.KEY_DONT_CLOSE, false)) { - showToast( - this@ActColumnList, - false, - R.string.column_has_dont_close_option - ) + showToast(false, R.string.column_has_dont_close_option) listView.resetSwipedViews(null) return } @@ -203,7 +200,7 @@ class ActColumnList : AppCompatActivity() { val type = ColumnType.parse(json.optInt(Column.KEY_TYPE)) val acct_color_bg = json.optInt(Column.KEY_COLUMN_ACCESS_COLOR_BG, 0) val acct_color_fg = json.optInt(Column.KEY_COLUMN_ACCESS_COLOR, 0) - .notZero() ?: getAttributeColor(context, R.attr.colorColumnListItemText) + .notZero() ?: context.getAttributeColor(R.attr.colorColumnListItemText) var bOldSelection : Boolean = false fun setOldSelection(b : Boolean) { @@ -276,16 +273,14 @@ class ActColumnList : AppCompatActivity() { dragView.findViewById(R.id.ivBookmark).visibility = clickedView.findViewById(R.id.ivBookmark).visibility - dragView.findViewById(R.id.item_layout).setBackgroundColor( - getAttributeColor(this@ActColumnList, R.attr.list_item_bg_pressed_dragged) - ) + dragView.findViewById(R.id.item_layout) + .setBackgroundColor(getAttributeColor(R.attr.list_item_bg_pressed_dragged)) } } private inner class MyListAdapter : DragItemAdapter() { - init { setHasStableIds(true) itemList = ArrayList() diff --git a/app/src/main/java/jp/juggler/subwaytooter/ActFavMute.kt b/app/src/main/java/jp/juggler/subwaytooter/ActFavMute.kt index 8ae08bd4..36093556 100644 --- a/app/src/main/java/jp/juggler/subwaytooter/ActFavMute.kt +++ b/app/src/main/java/jp/juggler/subwaytooter/ActFavMute.kt @@ -171,9 +171,8 @@ class ActFavMute : AppCompatActivity() { dragView.findViewById(R.id.tvName).text = clickedView.findViewById(R.id.tvName).text - dragView.findViewById(R.id.item_layout).setBackgroundColor( - getAttributeColor(this@ActFavMute, R.attr.list_item_bg_pressed_dragged) - ) + dragView.findViewById(R.id.item_layout) + .setBackgroundColor(getAttributeColor(R.attr.list_item_bg_pressed_dragged)) } } diff --git a/app/src/main/java/jp/juggler/subwaytooter/ActHighlightWordEdit.kt b/app/src/main/java/jp/juggler/subwaytooter/ActHighlightWordEdit.kt index a7fd15ac..1857d71a 100644 --- a/app/src/main/java/jp/juggler/subwaytooter/ActHighlightWordEdit.kt +++ b/app/src/main/java/jp/juggler/subwaytooter/ActHighlightWordEdit.kt @@ -116,8 +116,8 @@ class ActHighlightWordEdit swSpeech = findViewById(R.id.swSpeech) swSpeech.setOnCheckedChangeListener(this) - setSwitchColor(this, App1.pref, swSound) - setSwitchColor(this, App1.pref, swSpeech) + setSwitchColor(App1.pref, swSound) + setSwitchColor(App1.pref, swSpeech) intArrayOf( R.id.btnTextColorEdit, @@ -142,7 +142,7 @@ class ActHighlightWordEdit tvName.text = item.name tvName.setBackgroundColor(item.color_bg) // may 0 tvName.textColor = item.color_fg.notZero() - ?: getAttributeColor(this, android.R.attr.textColorPrimary) + ?: getAttributeColor(android.R.attr.textColorPrimary) } finally { bBusy = false diff --git a/app/src/main/java/jp/juggler/subwaytooter/ActHighlightWordList.kt b/app/src/main/java/jp/juggler/subwaytooter/ActHighlightWordList.kt index d999eb1f..76747d35 100644 --- a/app/src/main/java/jp/juggler/subwaytooter/ActHighlightWordList.kt +++ b/app/src/main/java/jp/juggler/subwaytooter/ActHighlightWordList.kt @@ -136,7 +136,7 @@ class ActHighlightWordList : AppCompatActivity(), View.OnClickListener { val tvName : TextView private val btnSound : View - private val ivSpeech: ImageButton + private val ivSpeech : ImageButton init { @@ -160,15 +160,15 @@ class ActHighlightWordList : AppCompatActivity(), View.OnClickListener { tvName.setBackgroundColor(item.color_bg) tvName.setTextColor( item.color_fg.notZero() - ?: getAttributeColor(this@ActHighlightWordList, android.R.attr.textColorPrimary) + ?: getAttributeColor(android.R.attr.textColorPrimary) ) - btnSound.vg(item.sound_type != HighlightWord.SOUND_TYPE_NONE)?.apply{ + btnSound.vg(item.sound_type != HighlightWord.SOUND_TYPE_NONE)?.apply { setOnClickListener(this@MyViewHolder) tag = item } - ivSpeech.vg(item.speech != 0 )?.apply{ + ivSpeech.vg(item.speech != 0)?.apply { setOnClickListener(this@MyViewHolder) tag = item } @@ -189,12 +189,14 @@ class ActHighlightWordList : AppCompatActivity(), View.OnClickListener { override fun onClick(v : View) { val o = v.tag if(o is HighlightWord) { - when(v.id){ - R.id.btnSound->{ + when(v.id) { + R.id.btnSound -> { sound(o) } - R.id.ivSpeech->{ - App1.getAppState(this@ActHighlightWordList).addSpeech(o.name,dedupMode = DedupMode.None) + + R.id.ivSpeech -> { + App1.getAppState(this@ActHighlightWordList) + .addSpeech(o.name, dedupMode = DedupMode.None) } } } @@ -206,22 +208,18 @@ class ActHighlightWordList : AppCompatActivity(), View.OnClickListener { DragItem(context, layoutId) { override fun onBindDragView(clickedView : View, dragView : View) { - + dragView.findViewById(R.id.tvName).text = clickedView.findViewById(R.id.tvName).text - + dragView.findViewById(R.id.btnSound).visibility = clickedView.findViewById(R.id.btnSound).visibility - - dragView.findViewById(R.id.ivSpeech).visibility= + + dragView.findViewById(R.id.ivSpeech).visibility = clickedView.findViewById(R.id.ivSpeech).visibility - - dragView.findViewById(R.id.item_layout).setBackgroundColor( - getAttributeColor( - this@ActHighlightWordList, - R.attr.list_item_bg_pressed_dragged - ) - ) + + dragView.findViewById(R.id.item_layout) + .setBackgroundColor(getAttributeColor(R.attr.list_item_bg_pressed_dragged)) } } @@ -250,23 +248,27 @@ class ActHighlightWordList : AppCompatActivity(), View.OnClickListener { } private fun create() { - DlgTextInput.show(this, getString(R.string.new_item), "", callback = object : DlgTextInput.Callback { - override fun onEmptyError() { - showToast(this@ActHighlightWordList, true, R.string.word_empty) - } - - override fun onOK(dialog : Dialog, text : String) { - var item = HighlightWord.load(text) - if(item == null) { - item = HighlightWord(text) - item.save(this@ActHighlightWordList) - loadData() + DlgTextInput.show( + this, + getString(R.string.new_item), + "", + callback = object : DlgTextInput.Callback { + override fun onEmptyError() { + showToast(true, R.string.word_empty) } - edit(item) - dialog.dismissSafe() - } - }) + override fun onOK(dialog : Dialog, text : String) { + var item = HighlightWord.load(text) + if(item == null) { + item = HighlightWord(text) + item.save(this@ActHighlightWordList) + loadData() + } + edit(item) + + dialog.dismissSafe() + } + }) } private fun edit(item : HighlightWord) { diff --git a/app/src/main/java/jp/juggler/subwaytooter/ActKeywordFilter.kt b/app/src/main/java/jp/juggler/subwaytooter/ActKeywordFilter.kt index 943d3787..0d5c26a0 100644 --- a/app/src/main/java/jp/juggler/subwaytooter/ActKeywordFilter.kt +++ b/app/src/main/java/jp/juggler/subwaytooter/ActKeywordFilter.kt @@ -178,7 +178,7 @@ class ActKeywordFilter onLoadComplete(filter) } else { if(result != null) { - showToast(this@ActKeywordFilter, true, result.error ?: "?") + showToast(true, result.error ?: "?") } finish() } @@ -287,9 +287,9 @@ class ActKeywordFilter result ?: return val error = result.error if(error != null) { - showToast(this@ActKeywordFilter, true, result.error) + showToast(true, result.error) } else { - val app_state = App1.prepare(applicationContext,"ActKeywordFilter.save()") + val app_state = App1.prepare(applicationContext, "ActKeywordFilter.save()") for(column in app_state.column_list) { if(column.type == ColumnType.KEYWORD_FILTER && column.access_info == account) { column.filter_reload_required = true diff --git a/app/src/main/java/jp/juggler/subwaytooter/ActLanguageFilter.kt b/app/src/main/java/jp/juggler/subwaytooter/ActLanguageFilter.kt index 38f36cb2..35426e05 100644 --- a/app/src/main/java/jp/juggler/subwaytooter/ActLanguageFilter.kt +++ b/app/src/main/java/jp/juggler/subwaytooter/ActLanguageFilter.kt @@ -33,6 +33,7 @@ class ActLanguageFilter : AsyncActivity(), View.OnClickListener { ) companion object { + internal val log = LogCategory("ActLanguageFilter") internal const val EXTRA_COLUMN_INDEX = "column_index" @@ -240,7 +241,7 @@ class ActLanguageFilter : AsyncActivity(), View.OnClickListener { getString(if(item.allow) R.string.language_show else R.string.language_hide) ) tv.textColor = getAttributeColor( - this@ActLanguageFilter, when(item.allow) { + when(item.allow) { true -> R.attr.colorContentText false -> R.attr.colorRegexFilterError } @@ -310,6 +311,7 @@ class ActLanguageFilter : AsyncActivity(), View.OnClickListener { private object DlgLanguageFilter { interface Callback { + fun onOK(code : String, allow : Boolean) fun onDelete(code : String) } @@ -371,7 +373,7 @@ class ActLanguageFilter : AsyncActivity(), View.OnClickListener { btnPresets.setEnabledColor( activity, R.drawable.ic_edit, - getAttributeColor(activity, R.attr.colorVectorDrawable), + activity.getAttributeColor(R.attr.colorVectorDrawable), false ) } @@ -439,9 +441,8 @@ class ActLanguageFilter : AsyncActivity(), View.OnClickListener { val intent = intentOpenDocument("*/*") startActivityForResult(intent, REQUEST_CODE_IMPORT) } catch(ex : Throwable) { - showToast(this, ex, "import failed.") + showToast(ex, "import failed.") } - } override fun onActivityResult(requestCode : Int, resultCode : Int, data : Intent?) { @@ -460,7 +461,7 @@ class ActLanguageFilter : AsyncActivity(), View.OnClickListener { log.d("import2 type=${contentResolver.getType(uri)}") val source = contentResolver.openInputStream(uri) if(source == null) { - showToast( true, "openInputStream failed.") + showToast(true, "openInputStream failed.") null } else { source.use { inStream -> diff --git a/app/src/main/java/jp/juggler/subwaytooter/ActMain.kt b/app/src/main/java/jp/juggler/subwaytooter/ActMain.kt index e30169ad..af1ceaf8 100644 --- a/app/src/main/java/jp/juggler/subwaytooter/ActMain.kt +++ b/app/src/main/java/jp/juggler/subwaytooter/ActMain.kt @@ -176,41 +176,41 @@ class ActMain : AsyncActivity(), Column.Callback, View.OnClickListener, ////////////////////////////////////////////////////////////////// // 変更しない変数 - val follow_complete_callback : EmptyCallback = { - showToast(this@ActMain, false, R.string.follow_succeeded) + val follow_complete_callback : ()->Unit = { + showToast(false, R.string.follow_succeeded) } - val unfollow_complete_callback : EmptyCallback = { - showToast(this@ActMain, false, R.string.unfollow_succeeded) + val unfollow_complete_callback : ()->Unit = { + showToast(false, R.string.unfollow_succeeded) } - val cancel_follow_request_complete_callback : EmptyCallback = { - showToast(this@ActMain, false, R.string.follow_request_cancelled) + val cancel_follow_request_complete_callback : ()->Unit = { + showToast(false, R.string.follow_request_cancelled) } - val favourite_complete_callback : EmptyCallback = { - showToast(this@ActMain, false, R.string.favourite_succeeded) + val favourite_complete_callback : ()->Unit = { + showToast(false, R.string.favourite_succeeded) } - val unfavourite_complete_callback : EmptyCallback = { - showToast(this@ActMain, false, R.string.unfavourite_succeeded) + val unfavourite_complete_callback : ()->Unit = { + showToast(false, R.string.unfavourite_succeeded) } - val bookmark_complete_callback : EmptyCallback = { - showToast(this@ActMain, false, R.string.bookmark_succeeded) + val bookmark_complete_callback : ()->Unit = { + showToast(false, R.string.bookmark_succeeded) } - val unbookmark_complete_callback : EmptyCallback = { - showToast(this@ActMain, false, R.string.unbookmark_succeeded) + val unbookmark_complete_callback : ()->Unit = { + showToast(false, R.string.unbookmark_succeeded) } - val boost_complete_callback : EmptyCallback = { - showToast(this@ActMain, false, R.string.boost_succeeded) + val boost_complete_callback : ()->Unit = { + showToast(false, R.string.boost_succeeded) } - val unboost_complete_callback : EmptyCallback = { - showToast(this@ActMain, false, R.string.unboost_succeeded) + val unboost_complete_callback : ()->Unit = { + showToast(false, R.string.unboost_succeeded) } - val reaction_complete_callback : EmptyCallback = { - showToast(this@ActMain, false, R.string.reaction_succeeded) + val reaction_complete_callback : ()->Unit = { + showToast(false, R.string.reaction_succeeded) } // 相対時刻の表記を定期的に更新する @@ -566,7 +566,8 @@ class ActMain : AsyncActivity(), Column.Callback, View.OnClickListener, ItemViewHolder.toot_color_direct_me = Pref.ipTootColorDirectMe(pref) MyClickableSpan.showLinkUnderline = Pref.bpShowLinkUnderline(pref) MyClickableSpan.defaultLinkColor = Pref.ipLinkColor(pref).notZero() - ?: getAttributeColor(this, R.attr.colorLink) + ?: getAttributeColor(R.attr.colorLink) + CustomShare.reloadCache(this, pref) te = SystemClock.elapsedRealtime() @@ -1099,7 +1100,7 @@ class ActMain : AsyncActivity(), Column.Callback, View.OnClickListener, } if(resultCode == Activity.RESULT_OK && data != null) { - App1.openBrowser(this, data.data) + openBrowser(data.data) } else if(resultCode == ActAccountSetting.RESULT_INPUT_ACCESS_TOKEN && data != null) { val db_id = data.getLongExtra(ActAccountSetting.EXTRA_DB_ID, - 1L) checkAccessToken2(db_id) @@ -1195,7 +1196,7 @@ class ActMain : AsyncActivity(), Column.Callback, View.OnClickListener, ) { this@ActMain.finish() } else { - showToast(this@ActMain, false, R.string.missing_closeable_column) + showToast(false, R.string.missing_closeable_column) } } @@ -1205,7 +1206,6 @@ class ActMain : AsyncActivity(), Column.Callback, View.OnClickListener, else -> { showToast( - this@ActMain, false, R.string.cant_close_column_by_back_button_when_multiple_column_shown ) @@ -2048,28 +2048,25 @@ class ActMain : AsyncActivity(), Column.Callback, View.OnClickListener, // cancelled. } - error != null -> showToast( - this@ActMain, - true, - "${result.error} ${result.requestInfo}".trim() - ) + error != null -> + showToast(true, "${result.error} ${result.requestInfo}".trim()) - token_info == null -> showToast(this@ActMain, true, "can't get access token.") + token_info == null -> showToast(true, "can't get access token.") - jsonObject == null -> showToast(this@ActMain, true, "can't parse json response.") + jsonObject == null -> showToast(true, "can't parse json response.") // 自分のユーザネームを取れなかった // …普通はエラーメッセージが設定されてるはずだが - ta == null -> showToast(this@ActMain, true, "can't verify user credential.") + ta == null -> showToast(true, "can't verify user credential.") // アクセストークン更新時 // インスタンスは同じだと思うが、ユーザ名が異なる可能性がある sa != null -> if(sa.username != ta.username) { - showToast(this@ActMain, true, R.string.user_name_not_match) + showToast(true, R.string.user_name_not_match) } else { showToast( - this@ActMain, + false, R.string.access_token_updated_for, sa.acct.pretty @@ -2100,7 +2097,7 @@ class ActMain : AsyncActivity(), Column.Callback, View.OnClickListener, val apDomain = ti?.uri if(apDomain == null) { - showToast(this@ActMain, false, "Can't get ActivityPub domain name.") + showToast(false, "Can't get ActivityPub domain name.") return false } @@ -2138,7 +2135,7 @@ class ActMain : AsyncActivity(), Column.Callback, View.OnClickListener, } } - showToast(this@ActMain, false, R.string.account_confirmed) + showToast(false, R.string.account_confirmed) // 通知の更新が必要かもしれない PollingWorker.queueUpdateNotification(this@ActMain) @@ -2221,7 +2218,7 @@ class ActMain : AsyncActivity(), Column.Callback, View.OnClickListener, } override fun onEmptyError() { - showToast(this@ActMain, true, R.string.token_not_specified) + showToast(true, R.string.token_not_specified) } }) } @@ -2252,7 +2249,7 @@ class ActMain : AsyncActivity(), Column.Callback, View.OnClickListener, fun closeColumn(column : Column, bConfirmed : Boolean = false) { if(column.dont_close) { - showToast(this, false, R.string.column_has_dont_close_option) + showToast(false, R.string.column_has_dont_close_option) return } @@ -2452,9 +2449,9 @@ class ActMain : AsyncActivity(), Column.Callback, View.OnClickListener, when(fullAcct.host.ascii) { "github.com", "twitter.com" -> - App1.openCustomTab(this, mention.url) + openCustomTab(mention.url) "gmail.com" -> - App1.openBrowser(this, "mailto:${fullAcct.pretty}") + openBrowser("mailto:${fullAcct.pretty}") else -> Action_User.profile( @@ -2485,11 +2482,11 @@ class ActMain : AsyncActivity(), Column.Callback, View.OnClickListener, val instanceHost = Host.parse(instance) when(instanceHost.ascii) { "github.com", "twitter.com" -> { - App1.openCustomTab(this, "https://$instance/$user") + openCustomTab("https://$instance/$user") } "gmail.com" -> { - App1.openBrowser(this, "mailto:$user@$instance") + openBrowser("mailto:$user@$instance") } else -> { @@ -2535,7 +2532,7 @@ class ActMain : AsyncActivity(), Column.Callback, View.OnClickListener, } - App1.openCustomTab(this, opener.url) + openCustomTab(opener.url) } catch(ex : Throwable) { // warning.trace( ex ); @@ -2563,7 +2560,7 @@ class ActMain : AsyncActivity(), Column.Callback, View.OnClickListener, val footer_tab_indicator_color = Pref.ipFooterTabIndicatorColor(pref) val colorColumnStripBackground = footer_tab_bg_color.notZero() - ?: getAttributeColor(this, R.attr.colorColumnStripBackground) + ?: getAttributeColor(R.attr.colorColumnStripBackground) svColumnStrip.setBackgroundColor(colorColumnStripBackground) llQuickTootBar.setBackgroundColor(colorColumnStripBackground) @@ -2572,7 +2569,7 @@ class ActMain : AsyncActivity(), Column.Callback, View.OnClickListener, ?: colorColumnStripBackground val colorButtonFg = footer_button_fg_color.notZero() - ?: getAttributeColor(this, R.attr.colorRippleEffect) + ?: getAttributeColor(R.attr.colorRippleEffect) btnMenu.backgroundDrawable = getAdaptiveRippleDrawableRound(this, colorButtonBg, colorButtonFg) @@ -2585,7 +2582,7 @@ class ActMain : AsyncActivity(), Column.Callback, View.OnClickListener, val csl = ColorStateList.valueOf( footer_button_fg_color.notZero() - ?: getAttributeColor(this, R.attr.colorVectorDrawable) + ?: getAttributeColor(R.attr.colorVectorDrawable) ) btnToot.imageTintList = csl btnMenu.imageTintList = csl @@ -2598,7 +2595,7 @@ class ActMain : AsyncActivity(), Column.Callback, View.OnClickListener, vFooterDivider2.setBackgroundColor(c) llColumnStrip.indicatorColor = footer_tab_indicator_color.notZero() - ?: getAttributeColor(this, R.attr.colorAccent) + ?: getAttributeColor(R.attr.colorAccent) } ///////////////////////////////////////////////////////////////////////// @@ -2878,7 +2875,7 @@ class ActMain : AsyncActivity(), Column.Callback, View.OnClickListener, } catch(ex : Throwable) { log.trace(ex) if(zipEntryCount != 0) { - showToast(this@ActMain, ex, "importAppData failed.") + showToast(ex, "importAppData failed.") } } // zipではなかった場合、zipEntryがない状態になる。例外はPH-1では出なかったが、出ても問題ないようにする。 @@ -2914,7 +2911,7 @@ class ActMain : AsyncActivity(), Column.Callback, View.OnClickListener, PollingWorker.queueAppDataImportAfter(this@ActMain) } - showToast(this@ActMain, true, R.string.import_completed_please_restart_app) + showToast(true, R.string.import_completed_please_restart_app) finish() }, preProc = { diff --git a/app/src/main/java/jp/juggler/subwaytooter/ActMediaViewer.kt b/app/src/main/java/jp/juggler/subwaytooter/ActMediaViewer.kt index 88aa3877..4d83f6aa 100644 --- a/app/src/main/java/jp/juggler/subwaytooter/ActMediaViewer.kt +++ b/app/src/main/java/jp/juggler/subwaytooter/ActMediaViewer.kt @@ -107,9 +107,8 @@ class ActMediaViewer : AppCompatActivity(), View.OnClickListener { private lateinit var svDescription : View private lateinit var tvDescription : TextView private lateinit var tvStatus : TextView - private lateinit var cbMute: CheckBox - private var lastVolume = Float.NaN - + private lateinit var cbMute : CheckBox + private var lastVolume = Float.NaN internal var buffering_last_shown : Long = 0 @@ -149,7 +148,7 @@ class ActMediaViewer : AppCompatActivity(), View.OnClickListener { val now = SystemClock.elapsedRealtime() if(now - buffering_last_shown >= short_limit && exoPlayer.duration >= short_limit) { buffering_last_shown = now - showToast(this@ActMediaViewer, false, R.string.video_buffering) + showToast(false, R.string.video_buffering) } /* exoPlayer.getDuration() may returns negative value (TIME_UNSET ,same as Long.MIN_VALUE + 1). @@ -163,7 +162,7 @@ class ActMediaViewer : AppCompatActivity(), View.OnClickListener { override fun onPlayerError(error : ExoPlaybackException) { log.d("exoPlayer onPlayerError") - showToast(this@ActMediaViewer, error, "player error.") + showToast(error, "player error.") } override fun onPositionDiscontinuity(reason : Int) { @@ -187,7 +186,7 @@ class ActMediaViewer : AppCompatActivity(), View.OnClickListener { outState.putLong(STATE_PLAYER_POS, exoPlayer.currentPosition) outState.putBoolean(STATE_PLAYER_PLAY_WHEN_READY, exoPlayer.playWhenReady) - outState.putFloat(STATE_LAST_VOLUME,lastVolume) + outState.putFloat(STATE_LAST_VOLUME, lastVolume) } override fun onCreate(savedInstanceState : Bundle?) { @@ -252,14 +251,14 @@ class ActMediaViewer : AppCompatActivity(), View.OnClickListener { findViewById(R.id.btnDownload).setOnClickListener(this) findViewById(R.id.btnMore).setOnClickListener(this) - cbMute.setOnCheckedChangeListener{_,isChecked-> + cbMute.setOnCheckedChangeListener { _, isChecked -> if(isChecked) { // mute lastVolume = exoPlayer.volume exoPlayer.volume = 0f - }else{ + } else { // unmute - exoPlayer.volume = when{ + exoPlayer.volume = when { lastVolume.isNaN() -> 1f lastVolume <= 0f -> 1f else -> lastVolume @@ -361,7 +360,7 @@ class ActMediaViewer : AppCompatActivity(), View.OnClickListener { private fun loadVideo(ta : TootAttachment, state : Bundle? = null) { cbMute.vg(true) - if(cbMute.isChecked && lastVolume.isFinite() ) { + if(cbMute.isChecked && lastVolume.isFinite()) { exoPlayer.volume = 0f } @@ -399,7 +398,7 @@ class ActMediaViewer : AppCompatActivity(), View.OnClickListener { } else { exoPlayer.playWhenReady = state.getBoolean(STATE_PLAYER_PLAY_WHEN_READY, true) exoPlayer.seekTo(max(0L, state.getLong(STATE_PLAYER_POS, 0L))) - lastVolume = state.getFloat(STATE_LAST_VOLUME,1f) + lastVolume = state.getFloat(STATE_LAST_VOLUME, 1f) } } @@ -486,7 +485,7 @@ class ActMediaViewer : AppCompatActivity(), View.OnClickListener { @SuppressLint("StaticFieldLeak") private fun loadBitmap(ta : TootAttachment) { - cbMute.visibility=View.INVISIBLE + cbMute.visibility = View.INVISIBLE val urlList = ta.getLargeUrlList(App1.pref) if(urlList.isEmpty()) { @@ -546,7 +545,7 @@ class ActMediaViewer : AppCompatActivity(), View.OnClickListener { return Pair(null, "image size <= 0") } - val dstSize = rotateSize(orientation,srcWidth,srcHeight) + val dstSize = rotateSize(orientation, srcWidth, srcHeight) val dstSizeInt = Point( max(1, (dstSize.x + 0.5f).toInt()), max(1, (dstSize.y + 0.5f).toInt()) @@ -599,13 +598,13 @@ class ActMediaViewer : AppCompatActivity(), View.OnClickListener { ) : Pair { val result = TootApiResult.makeWithCaption(url) - val request = try{ + val request = try { Request.Builder() .url(url) .cacheControl(App1.CACHE_CONTROL) .addHeader("Accept", "image/webp,image/*,*/*;q=0.8") .build() - }catch(ex:Throwable){ + } catch(ex : Throwable) { result.setError(ex.withCaption("incorrect URL.")) return Pair(result, null) } @@ -667,7 +666,7 @@ class ActMediaViewer : AppCompatActivity(), View.OnClickListener { if(bitmap != null) { pbvImage.setBitmap(bitmap) } else if(result != null) { - showToast(this@ActMediaViewer, true, result.error) + showToast(true, result.error) } } }) @@ -684,7 +683,7 @@ class ActMediaViewer : AppCompatActivity(), View.OnClickListener { R.id.btnMore -> more(media_list[idx]) } } catch(ex : Throwable) { - showToast(this, ex, "action failed.") + showToast(ex, "action failed.") } } @@ -702,7 +701,7 @@ class ActMediaViewer : AppCompatActivity(), View.OnClickListener { return } - val downLoadManager :DownloadManager = systemService(this) + val downLoadManager : DownloadManager = systemService(this) ?: error("missing DownloadManager system service") val url = if(ta is TootAttachment) { @@ -724,7 +723,7 @@ class ActMediaViewer : AppCompatActivity(), View.OnClickListener { it.remove() } else if(url == dh.url) { // 履歴に同じURLがあればエラーとする - showToast(this, false, R.string.dont_repeat_download_to_same_url) + showToast(false, R.string.dont_repeat_download_to_same_url) return } } @@ -773,7 +772,7 @@ class ActMediaViewer : AppCompatActivity(), View.OnClickListener { request.setNotificationVisibility(DownloadManager.Request.VISIBILITY_VISIBLE_NOTIFY_COMPLETED) downLoadManager.enqueue(request) - showToast(this, false, R.string.downloading) + showToast(false, R.string.downloading) } private fun share(action : String, url : String) { @@ -790,7 +789,7 @@ class ActMediaViewer : AppCompatActivity(), View.OnClickListener { startActivity(intent) } catch(ex : Throwable) { - showToast(this, ex, "can't open app.") + showToast(ex, "can't open app.") } } @@ -812,10 +811,10 @@ class ActMediaViewer : AppCompatActivity(), View.OnClickListener { //クリップボードにデータを格納 cm.setPrimaryClip(cd) - showToast(this, false, R.string.url_is_copied) + showToast(false, R.string.url_is_copied) } catch(ex : Throwable) { - showToast(this, ex, "clipboard access failed.") + showToast(ex, "clipboard access failed.") } } @@ -862,7 +861,7 @@ class ActMediaViewer : AppCompatActivity(), View.OnClickListener { intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK) startActivity(intent) } catch(ex : Throwable) { - showToast(this@ActMediaViewer, ex, "can't open app.") + showToast(ex, "can't open app.") } } } @@ -873,7 +872,7 @@ class ActMediaViewer : AppCompatActivity(), View.OnClickListener { this, arrayOf(Manifest.permission.WRITE_EXTERNAL_STORAGE), PERMISSION_REQUEST_CODE ) } else { - showToast(this, true, R.string.missing_permission_to_access_media) + showToast(true, R.string.missing_permission_to_access_media) } } @@ -892,7 +891,7 @@ class ActMediaViewer : AppCompatActivity(), View.OnClickListener { ++ i } if(bNotGranted) { - showToast(this, true, R.string.missing_permission_to_access_media) + showToast(true, R.string.missing_permission_to_access_media) } else { download(media_list[idx]) } diff --git a/app/src/main/java/jp/juggler/subwaytooter/ActMutedApp.kt b/app/src/main/java/jp/juggler/subwaytooter/ActMutedApp.kt index 5f180075..911e9c63 100644 --- a/app/src/main/java/jp/juggler/subwaytooter/ActMutedApp.kt +++ b/app/src/main/java/jp/juggler/subwaytooter/ActMutedApp.kt @@ -19,6 +19,7 @@ import com.woxthebox.draglistview.swipe.ListSwipeItem class ActMutedApp : AppCompatActivity() { companion object { + private val log = LogCategory("ActMutedApp") } @@ -168,9 +169,8 @@ class ActMutedApp : AppCompatActivity() { dragView.findViewById(R.id.tvName).text = clickedView.findViewById(R.id.tvName).text - dragView.findViewById(R.id.item_layout).setBackgroundColor( - getAttributeColor(this@ActMutedApp, R.attr.list_item_bg_pressed_dragged) - ) + dragView.findViewById(R.id.item_layout) + .setBackgroundColor(getAttributeColor(R.attr.list_item_bg_pressed_dragged)) } } diff --git a/app/src/main/java/jp/juggler/subwaytooter/ActMutedPseudoAccount.kt b/app/src/main/java/jp/juggler/subwaytooter/ActMutedPseudoAccount.kt index 0f63fe5a..bc6457bd 100644 --- a/app/src/main/java/jp/juggler/subwaytooter/ActMutedPseudoAccount.kt +++ b/app/src/main/java/jp/juggler/subwaytooter/ActMutedPseudoAccount.kt @@ -19,6 +19,7 @@ import java.util.* class ActMutedPseudoAccount : AppCompatActivity() { companion object { + private val log = LogCategory("ActMutedPseudoAccount") } @@ -167,9 +168,8 @@ class ActMutedPseudoAccount : AppCompatActivity() { dragView.findViewById(R.id.tvName).text = clickedView.findViewById(R.id.tvName).text - dragView.findViewById(R.id.item_layout).setBackgroundColor( - getAttributeColor(this@ActMutedPseudoAccount, R.attr.list_item_bg_pressed_dragged) - ) + dragView.findViewById(R.id.item_layout) + .setBackgroundColor(getAttributeColor(R.attr.list_item_bg_pressed_dragged)) } } diff --git a/app/src/main/java/jp/juggler/subwaytooter/ActMutedWord.kt b/app/src/main/java/jp/juggler/subwaytooter/ActMutedWord.kt index 04e11b17..5db40851 100644 --- a/app/src/main/java/jp/juggler/subwaytooter/ActMutedWord.kt +++ b/app/src/main/java/jp/juggler/subwaytooter/ActMutedWord.kt @@ -168,9 +168,8 @@ class ActMutedWord : AppCompatActivity() { dragView.findViewById(R.id.tvName).text = clickedView.findViewById(R.id.tvName).text - dragView.findViewById(R.id.item_layout).setBackgroundColor( - getAttributeColor(this@ActMutedWord, R.attr.list_item_bg_pressed_dragged) - ) + dragView.findViewById(R.id.item_layout) + .setBackgroundColor(getAttributeColor(R.attr.list_item_bg_pressed_dragged)) } } diff --git a/app/src/main/java/jp/juggler/subwaytooter/ActNickname.kt b/app/src/main/java/jp/juggler/subwaytooter/ActNickname.kt index dcf022ee..2a108a90 100644 --- a/app/src/main/java/jp/juggler/subwaytooter/ActNickname.kt +++ b/app/src/main/java/jp/juggler/subwaytooter/ActNickname.kt @@ -155,7 +155,7 @@ class ActNickname : AppCompatActivity(), View.OnClickListener, ColorPickerDialog tvAcct.text = acctPretty - val ac = AcctColor.load(acctAscii,acctPretty) + val ac = AcctColor.load(acctAscii, acctPretty) color_bg = ac.color_bg color_fg = ac.color_fg etNickname.setText(ac.nickname) @@ -180,7 +180,7 @@ class ActNickname : AppCompatActivity(), View.OnClickListener, ColorPickerDialog private fun show() { val s = etNickname.text.toString().trim { it <= ' ' } tvPreview.text = s.notEmpty() ?: acctPretty - tvPreview.textColor = color_fg.notZero() ?: getAttributeColor(this, R.attr.colorTimeSmall) + tvPreview.textColor = color_fg.notZero() ?: getAttributeColor(R.attr.colorTimeSmall) tvPreview.backgroundColor = color_bg } diff --git a/app/src/main/java/jp/juggler/subwaytooter/ActPost.kt b/app/src/main/java/jp/juggler/subwaytooter/ActPost.kt index 9bfef906..31e9cf61 100644 --- a/app/src/main/java/jp/juggler/subwaytooter/ActPost.kt +++ b/app/src/main/java/jp/juggler/subwaytooter/ActPost.kt @@ -493,7 +493,7 @@ class ActPost : AsyncActivity(), private var mushroom_end : Int = 0 private val link_click_listener : (View, MyClickableSpan) -> Unit = { _, span -> - App1.openBrowser(this@ActPost, span.linkInfo.url) + openBrowser(span.linkInfo.url) } //////////////////////////////////////////////////////////////// @@ -557,7 +557,7 @@ class ActPost : AsyncActivity(), if(uri != null) { addAttachment(uri) } else { - showToast(this@ActPost, false, "missing image uri") + showToast(false, "missing image uri") } } @@ -612,7 +612,7 @@ class ActPost : AsyncActivity(), } if(account_list.isEmpty()) { - showToast(this, true, R.string.please_add_account) + showToast(true, R.string.please_add_account) finish() return } @@ -1413,7 +1413,6 @@ class ActPost : AsyncActivity(), tvCharCount.text = remain.toString() tvCharCount.setTextColor( getAttributeColor( - this, if(remain < 0) R.attr.colorRegexFilterError else @@ -1495,7 +1494,7 @@ class ActPost : AsyncActivity(), if(a == null) { btnAccount.text = getString(R.string.not_selected) - btnAccount.setTextColor(getAttributeColor(this, android.R.attr.textColorPrimary)) + btnAccount.setTextColor(getAttributeColor(android.R.attr.textColorPrimary)) btnAccount.setBackgroundResource(R.drawable.btn_bg_transparent_round6dp) } else { @@ -1515,7 +1514,7 @@ class ActPost : AsyncActivity(), } btnAccount.textColor = ac.color_fg.notZero() - ?: getAttributeColor(this, android.R.attr.textColorPrimary) + ?: getAttributeColor(android.R.attr.textColorPrimary) } updateTextCount() updateFeaturedTags() @@ -1525,19 +1524,19 @@ class ActPost : AsyncActivity(), if(scheduledStatus != null) { // 予約投稿の再編集ではアカウントを切り替えられない - showToast(this, false, R.string.cant_change_account_when_editing_scheduled_status) + showToast(false, R.string.cant_change_account_when_editing_scheduled_status) return } if(attachment_list.isNotEmpty()) { // 添付ファイルがあったら確認の上添付ファイルを捨てないと切り替えられない - showToast(this, false, R.string.cant_change_account_when_attachment_specified) + showToast(false, R.string.cant_change_account_when_attachment_specified) return } if(redraft_status_id != null) { // 添付ファイルがあったら確認の上添付ファイルを捨てないと切り替えられない - showToast(this, false, R.string.cant_change_account_when_redraft) + showToast(false, R.string.cant_change_account_when_redraft) return } @@ -1598,7 +1597,7 @@ class ActPost : AsyncActivity(), selectAccount(a) try { if(TootVisibility.isVisibilitySpoilRequired(this.visibility, a.visibility)) { - showToast(this@ActPost, true, R.string.spoil_visibility_for_account) + showToast(true, R.string.spoil_visibility_for_account) this.visibility = a.visibility } @@ -1644,7 +1643,6 @@ class ActPost : AsyncActivity(), setAccountWithVisibilityConversion(access_info) } else { showToast( - this@ActPost, true, getString(R.string.in_reply_to_id_conversion_failed) + "\n" + result.error ) @@ -1701,7 +1699,7 @@ class ActPost : AsyncActivity(), val pa = try { attachment_list[idx] } catch(ex : Throwable) { - showToast(this, false, ex.withCaption("can't get attachment item[$idx].")) + showToast(false, ex.withCaption("can't get attachment item[$idx].")) return } @@ -1771,7 +1769,7 @@ class ActPost : AsyncActivity(), if(new_attachment != null) { pa.attachment = attachment } else { - showToast(this@ActPost, true, result.error) + showToast(true, result.error) } } }) @@ -1798,7 +1796,7 @@ class ActPost : AsyncActivity(), startActivityForResult(intent, REQUEST_CODE_CUSTOM_THUMBNAIL) } catch(ex : Throwable) { log.trace(ex) - showToast(this, ex, "ACTION_GET_CONTENT failed.") + showToast(ex, "ACTION_GET_CONTENT failed.") } } @@ -1809,19 +1807,19 @@ class ActPost : AsyncActivity(), val account = this@ActPost.account if(account == null) { - showToast(this, false, R.string.account_select_please) + showToast(false, R.string.account_select_please) return } val mime_type = getMimeType(src.uri, src.mimeType) if(mime_type?.isEmpty() != false) { - showToast(this, false, R.string.mime_type_missing) + showToast(false, R.string.mime_type_missing) return } val pa = lastPostAttachment if(pa == null || ! attachment_list.contains(pa)) { - showToast(this, true, "lost attachment information") + showToast(true, "lost attachment information") return } @@ -1922,7 +1920,7 @@ class ActPost : AsyncActivity(), override fun handleResult(result : TootApiResult?) { showMediaAttachment() - result?.error?.let { showToast(this@ActPost, true, it) } + result?.error?.let { showToast(true, it) } } }) } @@ -1946,7 +1944,7 @@ class ActPost : AsyncActivity(), private fun editAttachmentDescription(pa : PostAttachment) { val a = pa.attachment if(a == null) { - showToast(this, true, R.string.attachment_description_cant_edit_while_uploading) + showToast(true, R.string.attachment_description_cant_edit_while_uploading) return } @@ -1960,7 +1958,7 @@ class ActPost : AsyncActivity(), } override fun onEmptyError() { - showToast(this@ActPost, true, R.string.description_empty) + showToast(true, R.string.description_empty) } }) } @@ -1998,7 +1996,7 @@ class ActPost : AsyncActivity(), dialog.dismissSafe() } else { - showToast(this@ActPost, true, result.error) + showToast(true, result.error) } } }) @@ -2007,12 +2005,12 @@ class ActPost : AsyncActivity(), private fun openAttachment() { if(attachment_list.size >= 4) { - showToast(this, false, R.string.attachment_too_many) + showToast(false, R.string.attachment_too_many) return } if(account == null) { - showToast(this, false, R.string.account_select_please) + showToast(false, R.string.account_select_please) return } @@ -2068,7 +2066,7 @@ class ActPost : AsyncActivity(), startActivityForResult(intent, REQUEST_CODE_ATTACHMENT_OLD) } catch(ex : Throwable) { log.trace(ex) - showToast(this, ex, "ACTION_GET_CONTENT failed.") + showToast(ex, "ACTION_GET_CONTENT failed.") } } @@ -2109,7 +2107,7 @@ class ActPost : AsyncActivity(), try { val cache_dir = externalCacheDir if(cache_dir == null) { - showToast(this, false, "getExternalCacheDir returns null.") + showToast(false, "getExternalCacheDir returns null.") break } @@ -2145,7 +2143,7 @@ class ActPost : AsyncActivity(), } catch(ex : Throwable) { log.trace(ex) - showToast(this, ex, "Resizing image failed.") + showToast(ex, "Resizing image failed.") } break @@ -2219,35 +2217,35 @@ class ActPost : AsyncActivity(), ) { if(attachment_list.size >= 4) { - showToast(this, false, R.string.attachment_too_many) + showToast(false, R.string.attachment_too_many) return } val account = this@ActPost.account if(account == null) { - showToast(this, false, R.string.account_select_please) + showToast(false, R.string.account_select_please) return } val mime_type = getMimeType(uri, mimeTypeArg) if(mime_type?.isEmpty() != false) { - showToast(this, false, R.string.mime_type_missing) + showToast(false, R.string.mime_type_missing) return } val instance = TootInstance.getCached(account.apiHost.ascii) if(instance?.instanceType == TootInstance.InstanceType.Pixelfed) { if(in_reply_to_id != null) { - showToast(this, true, R.string.pixelfed_does_not_allow_reply_with_media) + showToast(true, R.string.pixelfed_does_not_allow_reply_with_media) return } if(! acceptable_mime_types_pixelfed.contains(mime_type)) { - showToast(this, true, R.string.mime_type_not_acceptable, mime_type) + showToast(true, R.string.mime_type_not_acceptable, mime_type) return } } else { if(! acceptable_mime_types.contains(mime_type)) { - showToast(this, true, R.string.mime_type_not_acceptable, mime_type) + showToast(true, R.string.mime_type_not_acceptable, mime_type) return } } @@ -2261,7 +2259,7 @@ class ActPost : AsyncActivity(), // アップロード開始トースト(連発しない) val now = System.currentTimeMillis() if(now - lastAttachmentAdd >= 5000L) { - showToast(this, false, R.string.attachment_uploading) + showToast(false, R.string.attachment_uploading) } lastAttachmentAdd = now @@ -2547,7 +2545,6 @@ class ActPost : AsyncActivity(), pa.status = PostAttachment.STATUS_UPLOAD_FAILED if(result != null) { showToast( - this@ActPost, true, "${result.error} ${result.response?.request?.method} ${result.response?.request?.url}" ) @@ -2581,7 +2578,7 @@ class ActPost : AsyncActivity(), val now = System.currentTimeMillis() if(now - lastAttachmentComplete >= 5000L) { - showToast(this@ActPost, false, R.string.attachment_uploaded) + showToast(false, R.string.attachment_uploaded) } lastAttachmentComplete = now @@ -2626,7 +2623,7 @@ class ActPost : AsyncActivity(), startActivityForResult(intent, REQUEST_CODE_CAMERA) } catch(ex : Throwable) { log.trace(ex) - showToast(this, ex, "opening camera app failed.") + showToast(ex, "opening camera app failed.") } } @@ -2636,7 +2633,7 @@ class ActPost : AsyncActivity(), startActivityForResult(Intent(action), requestCode) } catch(ex : Throwable) { log.trace(ex) - showToast(this, ex, errorCaption) + showToast(ex, errorCaption) } } @@ -2648,7 +2645,7 @@ class ActPost : AsyncActivity(), PERMISSION_REQUEST_CODE ) } else { - showToast(this, true, R.string.missing_permission_to_access_media) + showToast(true, R.string.missing_permission_to_access_media) } } @@ -2667,7 +2664,7 @@ class ActPost : AsyncActivity(), ++ i } if(bNotGranted) { - showToast(this, true, R.string.missing_permission_to_access_media) + showToast(true, R.string.missing_permission_to_access_media) } else { openAttachment() } @@ -2763,7 +2760,7 @@ class ActPost : AsyncActivity(), // アップロード中は投稿できない for(pa in attachment_list) { if(pa.status == PostAttachment.STATUS_UPLOADING) { - showToast(this, false, R.string.media_attachment_still_uploading) + showToast(false, R.string.media_attachment_still_uploading) return } } @@ -2850,7 +2847,7 @@ class ActPost : AsyncActivity(), } override fun onScheduledPostComplete(target_account : SavedAccount) { - showToast(this@ActPost, false, getString(R.string.scheduled_status_sent)) + showToast(false, getString(R.string.scheduled_status_sent)) val data = Intent() data.putExtra(EXTRA_POSTED_ACCT, target_account.acct.ascii) setResult(RESULT_OK, data) diff --git a/app/src/main/java/jp/juggler/subwaytooter/ActText.kt b/app/src/main/java/jp/juggler/subwaytooter/ActText.kt index 6395cad5..f74bc68d 100644 --- a/app/src/main/java/jp/juggler/subwaytooter/ActText.kt +++ b/app/src/main/java/jp/juggler/subwaytooter/ActText.kt @@ -161,7 +161,7 @@ class ActText : AppCompatActivity(), View.OnClickListener { } catch(ex : Throwable) { log.trace(ex) - showToast(this, ex, "send failed.") + showToast(ex, "send failed.") } } @@ -169,7 +169,7 @@ class ActText : AppCompatActivity(), View.OnClickListener { private fun search() { val sv = selection if(sv.isEmpty()) { - showToast(this, false, "please select search keyword") + showToast(false, "please select search keyword") return } try { @@ -180,7 +180,7 @@ class ActText : AppCompatActivity(), View.OnClickListener { } } catch(ex : Throwable) { log.trace(ex) - showToast(this, ex, "search failed.") + showToast(ex, "search failed.") } } @@ -188,7 +188,7 @@ class ActText : AppCompatActivity(), View.OnClickListener { private fun searchToot(@Suppress("SameParameterValue") resultCode : Int) { val sv = selection if(sv.isEmpty()) { - showToast(this, false, "please select search keyword") + showToast(false, "please select search keyword") return } try { @@ -206,10 +206,10 @@ class ActText : AppCompatActivity(), View.OnClickListener { try { MutedWord.save(selection) App1.getAppState(this).onMuteUpdated() - showToast(this, false, R.string.word_was_muted) + showToast(false, R.string.word_was_muted) } catch(ex : Throwable) { log.trace(ex) - showToast(this, ex, "muteWord failed.") + showToast(ex, "muteWord failed.") } } diff --git a/app/src/main/java/jp/juggler/subwaytooter/App1.kt b/app/src/main/java/jp/juggler/subwaytooter/App1.kt index 87f642ab..49b47ce5 100644 --- a/app/src/main/java/jp/juggler/subwaytooter/App1.kt +++ b/app/src/main/java/jp/juggler/subwaytooter/App1.kt @@ -3,27 +3,14 @@ package jp.juggler.subwaytooter import android.annotation.SuppressLint import android.app.Activity import android.app.Application -import android.content.ComponentName import android.content.Context -import android.content.Intent import android.content.SharedPreferences -import android.content.pm.PackageManager -import android.content.pm.ResolveInfo -import android.content.res.ColorStateList import android.database.sqlite.SQLiteDatabase import android.database.sqlite.SQLiteOpenHelper -import android.graphics.Color -import android.net.Uri import android.os.Build -import android.os.Bundle import android.os.Handler import android.util.Log -import android.view.View -import android.view.WindowInsetsController -import android.view.WindowManager import androidx.appcompat.app.AppCompatActivity -import androidx.appcompat.widget.SwitchCompat -import androidx.browser.customtabs.CustomTabsIntent import com.bumptech.glide.Glide import com.bumptech.glide.GlideBuilder import com.bumptech.glide.Registry @@ -32,13 +19,10 @@ import com.bumptech.glide.load.engine.cache.InternalCacheDiskCacheFactory import com.bumptech.glide.load.engine.executor.GlideExecutor import com.bumptech.glide.load.model.GlideUrl import jp.juggler.subwaytooter.api.TootApiClient -import jp.juggler.subwaytooter.api.entity.TootAttachment -import jp.juggler.subwaytooter.dialog.DlgAppPicker import jp.juggler.subwaytooter.table.* import jp.juggler.subwaytooter.util.CustomEmojiCache import jp.juggler.subwaytooter.util.CustomEmojiLister import jp.juggler.subwaytooter.util.ProgressResponseBody -import jp.juggler.subwaytooter.util.cn import jp.juggler.util.* import okhttp3.* import org.conscrypt.Conscrypt @@ -51,7 +35,6 @@ import java.security.Security import java.util.* import java.util.concurrent.TimeUnit import kotlin.math.max -import kotlin.math.pow class App1 : Application() { @@ -315,7 +298,7 @@ class App1 : Application() { initializeFont() - pref = Pref.pref(app_context) + pref = app_context.pref() run { @@ -518,7 +501,7 @@ class App1 : Application() { } fun setActivityTheme( - activity : Activity, + activity : AppCompatActivity, noActionBar : Boolean = false, forceDark : Boolean = false ) { @@ -534,7 +517,7 @@ class App1 : Application() { } ) - setStatusBarColor(activity, forceDark = forceDark) + activity.setStatusBarColor(forceDark = forceDark) } internal val CACHE_CONTROL = CacheControl.Builder() @@ -610,147 +593,6 @@ class App1 : Application() { } - // returns true if activity is opened. - // returns false if fallback required - private fun startActivityExcludeMyApp( - activity : AppCompatActivity, - intent : Intent, - startAnimationBundle : Bundle? = null - ) : Boolean { - try { - val pm = activity.packageManager !! - val myName = activity.packageName - - val filter : (ResolveInfo) -> Boolean = { - it.activityInfo.packageName != myName && - it.activityInfo.exported && - - 1 == it.activityInfo.packageName.indexOf("com.huawei.android.internal") - } - - // resolveActivity がこのアプリ以外のActivityを返すなら、それがベストなんだろう - // ただしAndroid M以降はMATCH_DEFAULT_ONLYだと「常時」が設定されてないとnullを返す - val ri = pm.resolveActivity( - intent, - if(Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) { - PackageManager.MATCH_ALL - } else { - PackageManager.MATCH_DEFAULT_ONLY - } - )?.takeIf(filter) - - if(ri != null) { - intent.setClassName(ri.activityInfo.packageName, ri.activityInfo.name) - activity.startActivity(intent, startAnimationBundle) - return true - } - - return DlgAppPicker( - activity, - intent, - autoSelect = true, - filter = filter - ) { - try { - intent.component = it.cn() - activity.startActivity(intent, startAnimationBundle) - } catch(ex : Throwable) { - log.trace(ex) - showToast(activity, ex, "can't open. ${intent.data}") - } - }.show() - - } catch(ex : Throwable) { - log.trace(ex) - showToast(activity, ex, "can't open. ${intent.data}") - return true // fallback not required in this case - } - } - - fun openBrowser(activity : AppCompatActivity, uri : Uri?) { - if(uri != null) { - val rv = startActivityExcludeMyApp(activity, Intent(Intent.ACTION_VIEW, uri)) - if(! rv) showToast(activity, true, "there is no app that can open $uri") - } - } - - fun openBrowser(activity : AppCompatActivity, url : String?) = - openBrowser(activity, url.mayUri()) - - // ubway Tooterの「アプリ設定/挙動/リンクを開く際にCustom Tabsを使わない」をONにして - // 投稿のコンテキストメニューの「トゥートへのアクション/Webページを開く」「ユーザへのアクション/Webページを開く」を使うと - // 投げたインテントをST自身が受け取って「次のアカウントから開く」ダイアログが出て - // 「Webページを開く」をまた押すと無限ループしてダイアログの影が徐々に濃くなりそのうち壊れる - // これを避けるには、投稿やトゥートを開く際に bpDontUseCustomTabs がオンならST以外のアプリを列挙したアプリ選択ダイアログを出すしかない - fun openCustomTabOrBrowser(activity : AppCompatActivity, url : String) { - if(! Pref.bpDontUseCustomTabs(pref)) { - openCustomTab(activity, url) - } else { - openBrowser(activity, url) - } - } - - // Chrome Custom Tab を開く - fun openCustomTab(activity : AppCompatActivity, url : String) { - if(Pref.bpDontUseCustomTabs(pref)) { - openCustomTabOrBrowser(activity, url) - return - } - - try { - if(url.startsWith("http") && Pref.bpPriorChrome(pref)) { - try { - // 初回はChrome指定で試す - val customTabsIntent = CustomTabsIntent.Builder() - .setToolbarColor(getAttributeColor(activity, R.attr.colorPrimary)) - .setShowTitle(true) - .build() - - val rv = startActivityExcludeMyApp( - activity, - customTabsIntent.intent.also { - it.component = ComponentName( - "com.android.chrome", - "com.google.android.apps.chrome.Main" - ) - it.data = url.toUri() - }, - customTabsIntent.startAnimationBundle - ) - if(rv) return - } catch(ex2 : Throwable) { - log.e(ex2, "openChromeTab: missing chrome. retry to other application.") - } - } - - // Chromeがないようなのでcomponent指定なしでリトライ - val customTabsIntent = CustomTabsIntent.Builder() - .setToolbarColor(getAttributeColor(activity, R.attr.colorPrimary)) - .setShowTitle(true) - .build() - - val rv = startActivityExcludeMyApp( - activity, - customTabsIntent.intent.also { - it.data = url.toUri() - }, - customTabsIntent.startAnimationBundle - ) - if(! rv) { - showToast(activity, true, "the browser app is not installed.") - } - - } catch(ex : Throwable) { - log.trace(ex) - val scheme = url.mayUri()?.scheme ?: url - showToast(activity, true, "can't open browser app for %s", scheme) - } - } - - fun openCustomTab(activity : AppCompatActivity, ta : TootAttachment) { - val url = ta.getLargeUrl(pref) ?: return - openCustomTab(activity, url) - } - // https://developer.android.com/preview/features/gesturalnav?hl=ja fun initEdgeToEdge(@Suppress("UNUSED_PARAMETER") activity : Activity) { // if(Build.VERSION.SDK_INT >= 29){ diff --git a/app/src/main/java/jp/juggler/subwaytooter/AppSettingItem.kt b/app/src/main/java/jp/juggler/subwaytooter/AppSettingItem.kt index 2e5c925d..9dd035f6 100644 --- a/app/src/main/java/jp/juggler/subwaytooter/AppSettingItem.kt +++ b/app/src/main/java/jp/juggler/subwaytooter/AppSettingItem.kt @@ -10,6 +10,7 @@ import android.widget.TextView import androidx.annotation.StringRes import androidx.appcompat.widget.AppCompatImageView import jp.juggler.subwaytooter.util.CustomShareTarget +import jp.juggler.subwaytooter.util.openBrowser import jp.juggler.util.* import org.jetbrains.anko.backgroundDrawable @@ -537,7 +538,7 @@ val appSettingRoot = AppSettingItem(null, SettingType.Section, R.string.app_sett val intent = intentOpenDocument("*/*") startActivityForResult(intent, ActAppSetting.REQUEST_CODE_TIMELINE_FONT) } catch(ex : Throwable) { - showToast(this, ex, "could not open picker for font") + showToast(ex, "could not open picker for font") } } onClickReset = { @@ -559,7 +560,7 @@ val appSettingRoot = AppSettingItem(null, SettingType.Section, R.string.app_sett val intent = intentOpenDocument("*/*") startActivityForResult(intent, ActAppSetting.REQUEST_CODE_TIMELINE_FONT_BOLD) } catch(ex : Throwable) { - showToast(this, ex, "could not open picker for font") + showToast(ex, "could not open picker for font") } } onClickReset = { @@ -701,10 +702,7 @@ val appSettingRoot = AppSettingItem(null, SettingType.Section, R.string.app_sett sw(Pref.bpInstanceTicker, R.string.show_instance_ticker) { desc = R.string.instance_ticker_copyright descClick = { - App1.openBrowser( - this, - "https://github.com/MiyonMiyon/InstanceTicker_List" - ) + openBrowser("https://github.com/MiyonMiyon/InstanceTicker_List") } } @@ -769,12 +767,12 @@ val appSettingRoot = AppSettingItem(null, SettingType.Section, R.string.app_sett colorAlpha(Pref.ipEventBgColorQuote, R.string.quote_renote) colorAlpha(Pref.ipEventBgColorVote, R.string.vote_polls) colorAlpha(Pref.ipEventBgColorStatus, R.string.status) - + colorAlpha( Pref.ipConversationMainTootBgColor, R.string.conversation_main_toot_background_color ) - + colorAlpha(Pref.ipEventBgColorGap, R.string.gap) } @@ -800,12 +798,12 @@ val appSettingRoot = AppSettingItem(null, SettingType.Section, R.string.app_sett val header_bg = when { color_column_header_bg != 0 -> color_column_header_bg - else -> getAttributeColor(activity, R.attr.color_column_header) + else -> activity.getAttributeColor(R.attr.color_column_header) } val header_fg = when { color_column_header_fg != 0 -> color_column_header_fg - else -> getAttributeColor(activity, R.attr.colorColumnHeaderName) + else -> activity.getAttributeColor(R.attr.colorColumnHeaderName) } llColumnHeader.background = getAdaptiveRippleDrawable(header_bg, header_fg) @@ -836,12 +834,12 @@ val appSettingRoot = AppSettingItem(null, SettingType.Section, R.string.app_sett tvSampleAcct.setTextColor( color_column_acct.notZero() - ?: getAttributeColor(activity, R.attr.colorTimeSmall) + ?: activity.getAttributeColor(R.attr.colorTimeSmall) ) tvSampleContent.setTextColor( color_column_text.notZero() - ?: getAttributeColor(activity, R.attr.colorContentText) + ?: activity.getAttributeColor(R.attr.colorContentText) ) } @@ -876,7 +874,7 @@ val appSettingRoot = AppSettingItem(null, SettingType.Section, R.string.app_sett val footer_tab_indicator_color = Pref.ipFooterTabIndicatorColor(pref) val colorColumnStripBackground = footer_tab_bg_color.notZero() - ?: getAttributeColor(activity, R.attr.colorColumnStripBackground) + ?: activity.getAttributeColor(R.attr.colorColumnStripBackground) llFooterBG.setBackgroundColor(colorColumnStripBackground) @@ -884,7 +882,7 @@ val appSettingRoot = AppSettingItem(null, SettingType.Section, R.string.app_sett ?: colorColumnStripBackground val colorButtonFg = footer_button_fg_color.notZero() - ?: getAttributeColor(activity, R.attr.colorRippleEffect) + ?: activity.getAttributeColor(R.attr.colorRippleEffect) ivFooterMenu.backgroundDrawable = getAdaptiveRippleDrawableRound(activity, colorButtonBg, colorButtonFg) @@ -893,7 +891,7 @@ val appSettingRoot = AppSettingItem(null, SettingType.Section, R.string.app_sett val csl = ColorStateList.valueOf( footer_button_fg_color.notZero() - ?: getAttributeColor(activity, R.attr.colorVectorDrawable) + ?: activity.getAttributeColor(R.attr.colorVectorDrawable) ) ivFooterToot.imageTintList = csl ivFooterMenu.imageTintList = csl @@ -905,7 +903,7 @@ val appSettingRoot = AppSettingItem(null, SettingType.Section, R.string.app_sett vIndicator.setBackgroundColor( footer_tab_indicator_color.notZero() - ?: getAttributeColor(activity, R.attr.colorAccent) + ?: activity.getAttributeColor(R.attr.colorAccent) ) } @@ -931,11 +929,11 @@ val appSettingRoot = AppSettingItem(null, SettingType.Section, R.string.app_sett } colorOpaque(Pref.ipStatusBarColor, R.string.status_bar_color) { - changed = { setStatusBarColor(this) } + changed = { setStatusBarColor() } } colorOpaque(Pref.ipNavigationBarColor, R.string.navigation_bar_color) { - changed = { setStatusBarColor(this) } + changed = { setStatusBarColor() } } colorOpaque(Pref.ipSearchBgColor, R.string.search_bar_background_color) @@ -958,15 +956,15 @@ val appSettingRoot = AppSettingItem(null, SettingType.Section, R.string.app_sett section(R.string.developer_options) { sw(Pref.bpCheckBetaVersion, R.string.check_beta_release) - + action(R.string.drawable_list) { action = { startActivity(Intent(this, ActDrawableList::class.java)) } } 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{ + } else { showToast(false, "this feature requires Android 11") } } diff --git a/app/src/main/java/jp/juggler/subwaytooter/AppState.kt b/app/src/main/java/jp/juggler/subwaytooter/AppState.kt index f54be1e4..b099380d 100644 --- a/app/src/main/java/jp/juggler/subwaytooter/AppState.kt +++ b/app/src/main/java/jp/juggler/subwaytooter/AppState.kt @@ -48,6 +48,7 @@ class AppState( ) { companion object { + internal val log = LogCategory("AppState") private const val FILE_COLUMN_LIST = "column_list" @@ -86,7 +87,7 @@ class AppState( } } catch(ex : Throwable) { log.trace(ex) - showToast(context, ex, "saveColumnList failed.") + context.showToast(ex, "saveColumnList failed.") } } } @@ -102,7 +103,7 @@ class AppState( } catch(ignored : FileNotFoundException) { } catch(ex : Throwable) { log.trace(ex) - showToast(context, ex, "loadColumnList failed.") + context.showToast(ex, "loadColumnList failed.") } return null @@ -355,11 +356,11 @@ class AppState( if(willSpeechEnabled && tts == null && tts_status == TTS_STATUS_NONE) { tts_status = TTS_STATUS_INITIALIZING - showToast(context, false, R.string.text_to_speech_initializing) + context.showToast(false, R.string.text_to_speech_initializing) log.d("initializing TextToSpeech…") GlobalScope.launch(Dispatchers.IO) { - + var tmp_tts : TextToSpeech? = null val tts_init_listener : TextToSpeech.OnInitListener = @@ -367,8 +368,7 @@ class AppState( val tts = tmp_tts if(tts == null || TextToSpeech.SUCCESS != status) { - showToast( - context, + context.showToast( false, R.string.text_to_speech_initialize_failed, status @@ -379,7 +379,7 @@ class AppState( runOnMainLooper { if(! willSpeechEnabled) { - showToast(context, false, R.string.text_to_speech_shutdown) + context.showToast(false, R.string.text_to_speech_shutdown) log.d("shutdown TextToSpeech…") tts.shutdown() } else { @@ -450,7 +450,7 @@ class AppState( } if(! willSpeechEnabled && tts != null) { - showToast(context, false, R.string.text_to_speech_shutdown) + context.showToast(false, R.string.text_to_speech_shutdown) log.d("shutdown TextToSpeech…") tts?.shutdown() tts = null diff --git a/app/src/main/java/jp/juggler/subwaytooter/Column.kt b/app/src/main/java/jp/juggler/subwaytooter/Column.kt index 47b9c9a2..aefad149 100644 --- a/app/src/main/java/jp/juggler/subwaytooter/Column.kt +++ b/app/src/main/java/jp/juggler/subwaytooter/Column.kt @@ -352,22 +352,22 @@ class Column( fun reloadDefaultColor(activity : AppCompatActivity, pref : SharedPreferences) { defaultColorHeaderBg = Pref.ipCcdHeaderBg(pref).notZero() - ?: getAttributeColor(activity, R.attr.color_column_header) + ?: activity.getAttributeColor(R.attr.color_column_header) defaultColorHeaderName = Pref.ipCcdHeaderFg(pref).notZero() - ?: getAttributeColor(activity, R.attr.colorColumnHeaderName) + ?: activity.getAttributeColor(R.attr.colorColumnHeaderName) defaultColorHeaderPageNumber = Pref.ipCcdHeaderFg(pref).notZero() - ?: getAttributeColor(activity, R.attr.colorColumnHeaderPageNumber) + ?: activity.getAttributeColor(R.attr.colorColumnHeaderPageNumber) defaultColorContentBg = Pref.ipCcdContentBg(pref) // may zero defaultColorContentAcct = Pref.ipCcdContentAcct(pref).notZero() - ?: getAttributeColor(activity, R.attr.colorTimeSmall) + ?: activity.getAttributeColor(R.attr.colorTimeSmall) defaultColorContentText = Pref.ipCcdContentText(pref).notZero() - ?: getAttributeColor(activity, R.attr.colorContentText) + ?: activity.getAttributeColor(R.attr.colorContentText) } } @@ -2131,14 +2131,14 @@ class Column( if(lastTask != null) { if(! bSilent) { - showToast(context, true, R.string.column_is_busy) + context.showToast(true, R.string.column_is_busy) val holder = viewHolder if(holder != null) holder.refreshLayout.isRefreshing = false } return } else if(bBottom && ! canRefreshBottom()) { if(! bSilent) { - showToast(context, true, R.string.end_of_list) + context.showToast(true, R.string.end_of_list) val holder = viewHolder if(holder != null) holder.refreshLayout.isRefreshing = false } @@ -2175,12 +2175,12 @@ class Column( internal fun startGap(gap : TimelineItem?, isHead : Boolean) { if(gap == null) { - showToast(context, true, "gap is null") + context.showToast(true, "gap is null") return } if(lastTask != null) { - showToast(context, true, R.string.column_is_busy) + context.showToast(true, R.string.column_is_busy) return } diff --git a/app/src/main/java/jp/juggler/subwaytooter/ColumnTask_Gap.kt b/app/src/main/java/jp/juggler/subwaytooter/ColumnTask_Gap.kt index f898b6b4..d74facad 100644 --- a/app/src/main/java/jp/juggler/subwaytooter/ColumnTask_Gap.kt +++ b/app/src/main/java/jp/juggler/subwaytooter/ColumnTask_Gap.kt @@ -415,7 +415,7 @@ class ColumnTask_Gap( } if(max_id == null) { - showToast(context, false, "gap-getConversationSummaryList: missing max_id") + context.showToast(false, "$logCaption: missing max_id") log.d("$logCaption: missing max_id") break } @@ -563,7 +563,7 @@ class ColumnTask_Gap( defaultAccountListParser ) : TootApiResult? { - if( column.pagingType != ColumnPagingType.Default ) { + if(column.pagingType != ColumnPagingType.Default) { return TootApiResult("can't support gap") } diff --git a/app/src/main/java/jp/juggler/subwaytooter/ColumnViewHolder.kt b/app/src/main/java/jp/juggler/subwaytooter/ColumnViewHolder.kt index 8c3ae8f1..97a5b7bb 100644 --- a/app/src/main/java/jp/juggler/subwaytooter/ColumnViewHolder.kt +++ b/app/src/main/java/jp/juggler/subwaytooter/ColumnViewHolder.kt @@ -59,6 +59,7 @@ class ColumnViewHolder( CompoundButton.OnCheckedChangeListener, View.OnLongClickListener { companion object { + private val log = LogCategory("ColumnViewHolder") val fieldRecycler : Field by lazy { @@ -540,8 +541,8 @@ class ColumnViewHolder( // } log.d( - "restoreScrollPosition [$page_idx] %s , column has no saved scroll position." - , column.getColumnName(true) + "restoreScrollPosition [$page_idx] %s , column has no saved scroll position.", + column.getColumnName(true) ) return } @@ -550,18 +551,18 @@ class ColumnViewHolder( if(listView.visibility != View.VISIBLE) { log.d( - "restoreScrollPosition [$page_idx] %s , listView is not visible. saved position %s,%s is dropped." - , column.getColumnName(true) - , sp.adapterIndex - , sp.offset + "restoreScrollPosition [$page_idx] %s , listView is not visible. saved position %s,%s is dropped.", + column.getColumnName(true), + sp.adapterIndex, + sp.offset ) } else { log.d( - "restoreScrollPosition [%d] %s , listView is visible. resume %s,%s" - , page_idx - , column.getColumnName(true) - , sp.adapterIndex - , sp.offset + "restoreScrollPosition [%d] %s , listView is visible. resume %s,%s", + page_idx, + column.getColumnName(true), + sp.adapterIndex, + sp.offset ) sp.restore(this@ColumnViewHolder) } @@ -717,21 +718,21 @@ class ColumnViewHolder( fun dip(dp : Int) : Int = (activity.density * dp + 0.5f).toInt() val context = activity - val announcementsBgColor = Pref.ipAnnouncementsBgColor(activity.pref).notZero() - ?: getAttributeColor(context, R.attr.colorSearchFormBackground) + val announcementsBgColor = Pref.ipAnnouncementsBgColor(App1.pref).notZero() + ?: context.getAttributeColor(R.attr.colorSearchFormBackground) btnAnnouncementsCutout.apply { color = announcementsBgColor } llAnnouncementsBox.apply { - background = createRoundDrawable( dip(6).toFloat(), announcementsBgColor ) + background = createRoundDrawable(dip(6).toFloat(), announcementsBgColor) val pad_tb = dip(2) setPadding(0, pad_tb, 0, pad_tb) } - val searchBgColor = Pref.ipSearchBgColor(activity.pref).notZero() - ?: getAttributeColor(context, R.attr.colorSearchFormBackground) + val searchBgColor = Pref.ipSearchBgColor(App1.pref).notZero() + ?: context.getAttributeColor(R.attr.colorSearchFormBackground) llSearch.apply { backgroundColor = searchBgColor @@ -740,7 +741,7 @@ class ColumnViewHolder( topPadding = dip(3) bottomPadding = dip(3) } - + llListList.apply { backgroundColor = searchBgColor startPadding = dip(12) @@ -1145,7 +1146,7 @@ class ColumnViewHolder( btnListAdd -> { val tv = etListName.text.toString().trim { it <= ' ' } if(tv.isEmpty()) { - showToast(activity, true, R.string.list_name_empty) + activity.showToast(true, R.string.list_name_empty) return } Action_List.create(activity, column.access_info, tv, null) @@ -1161,7 +1162,7 @@ class ColumnViewHolder( btnQuickFilterFavourite -> clickQuickFilter(Column.QUICK_FILTER_FAVOURITE) btnQuickFilterBoost -> clickQuickFilter(Column.QUICK_FILTER_BOOST) btnQuickFilterFollow -> clickQuickFilter(Column.QUICK_FILTER_FOLLOW) - btnQuickFilterPost-> clickQuickFilter(Column.QUICK_FILTER_POST) + btnQuickFilterPost -> clickQuickFilter(Column.QUICK_FILTER_POST) btnQuickFilterReaction -> clickQuickFilter(Column.QUICK_FILTER_REACTION) btnQuickFilterVote -> clickQuickFilter(Column.QUICK_FILTER_VOTE) @@ -1232,7 +1233,7 @@ class ColumnViewHolder( tvColumnContext.text = ac.nickname tvColumnContext.setTextColor( ac.color_fg.notZero() - ?: getAttributeColor(activity, R.attr.colorTimeSmall) + ?: activity.getAttributeColor(R.attr.colorTimeSmall) ) tvColumnContext.setBackgroundColor(ac.color_bg) @@ -1393,11 +1394,11 @@ class ColumnViewHolder( val scroll_save = ScrollPosition() column.scroll_save = scroll_save log.d( - "saveScrollPosition [%d] %s , listView is not visible, save %s,%s" - , page_idx - , column.getColumnName(true) - , scroll_save.adapterIndex - , scroll_save.offset + "saveScrollPosition [%d] %s , listView is not visible, save %s,%s", + page_idx, + column.getColumnName(true), + scroll_save.adapterIndex, + scroll_save.offset ) return true } @@ -1406,11 +1407,11 @@ class ColumnViewHolder( val scroll_save = ScrollPosition(this) column.scroll_save = scroll_save log.d( - "saveScrollPosition [%d] %s , listView is visible, save %s,%s" - , page_idx - , column.getColumnName(true) - , scroll_save.adapterIndex - , scroll_save.offset + "saveScrollPosition [%d] %s , listView is visible, save %s,%s", + page_idx, + column.getColumnName(true), + scroll_save.adapterIndex, + scroll_save.offset ) return true } @@ -1586,10 +1587,10 @@ class ColumnViewHolder( if(insideColumnSetting) { svQuickFilter.setBackgroundColor(0) - val colorFg = getAttributeColor(activity, R.attr.colorContentText) + val colorFg = activity.getAttributeColor(R.attr.colorContentText) val colorBgSelected = colorFg.applyAlphaMultiplier(0.25f) val colorFgList = ColorStateList.valueOf(colorFg) - val colorBg = getAttributeColor(activity, R.attr.colorColumnSettingBackground) + val colorBg = activity.getAttributeColor(R.attr.colorColumnSettingBackground) showQuickFilterButton = { btn, iconId, selected -> btn.backgroundDrawable = getAdaptiveRippleDrawableRound( @@ -1721,7 +1722,7 @@ class ColumnViewHolder( gravity = Gravity.END startPadding = dip(4) endPadding = dip(4) - textColor = getAttributeColor(context, R.attr.colorColumnHeaderAcct) + textColor = context.getAttributeColor(R.attr.colorColumnHeaderAcct) textSize = 12f }.lparams(0, wrapContent) { @@ -1730,7 +1731,7 @@ class ColumnViewHolder( tvColumnStatus = textView { gravity = Gravity.END - textColor = getAttributeColor(context, R.attr.colorColumnHeaderPageNumber) + textColor = context.getAttributeColor(R.attr.colorColumnHeaderPageNumber) textSize = 12f }.lparams(wrapContent, wrapContent) { @@ -1739,7 +1740,7 @@ class ColumnViewHolder( tvColumnIndex = textView { gravity = Gravity.END - textColor = getAttributeColor(context, R.attr.colorColumnHeaderPageNumber) + textColor = context.getAttributeColor(R.attr.colorColumnHeaderPageNumber) textSize = 12f }.lparams(wrapContent, wrapContent) { @@ -1843,7 +1844,7 @@ class ColumnViewHolder( val paint = Paint().apply { isAntiAlias = true color = - getAttributeColor(context, R.attr.colorColumnSettingBackground) + context.getAttributeColor(R.attr.colorColumnSettingBackground) } val path = Path() addOutsideDrawer(this) { canvas, parent, view, left, top -> @@ -1909,7 +1910,7 @@ class ColumnViewHolder( maxHeight = dip(240) backgroundColor = - getAttributeColor(context, R.attr.colorColumnSettingBackground) + context.getAttributeColor(R.attr.colorColumnSettingBackground) llColumnSettingInside = verticalLayout { lparams(matchParent, wrapContent) @@ -1924,7 +1925,7 @@ class ColumnViewHolder( label = textView { textColor = - getAttributeColor(context, R.attr.colorColumnHeaderPageNumber) + context.getAttributeColor(R.attr.colorColumnHeaderPageNumber) text = context.getString(R.string.hashtag_extra_any) }.lparams(matchParent, wrapContent) @@ -1939,7 +1940,7 @@ class ColumnViewHolder( label = textView { textColor = - getAttributeColor(context, R.attr.colorColumnHeaderPageNumber) + context.getAttributeColor(R.attr.colorColumnHeaderPageNumber) text = context.getString(R.string.hashtag_extra_all) }.lparams(matchParent, wrapContent) @@ -1954,7 +1955,7 @@ class ColumnViewHolder( label = textView { textColor = - getAttributeColor(context, R.attr.colorColumnHeaderPageNumber) + context.getAttributeColor(R.attr.colorColumnHeaderPageNumber) text = context.getString(R.string.hashtag_extra_none) }.lparams(matchParent, wrapContent) @@ -2049,12 +2050,12 @@ class ColumnViewHolder( label = textView { textColor = - getAttributeColor(context, R.attr.colorColumnHeaderPageNumber) + context.getAttributeColor(R.attr.colorColumnHeaderPageNumber) text = context.getString(R.string.regex_filter) }.lparams(wrapContent, wrapContent) tvRegexFilterError = textView { - textColor = getAttributeColor(context, R.attr.colorRegexFilterError) + textColor = context.getAttributeColor(R.attr.colorRegexFilterError) }.lparams(0, wrapContent) { weight = 1f startMargin = dip(4) @@ -2220,10 +2221,7 @@ class ColumnViewHolder( contentDescription = context.getString(R.string.clear) imageResource = R.drawable.ic_close imageTintList = ColorStateList.valueOf( - getAttributeColor( - context, - R.attr.colorVectorDrawable - ) + context.getAttributeColor(R.attr.colorVectorDrawable) ) }.lparams(dip(40), dip(40)) { startMargin = dip(4) @@ -2234,10 +2232,7 @@ class ColumnViewHolder( contentDescription = context.getString(R.string.search) imageResource = R.drawable.ic_search imageTintList = ColorStateList.valueOf( - getAttributeColor( - context, - R.attr.colorVectorDrawable - ) + context.getAttributeColor(R.attr.colorVectorDrawable) ) }.lparams(dip(40), dip(40)) { startMargin = dip(4) @@ -2269,8 +2264,7 @@ class ColumnViewHolder( contentDescription = context.getString(R.string.add) imageResource = R.drawable.ic_add imageTintList = ColorStateList.valueOf( - getAttributeColor( - context, + context.getAttributeColor( R.attr.colorVectorDrawable ) ) @@ -2688,8 +2682,8 @@ class ColumnViewHolder( btn.background = if(reaction.me == true) { getAdaptiveRippleDrawableRound( actMain, - getAttributeColor(actMain, R.attr.colorButtonBgCw), - getAttributeColor(actMain, R.attr.colorRippleEffect) + actMain.getAttributeColor(R.attr.colorButtonBgCw), + actMain.getAttributeColor(R.attr.colorRippleEffect) ) } else { ContextCompat.getDrawable(actMain, R.drawable.btn_bg_transparent_round6dp) @@ -2775,7 +2769,7 @@ class ColumnViewHolder( override fun handleResult(result : TootApiResult?) { result ?: return if(result.jsonObject == null) { - showToast(activity, true, result.error) + activity.showToast(true, result.error) } else { sample.count = 0 val list = item.reactions @@ -2811,7 +2805,7 @@ class ColumnViewHolder( override fun handleResult(result : TootApiResult?) { result ?: return if(result.jsonObject == null) { - showToast(activity, true, result.error) + activity.showToast(true, result.error) } else { val it = item.reactions?.iterator() ?: return while(it.hasNext()) { diff --git a/app/src/main/java/jp/juggler/subwaytooter/DlgContextMenu.kt b/app/src/main/java/jp/juggler/subwaytooter/DlgContextMenu.kt index 11f5e3cd..f8f3cfda 100644 --- a/app/src/main/java/jp/juggler/subwaytooter/DlgContextMenu.kt +++ b/app/src/main/java/jp/juggler/subwaytooter/DlgContextMenu.kt @@ -19,9 +19,7 @@ import jp.juggler.subwaytooter.span.MyClickableSpan import jp.juggler.subwaytooter.table.FavMute import jp.juggler.subwaytooter.table.SavedAccount import jp.juggler.subwaytooter.table.UserRelation -import jp.juggler.subwaytooter.util.CustomShare -import jp.juggler.subwaytooter.util.CustomShareTarget -import jp.juggler.subwaytooter.util.matchHost +import jp.juggler.subwaytooter.util.* import jp.juggler.util.* import org.jetbrains.anko.allCaps import org.jetbrains.anko.backgroundDrawable @@ -349,14 +347,14 @@ internal class DlgContextMenu( val colorButtonAccent = Pref.ipButtonFollowingColor(activity.pref).notZero() - ?: getAttributeColor(activity, R.attr.colorImageButtonAccent) + ?: activity.getAttributeColor(R.attr.colorImageButtonAccent) val colorButtonError = Pref.ipButtonFollowRequestColor(activity.pref).notZero() - ?: getAttributeColor(activity, R.attr.colorRegexFilterError) + ?: activity.getAttributeColor(R.attr.colorRegexFilterError) val colorButtonNormal = - getAttributeColor(activity, R.attr.colorImageButton) + activity.getAttributeColor(R.attr.colorImageButton) fun showRelation(relation : UserRelation) { @@ -407,7 +405,7 @@ internal class DlgContextMenu( ivFollowedBy.vg(false) btnFollow.setImageResource(R.drawable.ic_follow_plus) btnFollow.imageTintList = - ColorStateList.valueOf(getAttributeColor(activity, R.attr.colorImageButton)) + ColorStateList.valueOf(activity.getAttributeColor(R.attr.colorImageButton)) btnNotificationFrom.visibility = View.GONE } else { @@ -585,7 +583,7 @@ internal class DlgContextMenu( R.drawable.ic_arrow_drop_down } - val iconColor = getAttributeColor(activity, R.attr.colorTimeSmall) + val iconColor = activity.getAttributeColor(R.attr.colorTimeSmall) val drawable = createColoredDrawable(activity, iconId, iconColor, 1f) btn.setCompoundDrawablesRelativeWithIntrinsicBounds(drawable, null, null, null) } @@ -713,7 +711,7 @@ internal class DlgContextMenu( Action_User.mention(activity, access_info, who) R.id.btnAccountWebPage -> who.url?.let { url -> - App1.openCustomTabOrBrowser(activity, url) + activity.openCustomTabOrBrowser(url) } R.id.btnFollowRequestOK -> @@ -752,13 +750,13 @@ internal class DlgContextMenu( R.id.btnDomainBlock -> if(access_info.isPseudo) { // 疑似アカウントではドメインブロックできない - showToast(activity, false, R.string.domain_block_from_pseudo) + activity.showToast(false, R.string.domain_block_from_pseudo) return } else { val whoApDomain = who.apDomain // 自分のドメインではブロックできない if(access_info.matchHost(whoApDomain)) { - showToast(activity, false, R.string.domain_block_from_local) + activity.showToast(false, R.string.domain_block_from_local) return } AlertDialog.Builder(activity) @@ -794,7 +792,7 @@ internal class DlgContextMenu( R.id.btnAvatarImage -> { val url = if(! who.avatar.isNullOrEmpty()) who.avatar else who.avatar_static - if(url != null && url.isNotEmpty()) App1.openCustomTab(activity, url) + activity.openCustomTab(url) // XXX: 設定によっては内蔵メディアビューアで開けないか? } @@ -821,7 +819,7 @@ internal class DlgContextMenu( R.id.btnHideFavourite -> { val acct = access_info.getFullAcct(who) FavMute.save(acct) - showToast(activity, false, R.string.changed) + activity.showToast(false, R.string.changed) for(column in activity.app_state.column_list) { column.onHideFavouriteNotification(acct) } @@ -829,7 +827,7 @@ internal class DlgContextMenu( R.id.btnShowFavourite -> { FavMute.delete(access_info.getFullAcct(who)) - showToast(activity, false, R.string.changed) + activity.showToast(false, R.string.changed) } R.id.btnListMemberAddRemove -> @@ -884,14 +882,12 @@ internal class DlgContextMenu( R.id.btnCopyAccountId -> who.id.toString().copyToClipboard(activity) R.id.btnOpenAccountInAdminWebUi -> - App1.openBrowser( - activity, + activity.openBrowser( "https://${access_info.apiHost.ascii}/admin/accounts/${who.id}" ) R.id.btnOpenInstanceInAdminWebUi -> - App1.openBrowser( - activity, + activity.openBrowser( "https://${access_info.apiHost.ascii}/admin/instances/${who.apDomain.ascii}" ) @@ -929,8 +925,8 @@ internal class DlgContextMenu( status, access_info.getFullAcct(status.account), NOT_CROSS_ACCOUNT, - activity.boost_complete_callback, - visibility = list[which] + visibility = list[which], + callback =activity.boost_complete_callback, ) } } @@ -940,7 +936,7 @@ internal class DlgContextMenu( R.id.btnNotificationFrom -> { if(access_info.isMisskey) { - showToast(activity, false, R.string.misskey_account_not_supported) + activity.showToast(false, R.string.misskey_account_not_supported) } else { access_info.getFullAcct(who).validFull()?.let { activity.addColumn( @@ -963,9 +959,8 @@ internal class DlgContextMenu( when(v.id) { - R.id.btnStatusWebPage -> status?.url?.let { url -> - App1.openCustomTabOrBrowser(activity, url) - } + R.id.btnStatusWebPage -> + activity.openCustomTabOrBrowser(status?.url) R.id.btnText -> if(status != null) { ActText.open(activity, ActMain.REQUEST_CODE_TEXT, access_info, status) diff --git a/app/src/main/java/jp/juggler/subwaytooter/DownloadReceiver.kt b/app/src/main/java/jp/juggler/subwaytooter/DownloadReceiver.kt index 00279c09..f5b5e7b5 100644 --- a/app/src/main/java/jp/juggler/subwaytooter/DownloadReceiver.kt +++ b/app/src/main/java/jp/juggler/subwaytooter/DownloadReceiver.kt @@ -12,6 +12,7 @@ import jp.juggler.util.showToast class DownloadReceiver : BroadcastReceiver() { companion object { + private val log = LogCategory("DownloadReceiver") } @@ -33,8 +34,7 @@ class DownloadReceiver : BroadcastReceiver() { } val title = cursor.getStringOrNull(DownloadManager.COLUMN_TITLE) val status = cursor.getIntOrNull(DownloadManager.COLUMN_STATUS) - showToast( - context, + context.showToast( false, if(status == DownloadManager.STATUS_SUCCESSFUL) { context.getString(R.string.download_complete, title) diff --git a/app/src/main/java/jp/juggler/subwaytooter/ItemViewHolder.kt b/app/src/main/java/jp/juggler/subwaytooter/ItemViewHolder.kt index 335d1812..cdf11932 100644 --- a/app/src/main/java/jp/juggler/subwaytooter/ItemViewHolder.kt +++ b/app/src/main/java/jp/juggler/subwaytooter/ItemViewHolder.kt @@ -330,7 +330,7 @@ internal class ItemViewHolder( val textShowMedia = SpannableString(activity.getString(R.string.tap_to_show)) .apply { - val colorBg = getAttributeColor(activity, R.attr.colorShowMediaBackground) + val colorBg = activity.getAttributeColor(R.attr.colorShowMediaBackground) .applyAlphaMultiplier(0.5f) setSpan( BackgroundColorSpan(colorBg), @@ -1259,10 +1259,7 @@ internal class ItemViewHolder( val conversationMainBgColor = Pref.ipConversationMainTootBgColor(activity.pref).notZero() - ?: (getAttributeColor( - activity, - R.attr.colorImageButtonAccent - ) and 0xffffff) or 0x20000000 + ?: (activity.getAttributeColor(R.attr.colorImageButtonAccent) and 0xffffff) or 0x20000000 this.viewRoot.setBackgroundColor(conversationMainBgColor) @@ -1976,7 +1973,7 @@ internal class ItemViewHolder( column.startGap(item, isHead = false) else -> - showToast(activity, true, "This column can't support gap reading.") + activity.showToast(true, "This column can't support gap reading.") } is TootSearchGap -> column.startGap(item, isHead = true) @@ -2018,7 +2015,7 @@ internal class ItemViewHolder( .addAction(activity.getString(R.string.delete)) { Action_Toot.deleteScheduledPost(activity, access_info, item) { column.onScheduleDeleted(item) - showToast(activity, false, R.string.scheduled_post_deleted) + activity.showToast(false, R.string.scheduled_post_deleted) } } .show(activity) @@ -2279,8 +2276,8 @@ internal class ItemViewHolder( // メディアタイプがunknownの場合、そのほとんどはリモートから来たURLである // Pref.bpPriorLocalURL の状態に関わらずリモートURLがあればそれをブラウザで開く when(val remoteUrl = item.remote_url.notEmpty()) { - null -> App1.openCustomTab(activity, item) - else -> App1.openCustomTab(activity, remoteUrl) + null -> activity.openCustomTab(item) + else -> activity.openCustomTab(remoteUrl) } } @@ -2297,7 +2294,7 @@ internal class ItemViewHolder( ) // ブラウザで開く - else -> App1.openCustomTab(activity, item) + else -> activity.openCustomTab(item) } } } catch(ex : Throwable) { @@ -2674,7 +2671,7 @@ internal class ItemViewHolder( private fun addReaction(status : TootStatus, code : String?) { if(status.myReaction?.isNotEmpty() == true) { - showToast(activity, false, R.string.already_reactioned) + activity.showToast(false, R.string.already_reactioned) return } @@ -2718,7 +2715,7 @@ internal class ItemViewHolder( val error = result.error if(error != null) { - showToast(activity, false, error) + activity.showToast(false, error) return } @@ -2739,7 +2736,7 @@ internal class ItemViewHolder( val reaction = status.myReaction if(reaction?.isNotEmpty() != true) { - showToast(activity, false, R.string.not_reactioned) + activity.showToast(false, R.string.not_reactioned) return } @@ -2773,7 +2770,7 @@ internal class ItemViewHolder( val error = result.error if(error != null) { - showToast(activity, false, error) + activity.showToast(false, error) return } @@ -3050,7 +3047,7 @@ internal class ItemViewHolder( idx : Int ) { if(enquete.ownVoted) { - showToast(context, false, R.string.already_voted) + context.showToast(false, R.string.already_voted) return } @@ -3064,14 +3061,14 @@ internal class ItemViewHolder( TootPollsType.FriendsNico -> { val remain = enquete.time_start + TootPolls.ENQUETE_EXPIRE - now if(remain <= 0L) { - showToast(context, false, R.string.enquete_was_end) + context.showToast(false, R.string.enquete_was_end) return } } TootPollsType.Mastodon -> { if(enquete.expired || now >= enquete.expired_at) { - showToast(context, false, R.string.enquete_was_end) + context.showToast(false, R.string.enquete_was_end) return } } @@ -3108,7 +3105,7 @@ internal class ItemViewHolder( if(data != null) { when(enquete.pollType) { TootPollsType.Misskey -> if(enquete.increaseVote(activity, idx, true)) { - showToast(context, false, R.string.enquete_voted) + context.showToast(false, R.string.enquete_voted) // 1個だけ開閉するのではなく、例えば通知TLにある複数の要素をまとめて開閉するなどある list_adapter.notifyChange(reason = "onClickEnqueteChoice", reset = true) @@ -3130,7 +3127,7 @@ internal class ItemViewHolder( reset = true ) } else if(result.error != null) { - showToast(context, true, "response parse error") + context.showToast(true, "response parse error") } } @@ -3138,14 +3135,14 @@ internal class ItemViewHolder( val message = data.string("message") ?: "?" val valid = data.optBoolean("valid") if(valid) { - showToast(context, false, R.string.enquete_voted) + context.showToast(false, R.string.enquete_voted) } else { - showToast(context, true, R.string.enquete_vote_failed, message) + context.showToast(true, R.string.enquete_vote_failed, message) } } } } else { - showToast(context, true, result.error) + context.showToast(true, result.error) } } @@ -3160,12 +3157,12 @@ internal class ItemViewHolder( ) { val now = System.currentTimeMillis() if(now >= enquete.expired_at) { - showToast(context, false, R.string.enquete_was_end) + context.showToast(false, R.string.enquete_was_end) return } if(enquete.items?.find { it.checked } == null) { - showToast(context, false, R.string.polls_choice_not_selected) + context.showToast(false, R.string.polls_choice_not_selected) return } @@ -3207,7 +3204,7 @@ internal class ItemViewHolder( // 1個だけ開閉するのではなく、例えば通知TLにある複数の要素をまとめて開閉するなどある list_adapter.notifyChange(reason = "onClickEnqueteChoice", reset = true) } else if(result.error != null) { - showToast(context, true, result.error) + context.showToast(true, result.error) } } }) @@ -3322,13 +3319,11 @@ internal class ItemViewHolder( tvFollowerAcct = textView { setPaddingStartEnd(dip(4), dip(4)) textSize = 12f // SP - // tools:text="aaaaaaaaaaaaaaaa" }.lparams(matchParent, wrapContent) tvLastStatusAt = myTextView { setPaddingStartEnd(dip(4), dip(4)) textSize = 12f // SP - // tools:text="aaaaaaaaaaaaaaaa" }.lparams(matchParent, wrapContent) } @@ -3580,14 +3575,14 @@ internal class ItemViewHolder( btnShowMedia = blurhashView { - errorColor = getAttributeColor( - context, + errorColor = context.getAttributeColor( + R.attr.colorShowMediaBackground ) gravity = Gravity.CENTER - textColor = getAttributeColor( - context, + textColor = context.getAttributeColor( + R.attr.colorShowMediaText ) @@ -3678,14 +3673,12 @@ internal class ItemViewHolder( btnShowMedia = blurhashView { - errorColor = getAttributeColor( - context, + errorColor = context.getAttributeColor( R.attr.colorShowMediaBackground ) gravity = Gravity.CENTER - textColor = getAttributeColor( - context, + textColor = context.getAttributeColor( R.attr.colorShowMediaText ) @@ -3745,14 +3738,12 @@ internal class ItemViewHolder( btnCardImageShow = blurhashView { - errorColor = getAttributeColor( - context, + errorColor = context.getAttributeColor( R.attr.colorShowMediaBackground ) gravity = Gravity.CENTER - textColor = getAttributeColor( - context, + textColor = context.getAttributeColor( R.attr.colorShowMediaText ) diff --git a/app/src/main/java/jp/juggler/subwaytooter/PollingWorker.kt b/app/src/main/java/jp/juggler/subwaytooter/PollingWorker.kt index 0e919750..617889fd 100644 --- a/app/src/main/java/jp/juggler/subwaytooter/PollingWorker.kt +++ b/app/src/main/java/jp/juggler/subwaytooter/PollingWorker.kt @@ -230,7 +230,7 @@ class PollingWorker private constructor(contextArg : Context) { val intervalMillis = max( minute * 5L, - minute * Pref.spPullNotificationCheckInterval.toInt(Pref.pref(context)) + minute * Pref.spPullNotificationCheckInterval.toInt(context.pref()) ) val flexMillis = max( diff --git a/app/src/main/java/jp/juggler/subwaytooter/Pref.kt b/app/src/main/java/jp/juggler/subwaytooter/Pref.kt index 52368fb0..7c873ab0 100644 --- a/app/src/main/java/jp/juggler/subwaytooter/Pref.kt +++ b/app/src/main/java/jp/juggler/subwaytooter/Pref.kt @@ -6,6 +6,9 @@ import android.graphics.Color import androidx.preference.PreferenceManager import jp.juggler.util.optInt +fun Context.pref() : SharedPreferences = + PreferenceManager.getDefaultSharedPreferences(this) + @Suppress("EqualsOrHashCode") abstract class BasePref(val key : String, val defVal : T) { @@ -17,28 +20,25 @@ abstract class BasePref(val key : String, val defVal : T) { Pref.map[key] = this } - override fun equals(other : Any?) : Boolean { - return this === other - } - - fun remove(e : SharedPreferences.Editor) { - e.remove(key) - } - abstract fun put(editor : SharedPreferences.Editor, v : T) abstract fun invoke(pref : SharedPreferences) : T + + override fun equals(other : Any?) = + this === other - operator fun invoke(context : Context) : T { - return invoke(Pref.pref(context)) - } + operator fun invoke(context : Context) : T = + invoke(context.pref()) - fun removeDefault(pref : SharedPreferences, e : SharedPreferences.Editor) : Boolean { + fun remove(e : SharedPreferences.Editor) : SharedPreferences.Editor = + e.remove(key) + + fun removeDefault(pref : SharedPreferences, e : SharedPreferences.Editor) = if(pref.contains(key) && this.invoke(pref) == defVal) { e.remove(key) - return true + true + }else { + false } - return false - } } fun SharedPreferences.Editor.remove(item : BasePref<*>) : SharedPreferences.Editor { @@ -125,10 +125,6 @@ fun SharedPreferences.Editor.put(item : FloatPref, v : Float) = object Pref { - fun pref(context : Context) : SharedPreferences { - return PreferenceManager.getDefaultSharedPreferences(context) - } - // キー名と設定項目のマップ。インポートやアプリ設定で使う val map = HashMap>() @@ -445,6 +441,7 @@ object Pref { // int val ipBackButtonAction = IntPref("back_button_action", 0) + @Suppress("unused") const val BACK_ASK_ALWAYS = 0 const val BACK_CLOSE_COLUMN = 1 @@ -454,18 +451,18 @@ object Pref { val ipUiTheme = IntPref("ui_theme", 0) val ipResizeImage = IntPref("resize_image", 4) - const val RC_SIMPLE = 0 const val RC_ACTUAL = 1 + @Suppress("unused") const val RC_NONE = 2 val ipRepliesCount = IntPref("RepliesCount", RC_SIMPLE) val ipBoostsCount = IntPref("BoostsCount", RC_ACTUAL) val ipFavouritesCount = IntPref("FavouritesCount", RC_ACTUAL) - val ipRefreshAfterToot = IntPref("refresh_after_toot", 0) const val RAT_REFRESH_SCROLL = 0 + @Suppress("unused") const val RAT_REFRESH_DONT_SCROLL = 1 const val RAT_DONT_REFRESH = 2 @@ -477,6 +474,7 @@ object Pref { val ipVisibilityStyle = IntPref("ipVisibilityStyle", VS_BY_ACCOUNT) const val ABP_TOP = 0 + @Suppress("unused") const val ABP_BOTTOM = 1 const val ABP_START = 2 @@ -547,8 +545,6 @@ object Pref { val ipVerifiedLinkBgColor = IntPref("VerifiedLinkBgColor", 0) val ipVerifiedLinkFgColor = IntPref("VerifiedLinkFgColor", 0) - - // val ipTrendTagCountShowing = IntPref("TrendTagCountShowing", 0) // const val TTCS_WEEKLY = 0 // const val TTCS_DAILY = 1 @@ -577,7 +573,7 @@ object Pref { val spBoostAlpha = StringPref("BoostAlpha", "60") val spScreenBottomPadding = StringPref("ScreenBottomPadding", "8") - + val spPullNotificationCheckInterval = StringPref("PullNotificationCheckInterval", "15") val spUserAgent = StringPref("UserAgent", "") @@ -611,3 +607,4 @@ object Pref { internal const val default_header_font_size = 14f } + diff --git a/app/src/main/java/jp/juggler/subwaytooter/SideMenuAdapter.kt b/app/src/main/java/jp/juggler/subwaytooter/SideMenuAdapter.kt index 252ae6ac..4a41ae46 100644 --- a/app/src/main/java/jp/juggler/subwaytooter/SideMenuAdapter.kt +++ b/app/src/main/java/jp/juggler/subwaytooter/SideMenuAdapter.kt @@ -25,6 +25,7 @@ import jp.juggler.subwaytooter.action.Action_Instance import jp.juggler.subwaytooter.api.entity.TootStatus import jp.juggler.subwaytooter.table.SavedAccount import jp.juggler.subwaytooter.util.VersionString +import jp.juggler.subwaytooter.util.openBrowser import jp.juggler.util.* import kotlinx.coroutines.Dispatchers import kotlinx.coroutines.GlobalScope @@ -52,7 +53,7 @@ class SideMenuAdapter( private fun clickableSpan(url : String) = object : ClickableSpan() { override fun onClick(widget : View) { - App1.openBrowser(widget.activity as ActMain, url) + widget.activity?.openBrowser(url) } override fun updateDrawState(ds : TextPaint) { @@ -89,10 +90,9 @@ class SideMenuAdapter( currentVersion ) ) - val newRelease = when(Pref.bpCheckBetaVersion(Pref.pref(appContext))) { - false -> releaseInfo?.jsonObject("stable") - else -> releaseInfo?.jsonObject("beta") - } + val newRelease = releaseInfo?.jsonObject( + if(Pref.bpCheckBetaVersion(App1.pref)) "beta" else "stable" + ) val newVersion = (newRelease?.string("name")?.notEmpty() ?: newRelease?.string("tag_name")) @@ -122,10 +122,7 @@ class SideMenuAdapter( ) setSpan( ForegroundColorSpan( - getAttributeColor( - appContext, - R.attr.colorRegexFilterError - ) + appContext.getAttributeColor(R.attr.colorRegexFilterError) ), start, length, Spannable.SPAN_EXCLUSIVE_EXCLUSIVE @@ -362,7 +359,7 @@ class SideMenuAdapter( } ) - private val iconColor = getAttributeColor(actMain, R.attr.colorTimeSmall) + private val iconColor = actMain.getAttributeColor(R.attr.colorTimeSmall) override fun getCount() : Int = list.size override fun getItem(position : Int) : Any = list[position] @@ -427,7 +424,7 @@ class SideMenuAdapter( FrameLayout.LayoutParams.MATCH_PARENT, FrameLayout.LayoutParams.MATCH_PARENT ) - backgroundColor = getAttributeColor(actMain, R.attr.colorWindowBackground) + backgroundColor = actMain.getAttributeColor(R.attr.colorWindowBackground) selector = StateListDrawable() divider = null dividerHeight = 0 diff --git a/app/src/main/java/jp/juggler/subwaytooter/StatusButtons.kt b/app/src/main/java/jp/juggler/subwaytooter/StatusButtons.kt index 7ada491b..a8bde810 100644 --- a/app/src/main/java/jp/juggler/subwaytooter/StatusButtons.kt +++ b/app/src/main/java/jp/juggler/subwaytooter/StatusButtons.kt @@ -19,6 +19,7 @@ import jp.juggler.subwaytooter.table.SavedAccount import jp.juggler.subwaytooter.table.UserRelation import jp.juggler.subwaytooter.util.CustomShare import jp.juggler.subwaytooter.util.CustomShareTarget +import jp.juggler.subwaytooter.util.emptyCallback import jp.juggler.subwaytooter.util.startMargin import jp.juggler.subwaytooter.view.CountImageButton import jp.juggler.util.* @@ -36,6 +37,7 @@ internal class StatusButtons( ) : View.OnClickListener, View.OnLongClickListener { companion object { + val log = LogCategory("StatusButtons") } @@ -64,7 +66,7 @@ internal class StatusButtons( private val color_normal = column.getContentColor() private val color_accent : Int - get() = getAttributeColor(activity, R.attr.colorImageButtonAccent) + get() = activity.getAttributeColor(R.attr.colorImageButtonAccent) init { this.access_info = column.access_info @@ -494,13 +496,13 @@ internal class StatusButtons( status, access_info.getFullAcct(status.account), NOT_CROSS_ACCOUNT, - when { - ! bSimpleList -> null + bSet = bSet, + callback = when { + ! bSimpleList -> emptyCallback // 簡略表示なら結果をトースト表示 bSet -> activity.boost_complete_callback else -> activity.unboost_complete_callback }, - bSet = bSet ) } } @@ -518,13 +520,13 @@ internal class StatusButtons( access_info, status, NOT_CROSS_ACCOUNT, - when { - ! bSimpleList -> null + bSet = bSet, + callback = when { + ! bSimpleList -> emptyCallback // 簡略表示なら結果をトースト表示 bSet -> activity.favourite_complete_callback else -> activity.unfavourite_complete_callback }, - bSet = bSet ) } } @@ -542,13 +544,13 @@ internal class StatusButtons( access_info, status, NOT_CROSS_ACCOUNT, - when { - ! bSimpleList -> null + bSet = bSet, + callback = when { + ! bSimpleList -> emptyCallback // 簡略表示なら結果をトースト表示 bSet -> activity.bookmark_complete_callback else -> activity.unbookmark_complete_callback }, - bSet = bSet ) } } @@ -720,6 +722,7 @@ internal class StatusButtons( } open class _FlexboxLayout(ctx : Context) : FlexboxLayout(ctx) { + inline fun T.lparams( width : Int = android.view.ViewGroup.LayoutParams.WRAP_CONTENT, height : Int = android.view.ViewGroup.LayoutParams.WRAP_CONTENT, @@ -733,10 +736,10 @@ open class _FlexboxLayout(ctx : Context) : FlexboxLayout(ctx) { } class StatusButtonsViewHolder( - activity : ActMain - , lpWidth : Int - , topMarginDp : Float - , @JustifyContent justifyContent : Int = JustifyContent.CENTER + activity : ActMain, + lpWidth : Int, + topMarginDp : Float, + @JustifyContent justifyContent : Int = JustifyContent.CENTER ) { private val buttonHeight = ActMain.boostButtonSize diff --git a/app/src/main/java/jp/juggler/subwaytooter/Styler.kt b/app/src/main/java/jp/juggler/subwaytooter/Styler.kt index 8e6aa767..b142bd1a 100644 --- a/app/src/main/java/jp/juggler/subwaytooter/Styler.kt +++ b/app/src/main/java/jp/juggler/subwaytooter/Styler.kt @@ -30,7 +30,7 @@ object Styler { fun defaultColorIcon(context : Context, iconId : Int) : Drawable? = ContextCompat.getDrawable(context, iconId)?.also { - it.setTint(getAttributeColor(context, R.attr.colorVectorDrawable)) + it.setTint(context.getAttributeColor(R.attr.colorVectorDrawable)) it.setTintMode(PorterDuff.Mode.SRC_IN) } @@ -123,7 +123,7 @@ object Styler { val icon_id = getVisibilityIconId(isMisskeyData, visibility) val sv = getVisibilityString(context, isMisskeyData, visibility) - val color = getAttributeColor(context, R.attr.colorVectorDrawable) + val color = context.getAttributeColor(R.attr.colorVectorDrawable) val sb = SpannableStringBuilder() // アイコン部分 @@ -159,12 +159,12 @@ object Styler { alphaMultiplier : Float ) { fun colorAccent() = - Pref.ipButtonFollowingColor(Pref.pref(context)).notZero() - ?: getAttributeColor(context, R.attr.colorImageButtonAccent) + Pref.ipButtonFollowingColor(context.pref()).notZero() + ?: context.getAttributeColor(R.attr.colorImageButtonAccent) fun colorError() = - Pref.ipButtonFollowRequestColor(Pref.pref(context)).notZero() - ?: getAttributeColor(context, R.attr.colorRegexFilterError) + Pref.ipButtonFollowRequestColor(context.pref()).notZero() + ?: context.getAttributeColor(R.attr.colorRegexFilterError) // 被フォロー状態 when { diff --git a/app/src/main/java/jp/juggler/subwaytooter/ViewHolderHeaderInstance.kt b/app/src/main/java/jp/juggler/subwaytooter/ViewHolderHeaderInstance.kt index 0d54d433..fb227037 100644 --- a/app/src/main/java/jp/juggler/subwaytooter/ViewHolderHeaderInstance.kt +++ b/app/src/main/java/jp/juggler/subwaytooter/ViewHolderHeaderInstance.kt @@ -10,6 +10,8 @@ import jp.juggler.subwaytooter.action.Action_Instance import jp.juggler.subwaytooter.api.entity.Host import jp.juggler.subwaytooter.api.entity.TootInstance import jp.juggler.subwaytooter.util.DecodeOptions +import jp.juggler.subwaytooter.util.openBrowser +import jp.juggler.subwaytooter.util.openCustomTab import jp.juggler.subwaytooter.view.MyLinkMovementMethod import jp.juggler.subwaytooter.view.MyNetworkImageView import jp.juggler.util.LogCategory @@ -20,10 +22,10 @@ import org.conscrypt.OpenSSLX509Certificate internal class ViewHolderHeaderInstance( arg_activity : ActMain, viewRoot : View -) : ViewHolderHeaderBase(arg_activity, viewRoot) - , View.OnClickListener { +) : ViewHolderHeaderBase(arg_activity, viewRoot), View.OnClickListener { companion object { + private val log = LogCategory("ViewHolderHeaderInstance") } @@ -122,12 +124,13 @@ internal class ViewHolderHeaderInstance( btnEmail.isEnabled = email.isNotEmpty() val contact_acct = - instance.contact_account?.let { who -> "@${who.username}@${who.apDomain.pretty}" } ?: "" + instance.contact_account?.let { who -> "@${who.username}@${who.apDomain.pretty}" } + ?: "" btnContact.text = contact_acct btnContact.isEnabled = contact_acct.isNotEmpty() tvLanguages.text = instance.languages?.joinToString(", ") ?: "" - tvInvitesEnabled.text = when(instance.invites_enabled){ + tvInvitesEnabled.text = when(instance.invites_enabled) { null -> "?" true -> activity.getString(R.string.yes) false -> activity.getString(R.string.no) @@ -183,15 +186,15 @@ internal class ViewHolderHeaderInstance( Certificate : ${cert.type} subject : ${cert.subjectDN} subjectAlternativeNames : ${ - cert.subjectAlternativeNames - ?.joinToString(", ") { - try { - it?.last() - } catch(ignored : Throwable) { - it + cert.subjectAlternativeNames + ?.joinToString(", ") { + try { + it?.last() + } catch(ignored : Throwable) { + it + } + ?.toString() ?: "null" } - ?.toString() ?: "null" - } } issuer : ${cert.issuerX500Principal} end : ${cert.notAfter} @@ -216,7 +219,7 @@ internal class ViewHolderHeaderInstance( R.id.btnEmail -> instance?.email?.let { email -> try { if(email.contains("://")) { - App1.openCustomTab(activity, email) + activity.openCustomTab(email) } else { val intent = Intent(Intent.ACTION_SEND) intent.type = "text/plain" @@ -227,28 +230,31 @@ internal class ViewHolderHeaderInstance( } catch(ex : Throwable) { log.e(ex, "startActivity failed. mail=$email") - showToast(activity, true, R.string.missing_mail_app) + activity.showToast(true, R.string.missing_mail_app) } } R.id.btnContact -> instance?.contact_account?.let { who -> Action_Account.timeline( - activity - , activity.nextPosition(column) - , ColumnType.SEARCH - , args = arrayOf("@${who.username}@${who.apDomain.ascii}", true) + activity, + activity.nextPosition(column), + ColumnType.SEARCH, + args = arrayOf("@${who.username}@${who.apDomain.ascii}", true) ) } - R.id.btnInstance -> App1.openBrowser(activity, "https://${host.pretty}/about") - R.id.ivThumbnail -> App1.openBrowser(activity, instance?.thumbnail) + R.id.btnInstance -> + activity.openBrowser("https://${host.ascii}/about") + + R.id.ivThumbnail -> + activity.openBrowser(instance?.thumbnail) R.id.btnAbout -> - App1.openBrowser(activity, "https://${host.pretty}/about") + activity.openBrowser("https://${host.ascii}/about") R.id.btnAboutMore -> - App1.openBrowser(activity, "https://${host.pretty}/about/more") + activity.openBrowser("https://${host.ascii}/about/more") R.id.btnExplore -> Action_Instance.profileDirectoryFromInstanceInformation( activity, diff --git a/app/src/main/java/jp/juggler/subwaytooter/ViewHolderHeaderProfile.kt b/app/src/main/java/jp/juggler/subwaytooter/ViewHolderHeaderProfile.kt index 1777d4d7..3916e1f1 100644 --- a/app/src/main/java/jp/juggler/subwaytooter/ViewHolderHeaderProfile.kt +++ b/app/src/main/java/jp/juggler/subwaytooter/ViewHolderHeaderProfile.kt @@ -22,6 +22,7 @@ import jp.juggler.subwaytooter.table.SavedAccount import jp.juggler.subwaytooter.table.UserRelation import jp.juggler.subwaytooter.util.DecodeOptions import jp.juggler.subwaytooter.util.NetworkEmojiInvalidator +import jp.juggler.subwaytooter.util.openCustomTab import jp.juggler.subwaytooter.util.startMargin import jp.juggler.subwaytooter.view.MyLinkMovementMethod import jp.juggler.subwaytooter.view.MyNetworkImageView @@ -139,7 +140,7 @@ internal class ViewHolderHeaderProfile( override fun showColor() { llProfile.setBackgroundColor( when(val c = column.column_bg_color) { - 0 -> getAttributeColor(activity, R.attr.colorProfileBackgroundMask) + 0 -> activity.getAttributeColor(R.attr.colorProfileBackgroundMask) else -> - 0x40000000 or (0x00ffffff and c) } ) @@ -194,7 +195,7 @@ internal class ViewHolderHeaderProfile( color = contentColor, alphaMultiplier = Styler.boost_alpha ) - + setIconDrawableId( activity, btnPersonalNotesEdit, @@ -202,7 +203,7 @@ internal class ViewHolderHeaderProfile( color = contentColor, alphaMultiplier = Styler.boost_alpha ) - + val acctColor = column.getAcctColor() tvCreated.textColor = acctColor tvMovedAcct.textColor = acctColor @@ -354,8 +355,10 @@ internal class ViewHolderHeaderProfile( tvMisskeyExtra.vg(tvMisskeyExtra.text.isNotEmpty()) btnStatusCount.text = - "${activity.getString(R.string.statuses)}\n${whoDetail?.statuses_count - ?: who.statuses_count}" + "${activity.getString(R.string.statuses)}\n${ + whoDetail?.statuses_count + ?: who.statuses_count + }" if(Pref.bpHideFollowCount(activity.pref)) { btnFollowing.text = activity.getString(R.string.following) @@ -363,18 +366,18 @@ internal class ViewHolderHeaderProfile( } else { btnFollowing.text = "${activity.getString(R.string.following)}\n${ - whoDetail?.following_count ?: who.following_count + whoDetail?.following_count ?: who.following_count }" btnFollowers.text = "${activity.getString(R.string.followers)}\n${ - whoDetail?.followers_count ?: who.followers_count + whoDetail?.followers_count ?: who.followers_count }" } val relation = UserRelation.load(access_info.db_id, who.id) this.relation = relation - + Styler.setFollowIcon( activity, btnFollow, @@ -386,7 +389,7 @@ internal class ViewHolderHeaderProfile( ) tvPersonalNotes.text = relation.note ?: "" - + showMoved(who, who.movedRef) val fields = whoDetail?.fields ?: who.fields @@ -451,8 +454,10 @@ internal class ViewHolderHeaderProfile( ?: (Color.BLACK or 0x7fbc99) valueText.setSpan( - ForegroundColorSpan(linkFgColor) - , start, end, Spanned.SPAN_EXCLUSIVE_EXCLUSIVE + ForegroundColorSpan(linkFgColor), + start, + end, + Spanned.SPAN_EXCLUSIVE_EXCLUSIVE ) } @@ -537,9 +542,8 @@ internal class ViewHolderHeaderProfile( when(v.id) { - R.id.ivBackground, R.id.tvRemoteProfileWarning -> whoRef?.get()?.url?.let { url -> - App1.openCustomTab(activity, url) - } + R.id.ivBackground, R.id.tvRemoteProfileWarning -> + activity.openCustomTab(whoRef?.get()?.url) R.id.btnFollowing -> { column.profile_tab = ProfileTab.Following @@ -584,44 +588,45 @@ internal class ViewHolderHeaderProfile( } } - R.id.btnPersonalNotesEdit -> whoRef?.let{ whoRef-> + R.id.btnPersonalNotesEdit -> whoRef?.let { whoRef -> val who = whoRef.get() val relation = this.relation val lastColumn = column DlgTextInput.show( activity, - AcctColor.getStringWithNickname(activity,R.string.personal_notes_of,who.acct), + AcctColor.getStringWithNickname(activity, R.string.personal_notes_of, who.acct), relation?.note ?: "", allowEmpty = true, - callback = object: DlgTextInput.Callback{ + callback = object : DlgTextInput.Callback { override fun onEmptyError() { } - + override fun onOK(dialog : Dialog, text : String) { - TootTaskRunner(activity).run(column.access_info,object:TootTask{ + TootTaskRunner(activity).run(column.access_info, object : TootTask { override fun background(client : TootApiClient) : TootApiResult? { - + if(access_info.isPseudo) return TootApiResult("Personal notes is not supported on pseudo account.") - + if(access_info.isMisskey) return TootApiResult("Personal notes is not supported on Misskey account.") - return client.request("/api/v1/accounts/${who.id}/note", + return client.request( + "/api/v1/accounts/${who.id}/note", jsonObject { - put("comment",text) + put("comment", text) }.toPostRequestBuilder() ) } override fun handleResult(result : TootApiResult?) { - if(result==null) return - if(result.error!=null) - showToast(activity,true,result.error) - else{ + if(result == null) return + if(result.error != null) + activity.showToast(true, result.error) + else { relation?.note = text dialog.dismissSafe() - if(lastColumn==column) bindData(column) + if(lastColumn == column) bindData(column) } } }) diff --git a/app/src/main/java/jp/juggler/subwaytooter/action/ActionUtils.kt b/app/src/main/java/jp/juggler/subwaytooter/action/ActionUtils.kt index 1afc1fe6..fb1cc5e2 100644 --- a/app/src/main/java/jp/juggler/subwaytooter/action/ActionUtils.kt +++ b/app/src/main/java/jp/juggler/subwaytooter/action/ActionUtils.kt @@ -22,7 +22,7 @@ internal fun addPseudoAccount( callback : (SavedAccount) -> Unit ) { try { - val acct = Acct.parse("?",host) + val acct = Acct.parse("?", host) var account = SavedAccount.loadAccountByAcct(context, acct.ascii) if(account != null) { @@ -45,7 +45,7 @@ internal fun addPseudoAccount( result == null -> { } - targetInstance == null -> showToast(context, false, result.error) + targetInstance == null -> context.showToast(false, result.error) else -> addPseudoAccount(context, host, targetInstance, callback) } }) @@ -58,7 +58,7 @@ internal fun addPseudoAccount( } val row_id = SavedAccount.insert( - acct =acct.ascii, + acct = acct.ascii, host = host.ascii, domain = instanceInfo.uri, account = account_info, @@ -85,7 +85,7 @@ internal fun addPseudoAccount( val log = LogCategory("addPseudoAccount") log.trace(ex) log.e(ex, "failed.") - showToast(context, ex, "addPseudoAccount failed.") + context.showToast(ex, "addPseudoAccount failed.") } return } @@ -100,7 +100,7 @@ fun makeAccountListNonPseudo( for(a in SavedAccount.loadAccountList(context)) { if(a.isPseudo) continue when(pickup_host) { - null, a.apDomain,a.apiHost -> list_same_host + null, a.apDomain, a.apiHost -> list_same_host else -> list_other_host }.add(a) } diff --git a/app/src/main/java/jp/juggler/subwaytooter/action/Action_Account.kt b/app/src/main/java/jp/juggler/subwaytooter/action/Action_Account.kt index 0282e85a..fc72b6c3 100644 --- a/app/src/main/java/jp/juggler/subwaytooter/action/Action_Account.kt +++ b/app/src/main/java/jp/juggler/subwaytooter/action/Action_Account.kt @@ -1,7 +1,6 @@ package jp.juggler.subwaytooter.action import android.app.Dialog -import android.content.Intent import android.os.Build import androidx.appcompat.app.AlertDialog import jp.juggler.subwaytooter.* @@ -14,6 +13,7 @@ import jp.juggler.subwaytooter.dialog.LoginForm import jp.juggler.subwaytooter.table.SavedAccount import jp.juggler.subwaytooter.table.UserRelation import jp.juggler.subwaytooter.util.LinkHelper +import jp.juggler.subwaytooter.util.openBrowser import jp.juggler.util.* object Action_Account { @@ -57,7 +57,7 @@ object Action_Account { when(action) { LoginForm.Action.Existing -> if(data is String) { // ブラウザ用URLが生成された - App1.openBrowser(activity, data.toUri()) + activity.openBrowser(data.toUri()) dialog.dismissSafe() return } @@ -79,7 +79,7 @@ object Action_Account { instance, instanceInfo = data ) { a -> - showToast(activity, false, R.string.server_confirmed) + activity.showToast(false, R.string.server_confirmed) val pos = App1.getAppState(activity).column_list.size activity.addColumn(pos, a, ColumnType.LOCAL) dialog.dismissSafe() @@ -111,7 +111,7 @@ object Action_Account { } override fun onEmptyError() { - showToast(activity, true, R.string.token_not_specified) + activity.showToast(true, R.string.token_not_specified) } } ) @@ -131,7 +131,7 @@ object Action_Account { .setNeutralButton(R.string.close, null) .show() } else { - showToast(activity, true, "$errorText ${result.requestInfo}".trim()) + activity.showToast(true, "$errorText ${result.requestInfo}".trim()) } } }) @@ -284,7 +284,7 @@ object Action_Account { bSet : Boolean ) { if(access_info.isMisskey) { - showToast(activity, false, "This feature is not provided on Misskey account.") + activity.showToast(false, "This feature is not provided on Misskey account.") return } @@ -319,10 +319,10 @@ object Action_Account { result ?: return if(result.error != null) { - showToast(activity, true, result.error) + activity.showToast(true, result.error) } else { - showToast( - activity, false, when(bSet) { + activity.showToast( + false, when(bSet) { true -> R.string.endorse_succeeded else -> R.string.remove_endorse_succeeded } diff --git a/app/src/main/java/jp/juggler/subwaytooter/action/Action_App.kt b/app/src/main/java/jp/juggler/subwaytooter/action/Action_App.kt index d32ac7ea..85fe5800 100644 --- a/app/src/main/java/jp/juggler/subwaytooter/action/Action_App.kt +++ b/app/src/main/java/jp/juggler/subwaytooter/action/Action_App.kt @@ -35,7 +35,7 @@ object Action_App { MutedApp.save(application.name) App1.getAppState(activity).onMuteUpdated() - showToast(activity, false, R.string.app_was_muted) + activity.showToast(false, R.string.app_was_muted) } } diff --git a/app/src/main/java/jp/juggler/subwaytooter/action/Action_Filter.kt b/app/src/main/java/jp/juggler/subwaytooter/action/Action_Filter.kt index 9441c046..e3403f12 100644 --- a/app/src/main/java/jp/juggler/subwaytooter/action/Action_Filter.kt +++ b/app/src/main/java/jp/juggler/subwaytooter/action/Action_Filter.kt @@ -10,32 +10,40 @@ import jp.juggler.subwaytooter.api.TootTaskRunner import jp.juggler.subwaytooter.api.entity.TootFilter import jp.juggler.subwaytooter.dialog.DlgConfirm import jp.juggler.subwaytooter.table.SavedAccount -import jp.juggler.util.LogCategory import jp.juggler.util.showToast import okhttp3.Request object Action_Filter { - private val log = LogCategory("Action_Filter") + // private val log = LogCategory("Action_Filter") - fun delete( activity : ActMain, access_info : SavedAccount,filter: TootFilter ,bConfirmed :Boolean = false){ - if(!bConfirmed){ - DlgConfirm.openSimple(activity,activity.getString(R.string.filter_delete_confirm, filter.phrase)){ - delete(activity,access_info,filter,bConfirmed=true) + fun delete( + activity : ActMain, + access_info : SavedAccount, + filter : TootFilter, + bConfirmed : Boolean = false + ) { + if(! bConfirmed) { + DlgConfirm.openSimple( + activity, + activity.getString(R.string.filter_delete_confirm, filter.phrase) + ) { + delete(activity, access_info, filter, bConfirmed = true) } return } TootTaskRunner(activity).run(access_info, object : TootTask { - + var filterList : ArrayList? = null - + override fun background(client : TootApiClient) : TootApiResult? { - var result = client.request("/api/v1/filters/${filter.id}", Request.Builder().delete()) - if( result != null && result.error == null){ + var result = + client.request("/api/v1/filters/${filter.id}", Request.Builder().delete()) + if(result != null && result.error == null) { result = client.request("/api/v1/filters") val jsonArray = result?.jsonArray - if( jsonArray != null ) filterList = TootFilter.parseList(jsonArray) + if(jsonArray != null) filterList = TootFilter.parseList(jsonArray) } return result } @@ -44,15 +52,15 @@ object Action_Filter { if(result == null) return // cancelled. val filterList = this.filterList - if( filterList != null) { - showToast(activity, false, R.string.delete_succeeded) + if(filterList != null) { + activity.showToast(false, R.string.delete_succeeded) for(column in App1.getAppState(activity).column_list) { - if( column.access_info == access_info ){ - column.onFilterDeleted(filter,filterList) + if(column.access_info == access_info) { + column.onFilterDeleted(filter, filterList) } } } else { - showToast(activity, false, result.error) + activity.showToast(false, result.error) } } diff --git a/app/src/main/java/jp/juggler/subwaytooter/action/Action_Follow.kt b/app/src/main/java/jp/juggler/subwaytooter/action/Action_Follow.kt index f0e90126..1061ba31 100644 --- a/app/src/main/java/jp/juggler/subwaytooter/action/Action_Follow.kt +++ b/app/src/main/java/jp/juggler/subwaytooter/action/Action_Follow.kt @@ -1,7 +1,10 @@ package jp.juggler.subwaytooter.action import androidx.appcompat.app.AlertDialog -import jp.juggler.subwaytooter.* +import jp.juggler.subwaytooter.ActMain +import jp.juggler.subwaytooter.App1 +import jp.juggler.subwaytooter.ColumnType +import jp.juggler.subwaytooter.R import jp.juggler.subwaytooter.api.* import jp.juggler.subwaytooter.api.entity.* import jp.juggler.subwaytooter.dialog.AccountPicker @@ -9,8 +12,10 @@ import jp.juggler.subwaytooter.dialog.DlgConfirm import jp.juggler.subwaytooter.table.AcctColor import jp.juggler.subwaytooter.table.SavedAccount import jp.juggler.subwaytooter.table.UserRelation -import jp.juggler.subwaytooter.util.EmptyCallback -import jp.juggler.util.* +import jp.juggler.util.showToast +import jp.juggler.util.toFormRequestBody +import jp.juggler.util.toPost +import jp.juggler.util.toPostRequestBuilder object Action_Follow { @@ -22,12 +27,12 @@ object Action_Follow { bFollow : Boolean = true, bConfirmMoved : Boolean = false, bConfirmed : Boolean = false, - callback : EmptyCallback? = null + callback : () -> Unit = {} ) { val who = whoRef.get() if(access_info.isMe(who)) { - showToast(activity, false, R.string.it_is_you) + activity.showToast(false, R.string.it_is_you) return } @@ -73,8 +78,7 @@ object Action_Follow { R.string.confirm_follow_request_who_from, whoRef.decoded_display_name, AcctColor.getNickname(access_info) - ) - , object : DlgConfirm.Callback { + ), object : DlgConfirm.Callback { override fun onOK() { follow( @@ -242,8 +246,8 @@ object Action_Follow { } else { client.request( - "/api/v1/accounts/${userId}/${if(bFollow) "follow" else "unfollow"}" - , "".toFormRequestBody().toPost() + "/api/v1/accounts/${userId}/${if(bFollow) "follow" else "unfollow"}", + "".toFormRequestBody().toPost() )?.also { result -> val newRelation = parseItem(::TootRelationShip, parser, result.jsonObject) if(newRelation != null) { @@ -262,21 +266,21 @@ object Action_Follow { if(bFollow && relation.getRequested(who)) { // 鍵付きアカウントにフォローリクエストを申請した状態 - showToast(activity, false, R.string.follow_requested) + activity.showToast(false, R.string.follow_requested) } else if(! bFollow && relation.getRequested(who)) { - showToast(activity, false, R.string.follow_request_cant_remove_by_sender) + activity.showToast(false, R.string.follow_request_cant_remove_by_sender) } else { // ローカル操作成功、もしくはリモートフォロー成功 - if(callback != null) callback() + callback() } activity.showColumnMatchAccount(access_info) } else if(bFollow && who.locked && (result.response?.code ?: - 1) == 422) { - showToast(activity, false, R.string.cant_follow_locked_user) + activity.showToast(false, R.string.cant_follow_locked_user) } else { - showToast(activity, false, result.error) + activity.showToast(false, result.error) } } @@ -289,7 +293,7 @@ object Action_Follow { access_info : SavedAccount, whoRef : TootAccountRef, bConfirmed : Boolean = false, - callback : EmptyCallback? = null + callback : () -> Unit = {} ) { if(! access_info.isMisskey) { follow( @@ -307,7 +311,7 @@ object Action_Follow { val who = whoRef.get() if(access_info.isMe(who)) { - showToast(activity, false, R.string.it_is_you) + activity.showToast(false, R.string.it_is_you) return } @@ -350,8 +354,7 @@ object Action_Follow { } client.request( - "/api/following/requests/cancel" - , access_info.putMisskeyApiToken().apply { + "/api/following/requests/cancel", access_info.putMisskeyApiToken().apply { put("userId", userId) } .toPostRequestBuilder() @@ -375,16 +378,15 @@ object Action_Follow { val relation = this.relation if(relation != null) { // ローカル操作成功、もしくはリモートフォロー成功 - if(callback != null) callback() + callback() activity.showColumnMatchAccount(access_info) } else { - showToast(activity, false, result.error) + activity.showToast(false, result.error) } } }) } - // acct で指定したユーザをリモートフォローする fun followRemote( @@ -393,11 +395,11 @@ object Action_Follow { acct : Acct, locked : Boolean, bConfirmed : Boolean = false, - callback : EmptyCallback? = null + callback : () -> Unit = {} ) { if(access_info.isMe(acct)) { - showToast(activity, false, R.string.it_is_you) + activity.showToast(false, R.string.it_is_you) return } @@ -499,8 +501,7 @@ object Action_Follow { } } else { client.request( - "/api/v1/accounts/${userId}/follow" - , "".toFormRequestBody().toPost() + "/api/v1/accounts/${userId}/follow", "".toFormRequestBody().toPost() )?.also { result -> val newRelation = parseItem(::TootRelationShip, parser, result.jsonObject) if(newRelation != null) { @@ -515,15 +516,12 @@ object Action_Follow { if(result == null) return // cancelled. if(relation != null) { - + callback() activity.showColumnMatchAccount(access_info) - - if(callback != null) callback() - } else if(locked && (result.response?.code ?: - 1) == 422) { - showToast(activity, false, R.string.cant_follow_locked_user) + activity.showToast(false, R.string.cant_follow_locked_user) } else { - showToast(activity, false, result.error) + activity.showToast(false, result.error) } } @@ -590,7 +588,7 @@ object Action_Follow { ) { val who = whoRef.get() if(access_info.isMe(who)) { - showToast(activity, false, R.string.it_is_you) + activity.showToast(false, R.string.it_is_you) return } @@ -647,14 +645,13 @@ object Action_Follow { } } - showToast( - activity, + activity.showToast( false, if(bAllow) R.string.follow_request_authorized else R.string.follow_request_rejected, whoRef.decoded_display_name ) } else { - showToast(activity, false, result.error) + activity.showToast(false, result.error) } } }) diff --git a/app/src/main/java/jp/juggler/subwaytooter/action/Action_HashTag.kt b/app/src/main/java/jp/juggler/subwaytooter/action/Action_HashTag.kt index 8e2b6cf7..ac131e2f 100644 --- a/app/src/main/java/jp/juggler/subwaytooter/action/Action_HashTag.kt +++ b/app/src/main/java/jp/juggler/subwaytooter/action/Action_HashTag.kt @@ -1,7 +1,6 @@ package jp.juggler.subwaytooter.action import jp.juggler.subwaytooter.ActMain -import jp.juggler.subwaytooter.App1 import jp.juggler.subwaytooter.ColumnType import jp.juggler.subwaytooter.R import jp.juggler.subwaytooter.api.entity.Acct @@ -10,6 +9,7 @@ import jp.juggler.subwaytooter.dialog.ActionsDialog import jp.juggler.subwaytooter.table.AcctColor import jp.juggler.subwaytooter.table.SavedAccount import jp.juggler.subwaytooter.util.matchHost +import jp.juggler.subwaytooter.util.openCustomTab import jp.juggler.util.encodePercent import java.util.* @@ -23,7 +23,7 @@ object Action_HashTag { host : Host, tag_without_sharp : String, tag_list : ArrayList?, - whoAcct: Acct? + whoAcct : Acct? ) { val tag_with_sharp = "#$tag_without_sharp" @@ -40,12 +40,18 @@ object Action_HashTag { // https://mastodon.juggler.jp/@tateisu/101865456016473337 // 一時的に使えなくする - if( whoAcct != null ){ - d.addAction(AcctColor.getStringWithNickname(activity, R.string.open_hashtag_from_account ,whoAcct)) { + if(whoAcct != null) { + d.addAction( + AcctColor.getStringWithNickname( + activity, + R.string.open_hashtag_from_account, + whoAcct + ) + ) { timelineOtherInstance( activity, pos, - "https://${whoAcct.host?.ascii}/@${whoAcct.username}/tagged/${ tag_without_sharp.encodePercent()}", + "https://${whoAcct.host?.ascii}/@${whoAcct.username}/tagged/${tag_without_sharp.encodePercent()}", host, tag_without_sharp, whoAcct @@ -54,18 +60,10 @@ object Action_HashTag { } - d.addAction(activity.getString(R.string.open_in_browser)) { - App1.openCustomTab( - activity, - url - ) - } - .addAction( - activity.getString( - R.string.quote_hashtag_of, - tag_with_sharp - ) - ) { Action_Account.openPost(activity, "$tag_with_sharp ") } + d.addAction(activity.getString(R.string.open_in_browser)) + { activity.openCustomTab(url) } + .addAction(activity.getString(R.string.quote_hashtag_of, tag_with_sharp)) + { Action_Account.openPost(activity, "$tag_with_sharp ") } if(tag_list != null && tag_list.size > 1) { @@ -94,10 +92,16 @@ object Action_HashTag { tag_without_sharp : String, acctAscii : String? = null ) { - if( acctAscii == null) { + if(acctAscii == null) { activity.addColumn(pos, access_info, ColumnType.HASHTAG, tag_without_sharp) - }else { - activity.addColumn(pos, access_info, ColumnType.HASHTAG_FROM_ACCT, tag_without_sharp,acctAscii) + } else { + activity.addColumn( + pos, + access_info, + ColumnType.HASHTAG_FROM_ACCT, + tag_without_sharp, + acctAscii + ) } } @@ -108,7 +112,7 @@ object Action_HashTag { url : String, host : Host, tag_without_sharp : String, - acct :Acct? = null + acct : Acct? = null ) { val dialog = ActionsDialog() @@ -124,37 +128,36 @@ object Action_HashTag { val list_original_pseudo = ArrayList() val list_other = ArrayList() for(a in account_list) { - if( acct == null){ + if(acct == null) { when { - !a.matchHost(host) -> list_other.add(a) + ! a.matchHost(host) -> list_other.add(a) a.isPseudo -> list_original_pseudo.add(a) else -> list_original.add(a) } - }else{ + } else { when { - + // acctからidを取得できない a.isPseudo -> { } - + // ミスキーのアカウント別タグTLは未対応 a.isMisskey -> { } - !a.matchHost(host) -> list_other.add(a) + ! a.matchHost(host) -> list_other.add(a) else -> list_original.add(a) } } } // ブラウザで表示する - dialog.addAction(activity.getString(R.string.open_web_on_host, host)) { - App1.openCustomTab(activity,url) - } + dialog.addAction(activity.getString(R.string.open_web_on_host, host)) + { activity.openCustomTab(url) } // 同タンスのアカウントがない場合は疑似アカウントを作成して開く // ただし疑似アカウントではアカウントの同期ができないため、特定ユーザのタグTLは読めない) - if( acct == null && list_original.isEmpty() && list_original_pseudo.isEmpty()) { + if(acct == null && list_original.isEmpty() && list_original_pseudo.isEmpty()) { dialog.addAction(activity.getString(R.string.open_in_pseudo_account, "?@$host")) { addPseudoAccount(activity, host) { sa -> timeline(activity, pos, sa, tag_without_sharp) @@ -171,7 +174,7 @@ object Action_HashTag { a.acct ) ) - { timeline(activity, pos, a, tag_without_sharp,acct?.ascii) } + { timeline(activity, pos, a, tag_without_sharp, acct?.ascii) } } for(a in list_original_pseudo) { dialog.addAction( @@ -181,7 +184,7 @@ object Action_HashTag { a.acct ) ) - { timeline(activity, pos, a, tag_without_sharp,acct?.ascii) } + { timeline(activity, pos, a, tag_without_sharp, acct?.ascii) } } for(a in list_other) { dialog.addAction( @@ -191,7 +194,7 @@ object Action_HashTag { a.acct ) ) - { timeline(activity, pos, a, tag_without_sharp,acct?.ascii) } + { timeline(activity, pos, a, tag_without_sharp, acct?.ascii) } } dialog.show(activity, "#$tag_without_sharp") diff --git a/app/src/main/java/jp/juggler/subwaytooter/action/Action_Instance.kt b/app/src/main/java/jp/juggler/subwaytooter/action/Action_Instance.kt index a0d2c507..ae51ee24 100644 --- a/app/src/main/java/jp/juggler/subwaytooter/action/Action_Instance.kt +++ b/app/src/main/java/jp/juggler/subwaytooter/action/Action_Instance.kt @@ -9,6 +9,7 @@ import jp.juggler.subwaytooter.api.entity.TootStatus import jp.juggler.subwaytooter.dialog.AccountPicker import jp.juggler.subwaytooter.table.SavedAccount import jp.juggler.subwaytooter.util.matchHost +import jp.juggler.subwaytooter.util.openBrowser import jp.juggler.util.* import java.util.* @@ -35,7 +36,7 @@ object Action_Instance { override fun handleResult(result : TootApiResult?) { result ?: return // cancelled. when(val ti = targetInstance) { - null -> showToast(activity, true, result.error) + null -> activity.showToast(true, result.error) else -> profileDirectory(activity, accessInfo, host, ti, pos) } } @@ -43,11 +44,11 @@ object Action_Instance { // Misskey非対応 instance.instanceType == TootInstance.InstanceType.Misskey -> - showToast(activity, false, R.string.profile_directory_not_supported_on_misskey) + activity.showToast(false, R.string.profile_directory_not_supported_on_misskey) // バージョンが足りないならWebページを開く ! instance.versionGE(TootInstance.VERSION_3_0_0_rc1) -> - App1.openBrowser(activity, "https://${host.ascii}/explore") + activity.openBrowser("https://${host.ascii}/explore") // ホスト名部分が一致するならそのアカウントで開く accessInfo.matchHost(host) -> @@ -123,10 +124,10 @@ object Action_Instance { fun timelineDomain( activity : ActMain, pos : Int, - accessInfo: SavedAccount, + accessInfo : SavedAccount, host : Host - ){ - activity.addColumn(pos, accessInfo, ColumnType.DOMAIN_TIMELINE,host) + ) { + activity.addColumn(pos, accessInfo, ColumnType.DOMAIN_TIMELINE, host) } // 指定タンスのローカルタイムラインを開く @@ -167,7 +168,7 @@ object Action_Instance { ) { if(access_info.matchHost(domain)) { - showToast(activity, false, R.string.it_is_you) + activity.showToast(false, R.string.it_is_you) return } @@ -190,14 +191,13 @@ object Action_Instance { column.onDomainBlockChanged(access_info, domain, bBlock) } - showToast( - activity, + activity.showToast( false, if(bBlock) R.string.block_succeeded else R.string.unblock_succeeded ) } else { - showToast(activity, false, result.error) + activity.showToast(false, result.error) } } }) @@ -235,7 +235,7 @@ object Action_Instance { if(localStatus != null) { timelinePublicAround2(activity, access_info, pos, localStatus.id, type) } else { - showToast(activity, true, result.error) + activity.showToast(true, result.error) } } }) @@ -298,7 +298,7 @@ object Action_Instance { return } - showToast(activity, false, R.string.missing_available_account) + activity.showToast(false, R.string.missing_available_account) } } diff --git a/app/src/main/java/jp/juggler/subwaytooter/action/Action_List.kt b/app/src/main/java/jp/juggler/subwaytooter/action/Action_List.kt index b54ad9fc..483a637e 100644 --- a/app/src/main/java/jp/juggler/subwaytooter/action/Action_List.kt +++ b/app/src/main/java/jp/juggler/subwaytooter/action/Action_List.kt @@ -15,6 +15,7 @@ import okhttp3.Request object Action_List { fun interface CreateCallback { + fun onCreated(list : TootList) } @@ -65,11 +66,11 @@ object Action_List { column.onListListUpdated(access_info) } - showToast(activity, false, R.string.list_created) + activity.showToast(false, R.string.list_created) callback?.onCreated(list) } else { - showToast(activity, false, result.error) + activity.showToast(false, result.error) } } }) @@ -85,8 +86,7 @@ object Action_List { if(! bConfirmed) { DlgConfirm.openSimple( - activity - , activity.getString(R.string.list_delete_confirm, list.title) + activity, activity.getString(R.string.list_delete_confirm, list.title) ) { delete(activity, access_info, list, bConfirmed = true) } @@ -121,10 +121,10 @@ object Action_List { column.onListListUpdated(access_info) } - showToast(activity, false, R.string.delete_succeeded) + activity.showToast(false, R.string.delete_succeeded) } else { - showToast(activity, false, result.error) + activity.showToast(false, result.error) } } }) @@ -142,7 +142,7 @@ object Action_List { item.title, callback = object : DlgTextInput.Callback { override fun onEmptyError() { - showToast(activity, false, R.string.list_name_empty) + activity.showToast(false, R.string.list_name_empty) } override fun onOK(dialog : Dialog, text : String) { @@ -191,7 +191,7 @@ object Action_List { } dialog.dismissSafe() } else { - showToast(activity, false, result.error) + activity.showToast(false, result.error) } } }) diff --git a/app/src/main/java/jp/juggler/subwaytooter/action/Action_ListMember.kt b/app/src/main/java/jp/juggler/subwaytooter/action/Action_ListMember.kt index 2ca1e190..19f6bc9a 100644 --- a/app/src/main/java/jp/juggler/subwaytooter/action/Action_ListMember.kt +++ b/app/src/main/java/jp/juggler/subwaytooter/action/Action_ListMember.kt @@ -17,6 +17,7 @@ object Action_ListMember { private val reFollowError = "follow".asciiPattern(Pattern.CASE_INSENSITIVE) fun interface Callback { + fun onListMemberUpdated(willRegistered : Boolean, bSuccess : Boolean) } @@ -51,13 +52,13 @@ object Action_ListMember { } else { val isMe = access_info.isMe(local_who) - if( isMe ) { + if(isMe) { val (ti, ri) = TootInstance.get(client) if(ti == null) return ri if(! ti.versionGE(TootInstance.VERSION_3_1_0_rc1)) { return TootApiResult(activity.getString(R.string.it_is_you)) } - }else if(bFollow) { + } else if(bFollow) { // リモートユーザの解決 if(! access_info.isLocalUser(local_who)) { val (r2, ar) = client.syncAccountByAcct(access_info, local_who.acct) @@ -119,7 +120,7 @@ object Action_ListMember { // フォロー状態の更新を表示に反映させる if(bFollow) activity.showColumnMatchAccount(access_info) - showToast(activity, false, R.string.list_member_added) + activity.showToast(false, R.string.list_member_added) bSuccess = true @@ -159,7 +160,7 @@ object Action_ListMember { return } - showToast(activity, true, error) + activity.showToast(true, error) } } finally { @@ -209,12 +210,12 @@ object Action_ListMember { column.onListMemberUpdated(access_info, list_id, local_who, false) } - showToast(activity, false, R.string.delete_succeeded) + activity.showToast(false, R.string.delete_succeeded) bSuccess = true } else { - showToast(activity, false, result.error) + activity.showToast(false, result.error) } } finally { callback?.onListMemberUpdated(false, bSuccess) diff --git a/app/src/main/java/jp/juggler/subwaytooter/action/Action_Notification.kt b/app/src/main/java/jp/juggler/subwaytooter/action/Action_Notification.kt index 2cc6976e..fd6987ad 100644 --- a/app/src/main/java/jp/juggler/subwaytooter/action/Action_Notification.kt +++ b/app/src/main/java/jp/juggler/subwaytooter/action/Action_Notification.kt @@ -44,13 +44,13 @@ object Action_Notification { if(result.jsonObject != null) { // ok. api have return empty object. for(column in App1.getAppState(activity).column_list) { - if(column.isNotificationColumn && column.access_info == target_account ) { + if(column.isNotificationColumn && column.access_info == target_account) { column.removeNotifications() } } - showToast(activity, false, R.string.delete_succeeded) + activity.showToast(false, R.string.delete_succeeded) } else { - showToast(activity, false, result.error) + activity.showToast(false, result.error) } } @@ -92,9 +92,9 @@ object Action_Notification { for(column in App1.getAppState(activity).column_list) { column.removeNotificationOne(access_info, notification) } - showToast(activity, true, R.string.delete_succeeded) + activity.showToast(true, R.string.delete_succeeded) } else { - showToast(activity, true, result.error) + activity.showToast(true, result.error) } } diff --git a/app/src/main/java/jp/juggler/subwaytooter/action/Action_Toot.kt b/app/src/main/java/jp/juggler/subwaytooter/action/Action_Toot.kt index 9dcdd853..23c8ec50 100644 --- a/app/src/main/java/jp/juggler/subwaytooter/action/Action_Toot.kt +++ b/app/src/main/java/jp/juggler/subwaytooter/action/Action_Toot.kt @@ -9,9 +9,9 @@ import jp.juggler.subwaytooter.dialog.ActionsDialog import jp.juggler.subwaytooter.dialog.DlgConfirm import jp.juggler.subwaytooter.table.AcctColor import jp.juggler.subwaytooter.table.SavedAccount -import jp.juggler.subwaytooter.util.EmptyCallback import jp.juggler.subwaytooter.util.SavedAccountCallback import jp.juggler.subwaytooter.util.matchHost +import jp.juggler.subwaytooter.util.openCustomTab import jp.juggler.util.* import okhttp3.Request import java.util.* @@ -56,12 +56,12 @@ object Action_Toot { access_info : SavedAccount, arg_status : TootStatus, nCrossAccountMode : Int, - callback : EmptyCallback?, + callback : () -> Unit, bSet : Boolean = true, bConfirmed : Boolean = false ) { if(App1.getAppState(activity).isBusyFav(access_info, arg_status)) { - showToast(activity, false, R.string.wait_previous_operation) + activity.showToast(false, R.string.wait_previous_operation) return } @@ -209,11 +209,10 @@ object Action_Toot { true } } - if(callback != null) callback() - + callback() } - else -> showToast(activity, true, result.error) + else -> activity.showToast(true, result.error) } // 結果に関わらず、更新中状態から復帰させる activity.showColumnMatchAccount(access_info) @@ -256,16 +255,16 @@ object Action_Toot { access_info : SavedAccount, arg_status : TootStatus, nCrossAccountMode : Int, - callback : EmptyCallback?, + callback : () -> Unit, bSet : Boolean = true, bConfirmed : Boolean = false ) { if(App1.getAppState(activity).isBusyFav(access_info, arg_status)) { - showToast(activity, false, R.string.wait_previous_operation) + activity.showToast(false, R.string.wait_previous_operation) return } if(access_info.isMisskey) { - showToast(activity, false, R.string.misskey_account_not_supported) + activity.showToast(false, R.string.misskey_account_not_supported) return } @@ -344,10 +343,10 @@ object Action_Toot { true } } - if(callback != null) callback() + callback() } - else -> showToast(activity, true, result.error) + else -> activity.showToast(true, result.error) } // 結果に関わらず、更新中状態から復帰させる @@ -377,7 +376,7 @@ object Action_Toot { if(a.acct == status_owner) list.add(a) } if(list.isEmpty()) { - showToast(activity, false, R.string.boost_private_toot_not_allowed) + activity.showToast(false, R.string.boost_private_toot_not_allowed) return } AccountPicker.pick( @@ -393,7 +392,7 @@ object Action_Toot { status, status_owner, calcCrossAccountMode(timeline_account, action_account), - activity.boost_complete_callback + callback = activity.boost_complete_callback ) } } else { @@ -410,7 +409,7 @@ object Action_Toot { status, status_owner, calcCrossAccountMode(timeline_account, action_account), - activity.boost_complete_callback + callback = activity.boost_complete_callback ) } } @@ -422,15 +421,15 @@ object Action_Toot { arg_status : TootStatus, status_owner : Acct, nCrossAccountMode : Int, - callback : EmptyCallback?, bSet : Boolean = true, bConfirmed : Boolean = false, - visibility : TootVisibility? = null + visibility : TootVisibility? = null, + callback : () -> Unit ) { // アカウントからステータスにブースト操作を行っているなら、何もしない if(App1.getAppState(activity).isBusyBoost(access_info, arg_status)) { - showToast(activity, false, R.string.wait_previous_operation) + activity.showToast(false, R.string.wait_previous_operation) return } @@ -438,7 +437,7 @@ object Action_Toot { val isPrivateToot = access_info.isMastodon && arg_status.visibility == TootVisibility.PrivateFollowers if(isPrivateToot && access_info.acct != status_owner) { - showToast(activity, false, R.string.boost_private_toot_not_allowed) + activity.showToast(false, R.string.boost_private_toot_not_allowed) return } @@ -463,10 +462,10 @@ object Action_Toot { arg_status, status_owner, nCrossAccountMode, - callback, bSet = bSet, bConfirmed = true, - visibility = visibility + visibility = visibility, + callback = callback, ) } @@ -606,7 +605,7 @@ object Action_Toot { true } } - if(callback != null) callback() + callback() } new_status != null -> { @@ -652,10 +651,10 @@ object Action_Toot { true } } - if(callback != null) callback() + callback() } - else -> showToast(activity, true, result.error) + else -> activity.showToast(true, result.error) } // 結果に関わらず、更新中状態から復帰させる @@ -694,12 +693,12 @@ object Action_Toot { if(result == null) return // cancelled. if(result.jsonObject != null) { - showToast(activity, false, R.string.delete_succeeded) + activity.showToast(false, R.string.delete_succeeded) for(column in App1.getAppState(activity).column_list) { column.onStatusRemoved(access_info.apDomain, status_id) } } else { - showToast(activity, false, result.error) + activity.showToast(false, result.error) } } @@ -820,12 +819,8 @@ object Action_Toot { val host_original = Host.parse(url.toUri().authority ?: "") // 選択肢:ブラウザで表示する - dialog.addAction( - activity.getString( - R.string.open_web_on_host, - host_original.pretty - ) - ) { App1.openCustomTab(activity, url) } + dialog.addAction(activity.getString(R.string.open_web_on_host, host_original.pretty)) + { activity.openCustomTab(url) } // トゥートの投稿元タンスにあるアカウント val local_account_list = ArrayList() @@ -962,7 +957,7 @@ object Action_Toot { if(local_status_id != null) { conversationLocal(activity, pos, access_info, local_status_id) } else { - showToast(activity, true, result.error) + activity.showToast(true, result.error) } } }) @@ -993,9 +988,9 @@ object Action_Toot { val status = tmp val replyId = status?.in_reply_to_id when { - status == null -> showToast(activity, true, result.error ?: "?") - replyId == null -> showToast( - activity, true, + status == null -> activity.showToast(true, result.error ?: "?") + replyId == null -> activity.showToast( + true, "showReplyTootsearch: in_reply_to_id is null" ) else -> conversationLocal(activity, pos, a, replyId) @@ -1096,7 +1091,7 @@ object Action_Toot { } } - else -> showToast(activity, true, result.error) + else -> activity.showToast(true, result.error) } // 結果に関わらず、更新中状態から復帰させる @@ -1153,7 +1148,7 @@ object Action_Toot { if(ls != null) { reply(activity, access_info, ls, quote = quote) } else { - showToast(activity, true, result.error) + activity.showToast(true, result.error) } } }) @@ -1252,7 +1247,7 @@ object Action_Toot { return } val error = result.error ?: "(no information)" - showToast(activity, true, activity.getString(R.string.cant_sync_toot) + " : $error") + activity.showToast(true, activity.getString(R.string.cant_sync_toot) + " : $error") } }) } @@ -1293,13 +1288,12 @@ object Action_Toot { } } } - showToast( - activity, + activity.showToast( true, if(bMute) R.string.mute_succeeded else R.string.unmute_succeeded ) } else { - showToast(activity, true, result.error) + activity.showToast(true, result.error) } } }) @@ -1311,7 +1305,7 @@ object Action_Toot { arg_status : TootStatus, status_owner_acct : Acct, nCrossAccountMode : Int, - callback : EmptyCallback?, + callback : () -> Unit, bSet : Boolean = true, code : String? = null ) { @@ -1319,7 +1313,7 @@ object Action_Toot { // 自分の投稿にはリアクション出来ない if(access_info.acct == status_owner_acct) { - showToast(activity, false, R.string.it_is_you) + activity.showToast(false, R.string.it_is_you) return } @@ -1404,11 +1398,11 @@ object Action_Toot { val error = result.error if(error != null) { - showToast(activity, false, error) + activity.showToast(false, error) return } - if(callback != null) callback() + callback() } }) } @@ -1481,7 +1475,7 @@ object Action_Toot { val error = result.error if(error != null) { - showToast(activity, false, error) + activity.showToast(false, error) return } @@ -1512,7 +1506,7 @@ object Action_Toot { val error = result.error if(error != null) { - showToast(activity, false, error) + activity.showToast(false, error) return } diff --git a/app/src/main/java/jp/juggler/subwaytooter/action/Action_User.kt b/app/src/main/java/jp/juggler/subwaytooter/action/Action_User.kt index cb41a400..fb301354 100644 --- a/app/src/main/java/jp/juggler/subwaytooter/action/Action_User.kt +++ b/app/src/main/java/jp/juggler/subwaytooter/action/Action_User.kt @@ -18,6 +18,7 @@ import jp.juggler.subwaytooter.table.SavedAccount import jp.juggler.subwaytooter.table.UserRelation import jp.juggler.subwaytooter.util.TootApiResultCallback import jp.juggler.subwaytooter.util.matchHost +import jp.juggler.subwaytooter.util.openCustomTab import jp.juggler.util.* import okhttp3.Request @@ -35,7 +36,7 @@ object Action_User { val whoAcct = whoArg.acct if(access_info.isMe(whoAcct)) { - showToast(activity, false, R.string.it_is_you) + activity.showToast(false, R.string.it_is_you) return } @@ -56,7 +57,7 @@ object Action_User { TootApiResult() } - val whoId = if(access_info.matchHost(whoAccessInfo) ) { + val whoId = if(access_info.matchHost(whoAccessInfo)) { whoArg.id } else { val (result, accountRef) = client.syncAccountByAcct(access_info, whoAcct) @@ -124,7 +125,7 @@ object Action_User { if(relation != null && whoId != null) { // 未確認だが、自分をミュートしようとするとリクエストは成功するがレスポンス中のmutingはfalseになるはず if(bMute && ! relation.muting) { - showToast(activity, false, R.string.not_muted) + activity.showToast(false, R.string.not_muted) return } @@ -163,14 +164,13 @@ object Action_User { } } - showToast( - activity, + activity.showToast( false, if(relation.muting) R.string.mute_succeeded else R.string.unmute_succeeded ) } else { - showToast(activity, false, result.error) + activity.showToast(false, result.error) } } }) @@ -220,7 +220,11 @@ object Action_User { .show() } - fun muteFromAnotherAccount(activity : ActMain, who : TootAccount,whoAccessInfo : SavedAccount) { + fun muteFromAnotherAccount( + activity : ActMain, + who : TootAccount, + whoAccessInfo : SavedAccount + ) { AccountPicker.pick( activity, bAllowPseudo = false, @@ -228,7 +232,7 @@ object Action_User { message = activity.getString(R.string.account_picker_mute, who.acct.pretty), accountListArg = makeAccountListNonPseudo(activity, who.apDomain) ) { ai -> - muteConfirm(activity, ai, who,whoAccessInfo) + muteConfirm(activity, ai, who, whoAccessInfo) } } @@ -243,7 +247,7 @@ object Action_User { val whoAcct = whoArg.acct if(access_info.isMe(whoAcct)) { - showToast(activity, false, R.string.it_is_you) + activity.showToast(false, R.string.it_is_you) return } @@ -264,7 +268,7 @@ object Action_User { TootApiResult() } - val whoId = if(access_info.matchHost(whoAccessInfo) ) { + val whoId = if(access_info.matchHost(whoAccessInfo)) { whoArg.id } else { val (result, accountRef) = client.syncAccountByAcct(access_info, whoAcct) @@ -334,7 +338,7 @@ object Action_User { // 自分をブロックしようとすると、blocking==falseで帰ってくる if(bBlock && ! relation.blocking) { - showToast(activity, false, R.string.not_blocked) + activity.showToast(false, R.string.not_blocked) return } @@ -377,8 +381,7 @@ object Action_User { } } - showToast( - activity, + activity.showToast( false, if(relation.blocking) R.string.block_succeeded @@ -386,7 +389,7 @@ object Action_User { R.string.unblock_succeeded ) } else { - showToast(activity, false, result.error) + activity.showToast(false, result.error) } } }) @@ -464,9 +467,9 @@ object Action_User { when(val who = this.who) { null -> { - showToast(activity, true, result.error) + activity.showToast(true, result.error) // 仕方ないのでchrome tab で開く - App1.openCustomTab(activity, who_url) + activity.openCustomTab(who_url) } else -> activity.addColumn(pos, access_info, ColumnType.PROFILE, who.id) @@ -550,7 +553,7 @@ object Action_User { when(val who = this.who) { null -> { // ダメならchromeで開く - App1.openCustomTab(activity, url) + activity.openCustomTab(url) } else -> profileLocal(activity, pos, access_info, who) @@ -570,7 +573,7 @@ object Action_User { if(! SavedAccount.hasRealAccount()) { // 疑似アカウントしか登録されていない // chrome tab で開く - App1.openCustomTab(activity, original_url) + activity.openCustomTab(original_url) } else { AccountPicker.pick( activity, @@ -599,7 +602,7 @@ object Action_User { b.setBackgroundResource(R.drawable.btn_bg_transparent_round6dp) b.setOnClickListener { - App1.openCustomTab(activity, original_url) + activity.openCustomTab(original_url) } ll.addView(b, 0) } @@ -636,7 +639,7 @@ object Action_User { onReportComplete : TootApiResultCallback ) { if(access_info.isMe(who)) { - showToast(activity, false, R.string.it_is_you) + activity.showToast(false, R.string.it_is_you) return } @@ -663,9 +666,9 @@ object Action_User { if(result.jsonObject != null) { onReportComplete(result) - showToast(activity, false, R.string.report_completed) + activity.showToast(false, R.string.report_completed) } else { - showToast(activity, true, result.error) + activity.showToast(true, result.error) } } }) @@ -676,7 +679,7 @@ object Action_User { activity : ActMain, access_info : SavedAccount, who : TootAccount, bShow : Boolean ) { if(access_info.isMe(who)) { - showToast(activity, false, R.string.it_is_you) + activity.showToast(false, R.string.it_is_you) return } @@ -716,9 +719,9 @@ object Action_User { if(result == null) return // cancelled. if(relation != null) { - showToast(activity, true, R.string.operation_succeeded) + activity.showToast(true, R.string.operation_succeeded) } else { - showToast(activity, true, result.error) + activity.showToast(true, result.error) } } }) @@ -751,7 +754,6 @@ object Action_User { ) { if(who == null) return - val initial_text = "@${access_info.getFullAcct(who).ascii} " AccountPicker.pick( activity, @@ -794,11 +796,11 @@ object Action_User { // error val error = result.error if(error != null) { - showToast(activity, true, result.error) + activity.showToast(true, result.error) return } - showToast(activity, false, R.string.delete_succeeded) + activity.showToast(false, R.string.delete_succeeded) // update suggestion column for(column in activity.app_state.column_list) { @@ -819,12 +821,20 @@ object Action_User { return client.request( "/api/v1/accounts/$whoId/follow", jsonObject { - put("notify",enabled) + put("notify", enabled) }.toPostRequestBuilder() - )?.also{ result-> - val relation = parseItem( ::TootRelationShip, TootParser(activity,accessInfo),result.jsonObject) - if(relation!=null){ - UserRelation.save1Mastodon(System.currentTimeMillis(),accessInfo.db_id,relation) + )?.also { result -> + val relation = parseItem( + ::TootRelationShip, + TootParser(activity, accessInfo), + result.jsonObject + ) + if(relation != null) { + UserRelation.save1Mastodon( + System.currentTimeMillis(), + accessInfo.db_id, + relation + ) } } } @@ -836,11 +846,11 @@ object Action_User { // error val error = result.error if(error != null) { - showToast(activity, true, result.error) + activity.showToast(true, result.error) return } - showToast(activity, false, R.string.operation_succeeded) + activity.showToast(false, R.string.operation_succeeded) } }) } diff --git a/app/src/main/java/jp/juggler/subwaytooter/api/TootApiClient.kt b/app/src/main/java/jp/juggler/subwaytooter/api/TootApiClient.kt index 37cf6217..80257a10 100644 --- a/app/src/main/java/jp/juggler/subwaytooter/api/TootApiClient.kt +++ b/app/src/main/java/jp/juggler/subwaytooter/api/TootApiClient.kt @@ -40,7 +40,7 @@ class TootApiClient( } init { - pref = Pref.pref(context) + pref = context.pref() } companion object { @@ -566,7 +566,7 @@ class TootApiClient( val result = TootApiResult.makeWithCaption(apiHost?.pretty) if(result.error != null) { - showToast(context, false, result.error) + context.showToast(false, result.error) return null } @@ -583,7 +583,7 @@ class TootApiClient( ) { val error = result.error if(error != null) { - showToast(context, false, error) + context.showToast(false, error) return null } return null @@ -593,7 +593,7 @@ class TootApiClient( val jsonObject = result.jsonObject if(jsonObject == null) { - showToast(context, false, result.error) + context.showToast(false, result.error) return null } // {"token":"0ba88e2d-4b7d-4599-8d90-dc341a005637","url":"https://misskey.xyz/auth/0ba88e2d-4b7d-4599-8d90-dc341a005637"} @@ -601,7 +601,7 @@ class TootApiClient( // ブラウザで開くURL val url = jsonObject.string("url") if(url?.isEmpty() != false) { - showToast(context, false, "missing 'url' in auth session response.") + context.showToast(false, "missing 'url' in auth session response.") return null } @@ -690,7 +690,7 @@ class TootApiClient( val appSecret = jsonObject.string(KEY_MISSKEY_APP_SECRET) if(appSecret?.isEmpty() != false) { - showToast(context, true, context.getString(R.string.cant_get_misskey_app_secret)) + context.showToast(true, context.getString(R.string.cant_get_misskey_app_secret)) return null } // { diff --git a/app/src/main/java/jp/juggler/subwaytooter/api/entity/TootCard.kt b/app/src/main/java/jp/juggler/subwaytooter/api/entity/TootCard.kt index 9d92a724..3a0d3dff 100644 --- a/app/src/main/java/jp/juggler/subwaytooter/api/entity/TootCard.kt +++ b/app/src/main/java/jp/juggler/subwaytooter/api/entity/TootCard.kt @@ -1,7 +1,7 @@ package jp.juggler.subwaytooter.api.entity -import jp.juggler.subwaytooter.Pref import jp.juggler.subwaytooter.api.TootParser +import jp.juggler.subwaytooter.pref import jp.juggler.subwaytooter.util.DecodeOptions import jp.juggler.util.JsonObject import jp.juggler.util.filterNotEmpty @@ -61,7 +61,7 @@ class TootCard( }, image = src.media_attachments ?.firstOrNull() - ?.urlForThumbnail(Pref.pref(parser.context)) + ?.urlForThumbnail(parser.context.pref()) ?: src.account.avatar_static, type = "photo" ) diff --git a/app/src/main/java/jp/juggler/subwaytooter/dialog/AccountPicker.kt b/app/src/main/java/jp/juggler/subwaytooter/dialog/AccountPicker.kt index 3cff825d..67b62421 100644 --- a/app/src/main/java/jp/juggler/subwaytooter/dialog/AccountPicker.kt +++ b/app/src/main/java/jp/juggler/subwaytooter/dialog/AccountPicker.kt @@ -30,36 +30,36 @@ object AccountPicker { activity : AppCompatActivity, bAllowPseudo : Boolean = false, bAllowMisskey : Boolean = true, - bAllowMastodon: Boolean = true, + bAllowMastodon : Boolean = true, bAuto : Boolean = false, message : String? = null, accountListArg : ArrayList? = null, dismiss_callback : DialogInterfaceCallback? = null, - extra_callback : (LinearLayout,Int,Int)->Unit = {_,_,_->}, + extra_callback : (LinearLayout, Int, Int) -> Unit = { _, _, _ -> }, callback : SavedAccountCallback ) { - var removedMisskey =0 - var removedPseudo =0 + var removedMisskey = 0 + var removedPseudo = 0 var removeMastodon = 0 val account_list : MutableList = accountListArg ?: { - val l = SavedAccount.loadAccountList(activity).filter { a-> + val l = SavedAccount.loadAccountList(activity).filter { a -> var bOk = true - if( !bAllowMastodon && !a.isMisskey ){ - ++removeMastodon - bOk=false + if(! bAllowMastodon && ! a.isMisskey) { + ++ removeMastodon + bOk = false } - if( !bAllowMisskey && a.isMisskey ){ - ++removedMisskey - bOk=false + if(! bAllowMisskey && a.isMisskey) { + ++ removedMisskey + bOk = false } - - if( !bAllowPseudo && a.isPseudo ){ - ++removedPseudo - bOk=false + + if(! bAllowPseudo && a.isPseudo) { + ++ removedPseudo + bOk = false } - + bOk }.toMutableList() SavedAccount.sort(l) @@ -67,30 +67,30 @@ object AccountPicker { }() if(account_list.isEmpty()) { - - val sb=StringBuilder() - - if( removedPseudo > 0 ){ + + val sb = StringBuilder() + + if(removedPseudo > 0) { sb.append(activity.getString(R.string.not_available_for_pseudo_account)) } - - if( removedMisskey > 0 ){ - if(sb.isNotEmpty() ) sb.append('\n') + + if(removedMisskey > 0) { + if(sb.isNotEmpty()) sb.append('\n') sb.append(activity.getString(R.string.not_available_for_misskey_account)) } - if( removeMastodon > 0 ){ - if(sb.isNotEmpty() ) sb.append('\n') + if(removeMastodon > 0) { + if(sb.isNotEmpty()) sb.append('\n') sb.append(activity.getString(R.string.not_available_for_mastodon_account)) } - - if( sb.isEmpty() ){ + + if(sb.isEmpty()) { sb.append(activity.getString(R.string.account_empty)) } - showToast(activity, false,sb.toString()) + activity.showToast(false, sb.toString()) return } - + if(bAuto && account_list.size == 1) { callback(account_list[0]) return @@ -121,19 +121,22 @@ object AccountPicker { val density = activity.resources.displayMetrics.density - val llAccounts :LinearLayout= viewRoot.findViewById(R.id.llAccounts) + val llAccounts : LinearLayout = viewRoot.findViewById(R.id.llAccounts) val pad_se = (0.5f + 12f * density).toInt() val pad_tb = (0.5f + 6f * density).toInt() for(a in account_list) { - val lp = LinearLayout.LayoutParams(LinearLayout.LayoutParams.MATCH_PARENT, LinearLayout.LayoutParams.WRAP_CONTENT) + val lp = LinearLayout.LayoutParams( + LinearLayout.LayoutParams.MATCH_PARENT, + LinearLayout.LayoutParams.WRAP_CONTENT + ) val ac = AcctColor.load(a) val b = Button(activity) if(AcctColor.hasColorBackground(ac)) { - b.background = getAdaptiveRippleDrawableRound(activity,ac.color_bg,ac.color_fg) + b.background = getAdaptiveRippleDrawableRound(activity, ac.color_bg, ac.color_fg) } else { b.setBackgroundResource(R.drawable.btn_bg_transparent_round6dp) } @@ -148,13 +151,13 @@ object AccountPicker { b.minHeight = (0.5f + 32f * density).toInt() val sb = SpannableStringBuilder(ac.nickname) - if( a.last_notification_error?.isNotEmpty() == true) { + if(a.last_notification_error?.isNotEmpty() == true) { sb.append("\n") val start = sb.length sb.append(a.last_notification_error) val end = sb.length sb.setSpan(RelativeSizeSpan(0.7f), start, end, Spannable.SPAN_EXCLUSIVE_EXCLUSIVE) - }else if(a.last_subscription_error?.isNotEmpty() == true) { + } else if(a.last_subscription_error?.isNotEmpty() == true) { sb.append("\n") val start = sb.length sb.append(a.last_subscription_error) @@ -171,7 +174,7 @@ object AccountPicker { llAccounts.addView(b) } - extra_callback(llAccounts,pad_se, pad_tb) + extra_callback(llAccounts, pad_se, pad_tb) dialog.show() } diff --git a/app/src/main/java/jp/juggler/subwaytooter/dialog/ActionsDialog.kt b/app/src/main/java/jp/juggler/subwaytooter/dialog/ActionsDialog.kt index 1f62b4c7..281cec9c 100644 --- a/app/src/main/java/jp/juggler/subwaytooter/dialog/ActionsDialog.kt +++ b/app/src/main/java/jp/juggler/subwaytooter/dialog/ActionsDialog.kt @@ -2,26 +2,23 @@ package jp.juggler.subwaytooter.dialog import android.content.Context import androidx.appcompat.app.AlertDialog - -import java.util.ArrayList - import jp.juggler.subwaytooter.R -import jp.juggler.subwaytooter.util.EmptyCallback +import java.util.* class ActionsDialog { private val action_list = ArrayList() - private class Action(val caption : CharSequence, val r : EmptyCallback) + private class Action(val caption : CharSequence, val action : () -> Unit) - fun addAction(caption : CharSequence, r : EmptyCallback) : ActionsDialog { + fun addAction(caption : CharSequence, action : () -> Unit) : ActionsDialog { - action_list.add(Action(caption, r)) + action_list.add(Action(caption, action)) return this } - fun show(context : Context, title : CharSequence? = null ) : ActionsDialog { + fun show(context : Context, title : CharSequence? = null) : ActionsDialog { val caption_list = arrayOfNulls(action_list.size) var i = 0 val ie = caption_list.size @@ -33,11 +30,11 @@ class ActionsDialog { .setNegativeButton(R.string.cancel, null) .setItems(caption_list) { _, which -> if(which >= 0 && which < action_list.size) { - action_list[which].r() + action_list[which].action() } } - if( title != null && title.isNotEmpty() ) b.setTitle(title) + if(title != null && title.isNotEmpty()) b.setTitle(title) b.show() diff --git a/app/src/main/java/jp/juggler/subwaytooter/dialog/DlgAppPicker.kt b/app/src/main/java/jp/juggler/subwaytooter/dialog/DlgAppPicker.kt index e25c432e..5bc2fdf8 100644 --- a/app/src/main/java/jp/juggler/subwaytooter/dialog/DlgAppPicker.kt +++ b/app/src/main/java/jp/juggler/subwaytooter/dialog/DlgAppPicker.kt @@ -11,14 +11,14 @@ import android.view.View import android.view.ViewGroup import android.view.WindowManager import android.widget.* -import androidx.appcompat.app.AppCompatActivity +import android.app.Activity import jp.juggler.subwaytooter.R import jp.juggler.subwaytooter.util.CustomShare import jp.juggler.subwaytooter.util.cn import jp.juggler.util.* class DlgAppPicker( - val activity : AppCompatActivity, + val activity : Activity, val intent : Intent, val autoSelect : Boolean = false, val filter : (ResolveInfo) -> Boolean = { true }, @@ -26,6 +26,7 @@ class DlgAppPicker( ) { companion object { + fun Char.isAlpha() = ('A' <= this && this <= 'Z') || ('a' <= this && this <= 'z') } @@ -63,7 +64,7 @@ class DlgAppPicker( val (label, icon) = CustomShare.getInfo(activity, CustomShare.CN_CLIPBOARD.cn()) add(ListItem(icon, label.toString(), CustomShare.CN_CLIPBOARD)) } - sortWith{ a, b -> + sortWith { a, b -> val a1 = a.text.firstOrNull() ?: '\u0000' val b1 = b.text.firstOrNull() ?: '\u0000' when { @@ -99,10 +100,10 @@ class DlgAppPicker( // returns false if list is empty @SuppressLint("InflateParams") fun show() = - if( list.isEmpty()){ + if(list.isEmpty()) { dialog?.dismissSafe() false - }else { + } else { dialog?.run { window?.setLayout( WindowManager.LayoutParams.MATCH_PARENT, @@ -113,7 +114,6 @@ class DlgAppPicker( true } - private inner class MyAdapter : BaseAdapter(), AdapterView.OnItemClickListener { override fun getCount() : Int = list.size @@ -142,6 +142,7 @@ class DlgAppPicker( } private inner class MyViewHolder(viewRoot : View) { + val ivImage : ImageView = viewRoot.findViewById(R.id.ivImage) val tvText : TextView = viewRoot.findViewById(R.id.tvText) var item : ListItem? = null @@ -155,7 +156,7 @@ class DlgAppPicker( activity, ivImage, R.drawable.ic_question, - color = getAttributeColor(activity, R.attr.colorVectorDrawable), + color = activity.getAttributeColor(R.attr.colorVectorDrawable), alphaMultiplier = 1f ) } diff --git a/app/src/main/java/jp/juggler/subwaytooter/dialog/DlgCreateAccount.kt b/app/src/main/java/jp/juggler/subwaytooter/dialog/DlgCreateAccount.kt index 32bfe0a5..3db946da 100644 --- a/app/src/main/java/jp/juggler/subwaytooter/dialog/DlgCreateAccount.kt +++ b/app/src/main/java/jp/juggler/subwaytooter/dialog/DlgCreateAccount.kt @@ -9,12 +9,12 @@ import android.widget.CheckBox import android.widget.EditText import android.widget.TextView import androidx.appcompat.app.AppCompatActivity -import jp.juggler.subwaytooter.App1 import jp.juggler.subwaytooter.R import jp.juggler.subwaytooter.api.entity.Host import jp.juggler.subwaytooter.api.entity.TootInstance import jp.juggler.subwaytooter.util.DecodeOptions import jp.juggler.subwaytooter.util.LinkHelper +import jp.juggler.subwaytooter.util.openCustomTab import jp.juggler.util.neatSpaces import jp.juggler.util.notBlank import jp.juggler.util.showToast @@ -97,10 +97,10 @@ class DlgCreateAccount( override fun onClick(v : View?) { when(v?.id) { R.id.btnRules -> - App1.openCustomTab(activity, "https://$instance/about/more") + activity.openCustomTab("https://$instance/about/more") R.id.btnTerms -> - App1.openCustomTab(activity, "https://$instance/terms") + activity.openCustomTab("https://$instance/terms") R.id.btnCancel -> dialog.cancel() @@ -112,16 +112,16 @@ class DlgCreateAccount( when { username.isEmpty() -> - showToast(activity, true, R.string.username_empty) + activity.showToast(true, R.string.username_empty) email.isEmpty() -> - showToast(activity, true, R.string.email_empty) + activity.showToast(true, R.string.email_empty) password.isEmpty() -> - showToast(activity, true, R.string.password_empty) + activity.showToast(true, R.string.password_empty) username.contains("/") || username.contains("@") -> - showToast(activity, true, R.string.username_not_need_atmark) + activity.showToast(true, R.string.username_not_need_atmark) else -> onClickOk( dialog, diff --git a/app/src/main/java/jp/juggler/subwaytooter/dialog/DlgDraftPicker.kt b/app/src/main/java/jp/juggler/subwaytooter/dialog/DlgDraftPicker.kt index bc28f15b..e3d4cdce 100644 --- a/app/src/main/java/jp/juggler/subwaytooter/dialog/DlgDraftPicker.kt +++ b/app/src/main/java/jp/juggler/subwaytooter/dialog/DlgDraftPicker.kt @@ -23,7 +23,8 @@ import kotlinx.coroutines.* class DlgDraftPicker : AdapterView.OnItemClickListener, AdapterView.OnItemLongClickListener, DialogInterface.OnDismissListener { - companion object{ + companion object { + private val log = LogCategory("DlgDraftPicker") } @@ -55,7 +56,7 @@ class DlgDraftPicker : AdapterView.OnItemClickListener, AdapterView.OnItemLongCl val draft = getPostDraft(position) if(draft != null) { - showToast(activity, false, R.string.draft_deleted) + activity.showToast(false, R.string.draft_deleted) draft.delete() reload() return true @@ -104,16 +105,16 @@ class DlgDraftPicker : AdapterView.OnItemClickListener, AdapterView.OnItemLongCl // cancel old task task?.cancel() - task = GlobalScope.launch(Dispatchers.Main){ - val cursor =try { + task = GlobalScope.launch(Dispatchers.Main) { + val cursor = try { withContext(Dispatchers.IO) { PostDraft.createCursor() } ?: error("cursor is null") - }catch(ex:CancellationException) { + } catch(ex : CancellationException) { return@launch - }catch(ex:Throwable){ + } catch(ex : Throwable) { log.trace(ex) - showToast(activity,ex, "failed to loading drafts.") + activity.showToast(ex, "failed to loading drafts.") return@launch } @@ -136,6 +137,7 @@ class DlgDraftPicker : AdapterView.OnItemClickListener, AdapterView.OnItemLongCl } private inner class MyViewHolder(view : View) { + val tvTime : TextView val tvText : TextView diff --git a/app/src/main/java/jp/juggler/subwaytooter/dialog/DlgFocusPoint.kt b/app/src/main/java/jp/juggler/subwaytooter/dialog/DlgFocusPoint.kt index b4bd4521..a2dc4fad 100644 --- a/app/src/main/java/jp/juggler/subwaytooter/dialog/DlgFocusPoint.kt +++ b/app/src/main/java/jp/juggler/subwaytooter/dialog/DlgFocusPoint.kt @@ -24,6 +24,7 @@ class DlgFocusPoint(val activity : Activity, val attachment : TootAttachment) : View.OnClickListener { companion object { + val log = LogCategory("DlgFocusPoint") } @@ -57,7 +58,7 @@ class DlgFocusPoint(val activity : Activity, val attachment : TootAttachment) : fun show() { val url = attachment.preview_url if(url == null) { - showToast(activity, false, "missing image url") + activity.showToast(false, "missing image url") return } @@ -65,7 +66,10 @@ class DlgFocusPoint(val activity : Activity, val attachment : TootAttachment) : private val options = BitmapFactory.Options() - private fun decodeBitmap(data : ByteArray, pixel_max : Int) : Bitmap? { + private fun decodeBitmap( + data : ByteArray, + @Suppress("SameParameterValue") pixel_max : Int + ) : Bitmap? { options.inJustDecodeBounds = true options.inScaled = false options.outWidth = 0 @@ -92,7 +96,7 @@ class DlgFocusPoint(val activity : Activity, val attachment : TootAttachment) : override fun background(client : TootApiClient) : TootApiResult? { try { - val(result,data) = client.getHttpBytes(url) + val (result, data) = client.getHttpBytes(url) data ?: return result bitmap = decodeBitmap(data, 1024) if(bitmap == null) return TootApiResult("image decode failed.") @@ -105,7 +109,7 @@ class DlgFocusPoint(val activity : Activity, val attachment : TootAttachment) : override fun handleResult(result : TootApiResult?) { val bitmap = this.bitmap if(bitmap == null) { - showToast(activity, true, result?.error ?: "?") + activity.showToast(true, result?.error ?: "?") dialog.dismissSafe() return } diff --git a/app/src/main/java/jp/juggler/subwaytooter/dialog/DlgListMember.kt b/app/src/main/java/jp/juggler/subwaytooter/dialog/DlgListMember.kt index 92d5770b..7b0e0525 100644 --- a/app/src/main/java/jp/juggler/subwaytooter/dialog/DlgListMember.kt +++ b/app/src/main/java/jp/juggler/subwaytooter/dialog/DlgListMember.kt @@ -134,7 +134,7 @@ class DlgListMember( this.list_owner = a if(a == null) { btnListOwner.setText(R.string.not_selected) - btnListOwner.setTextColor(getAttributeColor(activity, android.R.attr.textColorPrimary)) + btnListOwner.setTextColor(activity.getAttributeColor( android.R.attr.textColorPrimary)) btnListOwner.setBackgroundResource(R.drawable.btn_bg_transparent_round6dp) // @@ -148,7 +148,7 @@ class DlgListMember( btnListOwner.setBackgroundResource(R.drawable.btn_bg_transparent_round6dp) } btnListOwner.textColor = ac.color_fg.notZero() - ?: getAttributeColor(activity, android.R.attr.textColorPrimary) + ?: activity.getAttributeColor( android.R.attr.textColorPrimary) } loadLists() @@ -175,7 +175,7 @@ class DlgListMember( val (r1, ar) = client.syncAccountByAcct(list_owner, target_user_full_acct) r1 ?: return null // cancelled. val local_who = ar?.get() // may null - if(local_who == null) showToast(activity, true, r1.error) + if(local_who == null) activity.showToast( true, r1.error) this@DlgListMember.local_who = local_who @@ -241,7 +241,7 @@ class DlgListMember( val error = result.error if(error?.isNotEmpty() == true) { - showToast(activity, true, result.error) + activity.showToast( true, result.error) } } @@ -268,14 +268,14 @@ class DlgListMember( callback = object : DlgTextInput.Callback { override fun onEmptyError() { - showToast(activity, false, R.string.list_name_empty) + activity.showToast( false, R.string.list_name_empty) } override fun onOK(dialog : Dialog, text : String) { val list_owner = this@DlgListMember.list_owner if(list_owner == null) { - showToast(activity, false, "list owner is not selected.") + activity.showToast( false, "list owner is not selected.") return } @@ -376,14 +376,14 @@ class DlgListMember( val list_owner = this@DlgListMember.list_owner if(list_owner == null) { - showToast(activity, false, "list owner is not selected") + activity.showToast( false, "list owner is not selected") revokeCheckedChanged(isChecked) return } val local_who = this@DlgListMember.local_who if(local_who == null) { - showToast(activity, false, "target user is not synchronized") + activity.showToast( false, "target user is not synchronized") revokeCheckedChanged(isChecked) return } diff --git a/app/src/main/java/jp/juggler/subwaytooter/dialog/EmojiPicker.kt b/app/src/main/java/jp/juggler/subwaytooter/dialog/EmojiPicker.kt index 3a27149a..fb4e52e7 100644 --- a/app/src/main/java/jp/juggler/subwaytooter/dialog/EmojiPicker.kt +++ b/app/src/main/java/jp/juggler/subwaytooter/dialog/EmojiPicker.kt @@ -5,11 +5,9 @@ import android.app.Activity import android.app.Dialog import android.graphics.Typeface import android.graphics.drawable.PictureDrawable -import android.os.Build import android.util.SparseArray import android.view.* import android.widget.* -import androidx.core.view.ViewCompat import androidx.viewpager.widget.ViewPager import com.astuetz.PagerSlidingTabStrip import com.bumptech.glide.Glide @@ -44,6 +42,7 @@ class EmojiPicker( class SkinTone(val suffix_list : Array) { companion object { + fun create(vararg suffix_list : String) : SkinTone { return SkinTone(suffix_list) } @@ -269,8 +268,7 @@ class EmojiPicker( setTypeface(typeface, Typeface.BOLD) - textColor = - getAttributeColor(this@EmojiPicker.activity, R.attr.colorContentText) + textColor = this@EmojiPicker.activity.getAttributeColor(R.attr.colorContentText) textSize = 16f // SP単位 text = when(val name = it.key) { @@ -542,7 +540,7 @@ class EmojiPicker( val pref = App1.pref - if( Pref.bpEmojiPickerCloseOnSelected(pref)) + if(Pref.bpEmojiPickerCloseOnSelected(pref)) dialog.dismissSafe() // Recentをロード(他インスタンスの絵文字を含む) diff --git a/app/src/main/java/jp/juggler/subwaytooter/dialog/LoginForm.kt b/app/src/main/java/jp/juggler/subwaytooter/dialog/LoginForm.kt index 3eb4db7e..3b43e39e 100644 --- a/app/src/main/java/jp/juggler/subwaytooter/dialog/LoginForm.kt +++ b/app/src/main/java/jp/juggler/subwaytooter/dialog/LoginForm.kt @@ -19,6 +19,7 @@ import java.net.IDN import java.util.* object LoginForm { + private val log = LogCategory("LoginForm") private class StringArray : ArrayList() @@ -107,10 +108,10 @@ object LoginForm { when { instance.isEmpty() -> - showToast(activity, true, R.string.instance_not_specified) + activity.showToast(true, R.string.instance_not_specified) instance.contains("/") || instance.contains("@") -> - showToast(activity, true, R.string.instance_not_need_slash) + activity.showToast(true, R.string.instance_not_need_slash) else -> { val actionPos = spAction.selectedItemPosition @@ -124,7 +125,7 @@ object LoginForm { } view.findViewById(R.id.btnCancel).setOnClickListener { dialog.cancel() } - val instance_list = HashSet().apply{ + val instance_list = HashSet().apply { try { activity.resources.openRawResource(R.raw.server_list).use { inStream -> val br = BufferedReader(InputStreamReader(inStream, "UTF-8")) @@ -133,8 +134,8 @@ object LoginForm { br.readLine()?.trim { it <= ' ' }?.toLowerCase(Locale.JAPAN) ?: break if(s.isEmpty()) continue add(s) - add(IDN.toASCII(s,IDN.ALLOW_UNASSIGNED)) - add(IDN.toUnicode(s,IDN.ALLOW_UNASSIGNED)) + add(IDN.toASCII(s, IDN.ALLOW_UNASSIGNED)) + add(IDN.toUnicode(s, IDN.ALLOW_UNASSIGNED)) } } } catch(ex : Throwable) { diff --git a/app/src/main/java/jp/juggler/subwaytooter/dialog/ReportForm.kt b/app/src/main/java/jp/juggler/subwaytooter/dialog/ReportForm.kt index 895dd489..e5a5e63b 100644 --- a/app/src/main/java/jp/juggler/subwaytooter/dialog/ReportForm.kt +++ b/app/src/main/java/jp/juggler/subwaytooter/dialog/ReportForm.kt @@ -23,35 +23,35 @@ object ReportForm { access_info : SavedAccount, who : TootAccount, status : TootStatus?, - onClickOk : (dialog : Dialog, comment : String,forward:Boolean) -> Unit + onClickOk : (dialog : Dialog, comment : String, forward : Boolean) -> Unit ) { val view = activity.layoutInflater.inflate(R.layout.dlg_report_user, null, false) - val tvUser :TextView = view.findViewById(R.id.tvUser) - val tvStatusCaption :TextView = view.findViewById(R.id.tvStatusCaption) - val tvStatus :TextView = view.findViewById(R.id.tvStatus) - val etComment :EditText = view.findViewById(R.id.etComment) + val tvUser : TextView = view.findViewById(R.id.tvUser) + val tvStatusCaption : TextView = view.findViewById(R.id.tvStatusCaption) + val tvStatus : TextView = view.findViewById(R.id.tvStatus) + val etComment : EditText = view.findViewById(R.id.etComment) val cbForward : CheckBox = view.findViewById(R.id.cbForward) - val tvForwardDesc:TextView = view.findViewById(R.id.tvForwardDesc) - val canForward = !access_info.matchHost( who) + val tvForwardDesc : TextView = view.findViewById(R.id.tvForwardDesc) + val canForward = ! access_info.matchHost(who) cbForward.isChecked = false - if(!canForward){ + if(! canForward) { cbForward.visibility = View.GONE tvForwardDesc.visibility = View.GONE - }else{ + } else { cbForward.visibility = View.VISIBLE tvForwardDesc.visibility = View.VISIBLE - cbForward.text = activity.getString(R.string.report_forward_to,who.apDomain.pretty) + cbForward.text = activity.getString(R.string.report_forward_to, who.apDomain.pretty) } tvUser.text = who.acct.pretty - if( status == null){ + if(status == null) { tvStatusCaption.visibility = View.GONE tvStatus.visibility = View.GONE - }else{ + } else { tvStatus.text = status.decoded_content } @@ -60,11 +60,11 @@ object ReportForm { view.findViewById(R.id.btnOk).setOnClickListener(View.OnClickListener { val comment = etComment.text.toString().trim() if(comment.isEmpty()) { - showToast(activity, true, R.string.comment_empty) + activity.showToast(true, R.string.comment_empty) return@OnClickListener } - onClickOk(dialog, comment,cbForward.isChecked) + onClickOk(dialog, comment, cbForward.isChecked) }) view.findViewById(R.id.btnCancel).setOnClickListener { dialog.cancel() } diff --git a/app/src/main/java/jp/juggler/subwaytooter/table/SavedAccount.kt b/app/src/main/java/jp/juggler/subwaytooter/table/SavedAccount.kt index 3da1f1d7..e8c03583 100644 --- a/app/src/main/java/jp/juggler/subwaytooter/table/SavedAccount.kt +++ b/app/src/main/java/jp/juggler/subwaytooter/table/SavedAccount.kt @@ -19,7 +19,7 @@ class SavedAccount( val db_id : Long, acctArg : String, apiHostArg : String? = null, - apDomainArg : String? = null, + apDomainArg : String? = null, var token_info : JsonObject? = null, var loginAccount : TootAccount? = null, // 疑似アカウントではnull override val misskeyVersion : Int = 0 @@ -74,14 +74,13 @@ class SavedAccount( var last_subscription_error : String? = null var last_push_endpoint : String? = null - init { val tmpAcct = Acct.parse(acctArg) this.username = tmpAcct.username if(username.isEmpty()) throw RuntimeException("missing username in acct") - - val tmpApiHost = apiHostArg?.notEmpty()?.let{ Host.parse(it)} - val tmpApDomain = apDomainArg?.notEmpty()?.let{ Host.parse(it)} + + val tmpApiHost = apiHostArg?.notEmpty()?.let { Host.parse(it) } + val tmpApDomain = apDomainArg?.notEmpty()?.let { Host.parse(it) } this.apiHost = tmpApiHost ?: tmpApDomain ?: tmpAcct.host ?: error("missing apiHost") this.apDomain = tmpApDomain ?: tmpApiHost ?: tmpAcct.host ?: error("missing apDomain") @@ -106,7 +105,7 @@ class SavedAccount( context, LinkHelper.create( apiHostArg = this@SavedAccount.apiHost, - apDomainArg = this@SavedAccount.apDomain, + apDomainArg = this@SavedAccount.apDomain, misskeyVersion = misskeyVersion ) ).account(jsonAccount) @@ -292,20 +291,19 @@ class SavedAccount( return acct.host == null || acct.host == this.apDomain } - // fun isRemoteUser(acct : String) : Boolean { // return ! isLocalUser(acct) // } fun isMe(who : TootAccount?) : Boolean = isMe(who?.acct) -// fun isMe(who_acct : String) : Boolean = isMe(Acct.parse(who_acct)) - - fun isMe(who_acct : Acct?):Boolean{ - who_acct?:return false - if( who_acct.username != this.acct.username) return false + // fun isMe(who_acct : String) : Boolean = isMe(Acct.parse(who_acct)) + + fun isMe(who_acct : Acct?) : Boolean { + who_acct ?: return false + if(who_acct.username != this.acct.username) return false return who_acct.host == null || who_acct.host == this.acct.host } - + fun supplyBaseUrl(url : String?) : String? { return when { url == null || url.isEmpty() -> return null @@ -317,6 +315,7 @@ class SavedAccount( fun isNicoru(account : TootAccount?) : Boolean = account?.apiHost == Host.FRIENDS_NICO companion object : TableCompanion { + private val log = LogCategory("SavedAccount") const val table = "access_info" @@ -470,7 +469,7 @@ class SavedAccount( // スキーマ57から + ",$COL_NOTIFICATION_POST integer default 1" - + + ")" ) db.execSQL("create index if not exists ${table}_user on ${table}(u)") @@ -604,7 +603,7 @@ class SavedAccount( log.trace(ex) } } - + if(oldVersion < 33 && newVersion >= 33) { try { db.execSQL("alter table $table add column $COL_NOTIFICATION_REACTION integer default 1") @@ -617,7 +616,7 @@ class SavedAccount( log.trace(ex) } } - + if(oldVersion < 38 && newVersion >= 38) { try { db.execSQL("alter table $table add column $COL_DEFAULT_SENSITIVE integer default 0") @@ -716,7 +715,7 @@ class SavedAccount( fun insert( acct : String, host : String, - domain:String?, + domain : String?, account : JsonObject, token : JsonObject, misskeyVersion : Int = 0 @@ -725,7 +724,7 @@ class SavedAccount( val cv = ContentValues() cv.put(COL_USER, acct) cv.put(COL_HOST, host) - cv.putOrNull(COL_DOMAIN,domain) + cv.putOrNull(COL_DOMAIN, domain) cv.put(COL_ACCOUNT, account.toString()) cv.put(COL_TOKEN, token.toString()) cv.put(COL_MISSKEY_VERSION, misskeyVersion) @@ -792,7 +791,7 @@ class SavedAccount( } catch(ex : Throwable) { log.trace(ex) log.e(ex, "loadAccountList failed.") - showToast(context, true, ex.withCaption("(SubwayTooter) broken in-app database?")) + context.showToast(true, ex.withCaption("(SubwayTooter) broken in-app database?")) } return result @@ -893,47 +892,47 @@ class SavedAccount( return 0L } - fun isNicoru(acct:Acct) : Boolean { + fun isNicoru(acct : Acct) : Boolean { return acct.host == Host.FRIENDS_NICO } -// private fun charAtLower(src : CharSequence, pos : Int) : Char { -// val c = src[pos] -// return if(c >= 'a' && c <= 'z') c - ('a' - 'A') else c -// } -// -// @Suppress("SameParameterValue") -// private fun host_match( -// a : CharSequence, -// a_startArg : Int, -// b : CharSequence, -// b_startArg : Int -// ) : Boolean { -// var a_start = a_startArg -// var b_start = b_startArg -// -// val a_end = a.length -// val b_end = b.length -// -// var a_remain = a_end - a_start -// val b_remain = b_end - b_start -// -// // 文字数が違う -// if(a_remain != b_remain) return false -// -// // 文字数がゼロ -// if(a_remain <= 0) return true -// -// // 末尾の文字が違う -// if(charAtLower(a, a_end - 1) != charAtLower(b, b_end - 1)) return false -// -// // 先頭からチェック -// while(a_remain -- > 0) { -// if(charAtLower(a, a_start ++) != charAtLower(b, b_start ++)) return false -// } -// -// return true -// } + // private fun charAtLower(src : CharSequence, pos : Int) : Char { + // val c = src[pos] + // return if(c >= 'a' && c <= 'z') c - ('a' - 'A') else c + // } + // + // @Suppress("SameParameterValue") + // private fun host_match( + // a : CharSequence, + // a_startArg : Int, + // b : CharSequence, + // b_startArg : Int + // ) : Boolean { + // var a_start = a_startArg + // var b_start = b_startArg + // + // val a_end = a.length + // val b_end = b.length + // + // var a_remain = a_end - a_start + // val b_remain = b_end - b_start + // + // // 文字数が違う + // if(a_remain != b_remain) return false + // + // // 文字数がゼロ + // if(a_remain <= 0) return true + // + // // 末尾の文字が違う + // if(charAtLower(a, a_end - 1) != charAtLower(b, b_end - 1)) return false + // + // // 先頭からチェック + // while(a_remain -- > 0) { + // if(charAtLower(a, a_start ++) != charAtLower(b, b_start ++)) return false + // } + // + // return true + // } private val account_comparator = Comparator { a, b -> var i : Int @@ -1065,7 +1064,7 @@ class SavedAccount( fun updateNotificationError(text : String?) { this.last_notification_error = text - if(db_id != INVALID_DB_ID){ + if(db_id != INVALID_DB_ID) { val cv = ContentValues() when(text) { null -> cv.putNull(COL_LAST_NOTIFICATION_ERROR) @@ -1077,7 +1076,7 @@ class SavedAccount( fun updateSubscriptionError(text : String?) { this.last_subscription_error = text - if(db_id != INVALID_DB_ID){ + if(db_id != INVALID_DB_ID) { val cv = ContentValues() when(text) { null -> cv.putNull(COL_LAST_SUBSCRIPTION_ERROR) @@ -1089,7 +1088,7 @@ class SavedAccount( fun updateLastPushEndpoint(text : String?) { this.last_push_endpoint = text - if(db_id != INVALID_DB_ID){ + if(db_id != INVALID_DB_ID) { val cv = ContentValues() when(text) { null -> cv.putNull(COL_LAST_PUSH_ENDPOINT) @@ -1107,5 +1106,4 @@ class SavedAccount( override fun hashCode() : Int = acct.hashCode() - } diff --git a/app/src/main/java/jp/juggler/subwaytooter/util/AppOpener.kt b/app/src/main/java/jp/juggler/subwaytooter/util/AppOpener.kt new file mode 100644 index 00000000..dca03a88 --- /dev/null +++ b/app/src/main/java/jp/juggler/subwaytooter/util/AppOpener.kt @@ -0,0 +1,163 @@ +package jp.juggler.subwaytooter.util + +import android.content.ComponentName +import android.content.Intent +import android.content.pm.PackageManager +import android.content.pm.ResolveInfo +import android.net.Uri +import android.os.Build +import android.os.Bundle +import android.app.Activity +import androidx.browser.customtabs.CustomTabsIntent +import jp.juggler.subwaytooter.Pref +import jp.juggler.subwaytooter.R +import jp.juggler.subwaytooter.api.entity.TootAttachment +import jp.juggler.subwaytooter.dialog.DlgAppPicker +import jp.juggler.subwaytooter.pref +import jp.juggler.util.* + +private val log = LogCategory("AppOpener") + +// returns true if activity is opened. +// returns false if fallback required +private fun Activity.startActivityExcludeMyApp( + intent : Intent, + startAnimationBundle : Bundle? = null +) : Boolean { + try { + val pm = packageManager !! + val myName = packageName + + val filter : (ResolveInfo) -> Boolean = { + it.activityInfo.packageName != myName && + it.activityInfo.exported && + - 1 == it.activityInfo.packageName.indexOf("com.huawei.android.internal") + } + + // resolveActivity がこのアプリ以外のActivityを返すなら、それがベストなんだろう + // ただしAndroid M以降はMATCH_DEFAULT_ONLYだと「常時」が設定されてないとnullを返す + val ri = pm.resolveActivity( + intent, + if(Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) { + PackageManager.MATCH_ALL + } else { + PackageManager.MATCH_DEFAULT_ONLY + } + )?.takeIf(filter) + + if(ri != null) { + intent.setClassName(ri.activityInfo.packageName, ri.activityInfo.name) + startActivity(intent, startAnimationBundle) + return true + } + + return DlgAppPicker( + this, + intent, + autoSelect = true, + filter = filter + ) { + try { + intent.component = it.cn() + startActivity(intent, startAnimationBundle) + } catch(ex : Throwable) { + log.trace(ex) + showToast(ex, "can't open. ${intent.data}") + } + }.show() + + } catch(ex : Throwable) { + log.trace(ex) + showToast(ex, "can't open. ${intent.data}") + return true // fallback not required in this case + } +} + +fun Activity.openBrowser(uri : Uri?) { + if(uri != null) { + val rv = startActivityExcludeMyApp(Intent(Intent.ACTION_VIEW, uri)) + if(! rv) showToast(true, "there is no app that can open $uri") + } +} + +fun Activity.openBrowser(url : String?) = openBrowser(url.mayUri()) + +// ubway Tooterの「アプリ設定/挙動/リンクを開く際にCustom Tabsを使わない」をONにして +// 投稿のコンテキストメニューの「トゥートへのアクション/Webページを開く」「ユーザへのアクション/Webページを開く」を使うと +// 投げたインテントをST自身が受け取って「次のアカウントから開く」ダイアログが出て +// 「Webページを開く」をまた押すと無限ループしてダイアログの影が徐々に濃くなりそのうち壊れる +// これを避けるには、投稿やトゥートを開く際に bpDontUseCustomTabs がオンならST以外のアプリを列挙したアプリ選択ダイアログを出すしかない +fun Activity.openCustomTabOrBrowser(url : String?) { + url ?: return + if(! Pref.bpDontUseCustomTabs(pref())) { + openCustomTab(url) + } else { + openBrowser(url) + } +} + +// Chrome Custom Tab を開く +fun Activity.openCustomTab(url : String?) { + url ?: return + + if(url.isEmpty()) { + showToast(false, "URL is empty string.") + return + } + + val pref = pref() + if(Pref.bpDontUseCustomTabs(pref)) { + openCustomTabOrBrowser(url) + return + } + + try { + if(url.startsWith("http") && Pref.bpPriorChrome(pref)) { + try { + // 初回はChrome指定で試す + val customTabsIntent = CustomTabsIntent.Builder() + .setToolbarColor(getAttributeColor(R.attr.colorPrimary)) + .setShowTitle(true) + .build() + + val rv = startActivityExcludeMyApp( + customTabsIntent.intent.also { + it.component = ComponentName( + "com.android.chrome", + "com.google.android.apps.chrome.Main" + ) + it.data = url.toUri() + }, + customTabsIntent.startAnimationBundle + ) + if(rv) return + } catch(ex2 : Throwable) { + log.e(ex2, "openChromeTab: missing chrome. retry to other application.") + } + } + + // Chromeがないようなのでcomponent指定なしでリトライ + val customTabsIntent = CustomTabsIntent.Builder() + .setToolbarColor(getAttributeColor(R.attr.colorPrimary)) + .setShowTitle(true) + .build() + + val rv = startActivityExcludeMyApp( + customTabsIntent.intent.also { + it.data = url.toUri() + }, + customTabsIntent.startAnimationBundle + ) + if(! rv) { + showToast(true, "the browser app is not installed.") + } + + } catch(ex : Throwable) { + log.trace(ex) + val scheme = url.mayUri()?.scheme ?: url + showToast(true, "can't open browser app for %s", scheme) + } +} + +fun Activity.openCustomTab(ta : TootAttachment) = + openCustomTab(ta.getLargeUrl(pref())) diff --git a/app/src/main/java/jp/juggler/subwaytooter/util/AsyncActivity.kt b/app/src/main/java/jp/juggler/subwaytooter/util/AsyncActivity.kt index ade08e74..14f95862 100644 --- a/app/src/main/java/jp/juggler/subwaytooter/util/AsyncActivity.kt +++ b/app/src/main/java/jp/juggler/subwaytooter/util/AsyncActivity.kt @@ -31,18 +31,6 @@ abstract class AsyncActivity : AppCompatActivity(), CoroutineScope { (job + Dispatchers.Default).cancel() } - fun showToast(bLong : Boolean, fmt : String?, vararg args : Any) = - showToast(this, bLong, fmt, *args) - - fun showToast(ex : Throwable, fmt : String?, vararg args : Any) = - showToast(this, ex, fmt, *args) - - fun showToast(bLong : Boolean, string_id : Int, vararg args : Any) = - showToast(this, bLong, string_id, *args) - - fun showToast(ex : Throwable, string_id : Int, vararg args : Any) = - showToast(this, ex, string_id, *args) - fun runWithProgress( caption : String, doInBackground : suspend CoroutineScope.(ProgressDialogEx) -> T, @@ -79,7 +67,7 @@ abstract class AsyncActivity : AppCompatActivity(), CoroutineScope { } if(result != null) afterProc(result) } catch(ex : Throwable) { - showToast(this@AsyncActivity, ex, "$caption failed.") + showToast(ex, "$caption failed.") } finally { progress.dismissSafe() try { diff --git a/app/src/main/java/jp/juggler/subwaytooter/util/CustomShare.kt b/app/src/main/java/jp/juggler/subwaytooter/util/CustomShare.kt index 5d841e94..ee7a381d 100644 --- a/app/src/main/java/jp/juggler/subwaytooter/util/CustomShare.kt +++ b/app/src/main/java/jp/juggler/subwaytooter/util/CustomShare.kt @@ -71,7 +71,7 @@ object CustomShare { label = "${context.getString(R.string.copy_to_clipboard)}(${context.getString(R.string.app_name)})" icon = ContextCompat.getDrawable(context, R.drawable.ic_copy)?.mutate()?.apply { - setTint(getAttributeColor(context, R.attr.colorVectorDrawable)) + setTint(context.getAttributeColor(R.attr.colorVectorDrawable)) setTintMode(PorterDuff.Mode.SRC_IN) } } else { @@ -105,7 +105,7 @@ object CustomShare { // convert "pkgName/className" string to ComponentName object. val cn = getCustomShareComponentName(App1.pref, target) if(cn == null) { - showToast(context, true, R.string.custom_share_app_not_found) + context.showToast(true, R.string.custom_share_app_not_found) return } val cnStr = "${cn.packageName}/${cn.className}" @@ -113,9 +113,9 @@ object CustomShare { try { val cm : ClipboardManager = systemService(context) !! cm.setPrimaryClip(ClipData.newPlainText("", text)) - showToast(context, false, R.string.copied_to_clipboard) + context.showToast(false, R.string.copied_to_clipboard) } catch(ex : Throwable) { - showToast(context, ex, "copy to clipboard failed.") + context.showToast(ex, "copy to clipboard failed.") } return } @@ -128,10 +128,10 @@ object CustomShare { context.startActivity(intent) } catch(ex : ActivityNotFoundException) { log.trace(ex) - showToast(context, true, R.string.custom_share_app_not_found) + context.showToast(true, R.string.custom_share_app_not_found) } catch(ex : Throwable) { log.trace(ex) - showToast(context, ex, "invoke() failed.") + context.showToast(ex, "invoke() failed.") } } @@ -147,7 +147,7 @@ object CustomShare { // convert "pkgName/className" string to ComponentName object. val cn = getCustomShareComponentName(App1.pref, target) if(cn == null) { - showToast(context, true, R.string.custom_share_app_not_found) + context.showToast(true, R.string.custom_share_app_not_found) return } @@ -155,7 +155,7 @@ object CustomShare { invoke(context, sv, target) } catch(ex : Throwable) { log.trace(ex) - showToast(context, ex, "invoke() failed.") + context.showToast(ex, "invoke() failed.") } } diff --git a/app/src/main/java/jp/juggler/subwaytooter/util/EmojiDecoder.kt b/app/src/main/java/jp/juggler/subwaytooter/util/EmojiDecoder.kt index ef3dc88e..549fe495 100644 --- a/app/src/main/java/jp/juggler/subwaytooter/util/EmojiDecoder.kt +++ b/app/src/main/java/jp/juggler/subwaytooter/util/EmojiDecoder.kt @@ -11,6 +11,7 @@ import jp.juggler.subwaytooter.App1 import jp.juggler.subwaytooter.Pref import jp.juggler.subwaytooter.R import jp.juggler.subwaytooter.api.entity.CustomEmoji +import jp.juggler.subwaytooter.pref import jp.juggler.subwaytooter.span.EmojiImageSpan import jp.juggler.subwaytooter.span.HighlightSpan import jp.juggler.subwaytooter.span.NetworkEmojiSpan @@ -356,7 +357,7 @@ object EmojiDecoder { val useEmojioneShortcode = when(val context = options.context) { null -> false - else -> Pref.bpEmojioneShortcode( Pref.pref(context)) + else -> Pref.bpEmojioneShortcode( context.pref()) } splitShortCode(s, callback = object : ShortCodeSplitterCallback { diff --git a/app/src/main/java/jp/juggler/subwaytooter/util/PopupAutoCompleteAcct.kt b/app/src/main/java/jp/juggler/subwaytooter/util/PopupAutoCompleteAcct.kt index 73f3412c..92fc51e4 100644 --- a/app/src/main/java/jp/juggler/subwaytooter/util/PopupAutoCompleteAcct.kt +++ b/app/src/main/java/jp/juggler/subwaytooter/util/PopupAutoCompleteAcct.kt @@ -14,7 +14,6 @@ import android.widget.LinearLayout import android.widget.PopupWindow import androidx.core.content.ContextCompat import jp.juggler.subwaytooter.App1 -import jp.juggler.subwaytooter.Pref import jp.juggler.subwaytooter.R import jp.juggler.subwaytooter.api.entity.Acct import jp.juggler.subwaytooter.view.MyEditText @@ -47,7 +46,7 @@ internal class PopupAutoCompleteAcct( private val popup_width : Int val handler : Handler - private val pref : SharedPreferences = Pref.pref(activity) + private val pref : SharedPreferences = App1.pref private var popup_rows : Int = 0 @@ -98,7 +97,7 @@ internal class PopupAutoCompleteAcct( run { val v = activity.layoutInflater .inflate(R.layout.lv_spinner_dropdown, llItems, false) as CheckedTextView - v.setTextColor(getAttributeColor(activity, android.R.attr.textColorPrimary)) + v.setTextColor(activity.getAttributeColor(android.R.attr.textColorPrimary)) v.setText(R.string.close) v.setOnClickListener { acct_popup.dismiss() } llItems.addView(v) @@ -108,7 +107,7 @@ internal class PopupAutoCompleteAcct( if(picker_caption != null && picker_callback != null) { val v = activity.layoutInflater .inflate(R.layout.lv_spinner_dropdown, llItems, false) as CheckedTextView - v.setTextColor(getAttributeColor(activity, android.R.attr.textColorPrimary)) + v.setTextColor(activity.getAttributeColor(android.R.attr.textColorPrimary)) v.text = picker_caption v.setOnClickListener { acct_popup.dismiss() @@ -126,7 +125,7 @@ internal class PopupAutoCompleteAcct( val acct = acct_list[i] val v = activity.layoutInflater .inflate(R.layout.lv_spinner_dropdown, llItems, false) as CheckedTextView - v.setTextColor(getAttributeColor(activity, android.R.attr.textColorPrimary)) + v.setTextColor(activity.getAttributeColor(android.R.attr.textColorPrimary)) v.text = acct if(acct is Spannable) { NetworkEmojiInvalidator(handler, v).register(acct) diff --git a/app/src/main/java/jp/juggler/subwaytooter/util/PostHelper.kt b/app/src/main/java/jp/juggler/subwaytooter/util/PostHelper.kt index afbbb498..036ab91e 100644 --- a/app/src/main/java/jp/juggler/subwaytooter/util/PostHelper.kt +++ b/app/src/main/java/jp/juggler/subwaytooter/util/PostHelper.kt @@ -38,6 +38,7 @@ class PostHelper( ) { companion object { + private val log = LogCategory("PostHelper") private val reCharsNotEmoji = "[^0-9A-Za-z_-]".asciiPattern() @@ -47,6 +48,7 @@ class PostHelper( } interface PostCompleteCallback { + fun onPostComplete(target_account : SavedAccount, status : TootStatus) fun onScheduledPostComplete(target_account : SavedAccount) } @@ -110,14 +112,14 @@ class PostHelper( val hasAttachment = attachment_list?.isNotEmpty() ?: false if(! hasAttachment && content.isEmpty()) { - showToast(activity, true, R.string.post_error_contents_empty) + activity.showToast(true, R.string.post_error_contents_empty) return } // nullはCWチェックなしを示す // nullじゃなくてカラならエラー if(spoiler_text != null && spoiler_text.isEmpty()) { - showToast(activity, true, R.string.post_error_contents_warning_empty) + activity.showToast(true, R.string.post_error_contents_warning_empty) return } @@ -134,19 +136,19 @@ class PostHelper( if(item.isEmpty()) { if(n < 2) { - showToast(activity, true, R.string.enquete_item_is_empty, n + 1) + activity.showToast(true, R.string.enquete_item_is_empty, n + 1) return } } else { val code_count = item.codePointCount(0, item.length) if(code_count > choice_max_chars) { val over = code_count - choice_max_chars - showToast(activity, true, R.string.enquete_item_too_long, n + 1, over) + activity.showToast(true, R.string.enquete_item_too_long, n + 1, over) return } else if(n > 0) { for(i in 0 until n) { if(item == enquete_items[i]) { - showToast(activity, true, R.string.enquete_item_duplicate, n + 1) + activity.showToast(true, R.string.enquete_item_duplicate, n + 1) return } } @@ -278,7 +280,7 @@ class PostHelper( // 確認を終えたらボタン連打判定 if(last_post_task?.get()?.isActive == true) { - showToast(activity, false, R.string.post_button_tapped_repeatly) + activity.showToast(false, R.string.post_button_tapped_repeatly) return } @@ -286,371 +288,372 @@ class PostHelper( val delta = now - last_post_tapped last_post_tapped = now if(delta < 1000L) { - showToast(activity, false, R.string.post_button_tapped_repeatly) + activity.showToast(false, R.string.post_button_tapped_repeatly) return } // 全ての確認を終えたらバックグラウンドでの処理を開始する - last_post_task = WeakReference(TootTaskRunner(activity - , progressSetupCallback = { progressDialog -> + last_post_task = + WeakReference(TootTaskRunner(activity, progressSetupCallback = { progressDialog -> progressDialog.setCanceledOnTouchOutside(false) } - ).run(account, object : TootTask { - - var status : TootStatus? = null - - var credential_tmp : TootAccount? = null - - - - var scheduledStatusSucceeded = false - - fun getCredential(client : TootApiClient,parser:TootParser) : TootApiResult? { - val result = client.request("/api/v1/accounts/verify_credentials") - credential_tmp = parser.account(result?.jsonObject) - return result - } - - override fun background(client : TootApiClient) : TootApiResult? { - val parser = TootParser(activity, account) + ).run(account, object : TootTask { - var result : TootApiResult? + var status : TootStatus? = null - // 元の投稿を削除する - if(redraft_status_id != null) { - result = if(account.isMisskey) { - val params = account.putMisskeyApiToken(JsonObject()).apply { - put("noteId", redraft_status_id) - } - client.request( - "/api/notes/delete", - params.toPostRequestBuilder() - ) - } else { - client.request( - "/api/v1/statuses/$redraft_status_id", - Request.Builder().delete() - ) - - } - log.d("delete redraft. result=$result") - Thread.sleep(2000L) - } else if(scheduledId != null) { - val r1 = client.request( - "/api/v1/scheduled_statuses/$scheduledId", - Request.Builder().delete() - ) - log.d("delete old scheduled status. result=$r1") - Thread.sleep(2000L) - } + var credential_tmp : TootAccount? = null - var visibility_checked : TootVisibility? = visibility + var scheduledStatusSucceeded = false - val (instance, ri) = TootInstance.get(client) - instance ?: return ri - - if(instance.instanceType == TootInstance.InstanceType.Pixelfed) { - if(in_reply_to_id != null && attachment_list?.isNotEmpty() == true) { - return TootApiResult(activity.getString(R.string.pixelfed_does_not_allow_reply_with_media)) - } - if(in_reply_to_id == null && attachment_list?.isNotEmpty() != true) { - return TootApiResult(activity.getString(R.string.pixelfed_does_not_allow_post_without_media)) - } - } - - if(visibility == TootVisibility.WebSetting) { - visibility_checked = - if(account.isMisskey || instance.versionGE(TootInstance.VERSION_1_6)) { - null - } else { - val r2 = getCredential(client,parser) - val credential_tmp = this.credential_tmp ?: return r2 - val privacy = credential_tmp.source?.privacy - ?: return TootApiResult(activity.getString(R.string.cant_get_web_setting_visibility)) - TootVisibility.parseMastodon(privacy) - } - } - - val json = JsonObject() - try { - if(account.isMisskey) { - account.putMisskeyApiToken(json) - json["text"] = EmojiDecoder.decodeShortCode( - content, - emojiMapCustom = emojiMapCustom - ) - if(visibility_checked != null) { - - if(visibility_checked == TootVisibility.DirectSpecified || visibility_checked == TootVisibility.DirectPrivate) { - val userIds = JsonArray() - - val m = TootAccount.reMisskeyMentionPost.matcher(content) - while(m.find()) { - val username = m.groupEx(1) - val host = m.groupEx(2) // may null - - result = client.request( - "/api/users/show", - account.putMisskeyApiToken().apply { - if(username?.isNotEmpty() == true) - put("username", username) - if(host?.isNotEmpty() == true) - put("host", host) - }.toPostRequestBuilder() - ) - val id = result?.jsonObject?.string("id") - if(id?.isNotEmpty() == true) { - userIds.add(id) - } - } - json["visibility"] = when { - userIds.isNotEmpty() -> { - json["visibleUserIds"] = userIds - "specified" - } - - account.misskeyVersion >= 11 -> "specified" - else -> "private" - } - } else { - val localVis = visibility_checked.strMisskey.replace( - "^local-".toRegex(), - "" - ) - if(localVis != visibility_checked.strMisskey) { - json["localOnly"] = true - json["visibility"] = localVis - } else { - json["visibility"] = visibility_checked.strMisskey - } - } - } - - if(spoiler_text?.isNotEmpty() == true) { - json["cw"] = EmojiDecoder.decodeShortCode( - spoiler_text, - emojiMapCustom = emojiMapCustom - ) - } - - if(in_reply_to_id != null) { - if(useQuoteToot) { - json["renoteId"] = in_reply_to_id.toString() - } else { - json["replyId"] = in_reply_to_id.toString() - } - } - - json["viaMobile"] = true - - if(attachment_list != null) { - val array = JsonArray() - for(pa in attachment_list) { - val a = pa.attachment ?: continue - // Misskeyは画像の再利用に問題がないので redraftとバージョンのチェックは行わない - array.add(a.id.toString()) - - // Misskeyの場合、NSFWするにはアップロード済みの画像を drive/files/update で更新する - if(bNSFW) { - val r = client.request( - "/api/drive/files/update", - account.putMisskeyApiToken().apply { - put("fileId", a.id.toString()) - put("isSensitive", true) - } - .toPostRequestBuilder() - ) - if(r == null || r.error != null) return r - } - } - if(array.isNotEmpty()) json["mediaIds"] = array - } - - if(enquete_items?.isNotEmpty() == true) { - val choices = JsonArray().apply { - for(item in enquete_items) { - val text = EmojiDecoder.decodeShortCode( - item, - emojiMapCustom = emojiMapCustom - ) - if(text.isEmpty()) continue - add(text) - } - } - if(choices.isNotEmpty()) { - json["poll"] = jsonObject { - put("choices", choices) - } - } - } - - if(scheduledAt != 0L) { - return TootApiResult("misskey has no scheduled status API") - } - - } else { - json["status"] = EmojiDecoder.decodeShortCode( - content, - emojiMapCustom = emojiMapCustom - ) - if(visibility_checked != null) { - json["visibility"] = visibility_checked.strMastodon - } - json["sensitive"] = bNSFW - json["spoiler_text"] = EmojiDecoder.decodeShortCode( - spoiler_text ?: "", - emojiMapCustom = emojiMapCustom - ) - - if(in_reply_to_id != null) { - if(useQuoteToot) { - json["quote_id"] = in_reply_to_id.toString() - } else { - json["in_reply_to_id"] = in_reply_to_id.toString() - } - } - - if(attachment_list != null) { - json["media_ids"] = jsonArray { - for(pa in attachment_list) { - val a = pa.attachment ?: continue - if(a.redraft && ! instance.versionGE(TootInstance.VERSION_2_4_1)) continue - add(a.id.toString()) - } - } - } - - if(enquete_items?.isNotEmpty() == true) { - if(poll_type == TootPollsType.Mastodon) { - json["poll"] = jsonObject { - put("multiple", poll_multiple_choice) - put("hide_totals", poll_hide_totals) - put("expires_in", poll_expire_seconds) - put("options", - enquete_items.map { - EmojiDecoder.decodeShortCode( - it, - emojiMapCustom = emojiMapCustom - ) - } - .toJsonArray() - ) - } - } else { - json["isEnquete"] = true - json["enquete_items"] = enquete_items.map { - EmojiDecoder.decodeShortCode( - it, - emojiMapCustom = emojiMapCustom - ) - }.toJsonArray() - } - } - - if(scheduledAt != 0L) { - if(! instance.versionGE(TootInstance.VERSION_2_7_0_rc1)) { - return TootApiResult(activity.getString(R.string.scheduled_status_requires_mastodon_2_7_0)) - } - // UTCの日時を渡す - val c = GregorianCalendar.getInstance(TimeZone.getTimeZone("UTC")) - c.timeInMillis = scheduledAt - val sv = String.format( - "%d-%02d-%02d %02d:%02d:%02d", - c.get(Calendar.YEAR), - c.get(Calendar.MONTH) + 1, - c.get(Calendar.DAY_OF_MONTH), - c.get(Calendar.HOUR_OF_DAY), - c.get(Calendar.MINUTE), - c.get(Calendar.SECOND) - ) - json["scheduled_at"] = sv - } - - } - } catch(ex : JsonException) { - log.trace(ex) - log.e(ex, "status encoding failed.") - } - - val body_string = json.toString() - - val request_builder = body_string.toRequestBody(MEDIA_TYPE_JSON).toPost() - - if(! Pref.bpDontDuplicationCheck(pref)) { - val digest = (body_string + account.acct.ascii).digestSHA256Hex() - request_builder.header("Idempotency-Key", digest) - } - - result = if(account.isMisskey) { - // log.d("misskey json %s", body_string) - client.request("/api/notes/create", request_builder) - } else { - client.request("/api/v1/statuses", request_builder) - } - - val jsonObject = result?.jsonObject - - if(scheduledAt != 0L && jsonObject != null) { - // {"id":"3","scheduled_at":"2019-01-06T07:08:00.000Z","media_attachments":[]} - scheduledStatusSucceeded = true + fun getCredential( + client : TootApiClient, + parser : TootParser + ) : TootApiResult? { + val result = client.request("/api/v1/accounts/verify_credentials") + credential_tmp = parser.account(result?.jsonObject) return result } - val status = parser.status( - if(account.isMisskey) { - result?.jsonObject?.jsonObject("createdNote") ?: result?.jsonObject - } else { - result?.jsonObject - } - ) - this.status = status - if(status != null) { + override fun background(client : TootApiClient) : TootApiResult? { + val parser = TootParser(activity, account) - // タグを覚えておく - val s = status.decoded_content - val span_list = s.getSpans(0, s.length, MyClickableSpan::class.java) - if(span_list != null) { - val tag_list = ArrayList(span_list.size) - for(span in span_list) { - val start = s.getSpanStart(span) - val end = s.getSpanEnd(span) - val text = s.subSequence(start, end).toString() - if(text.startsWith("#")) { - tag_list.add(text.substring(1)) + var result : TootApiResult? + + // 元の投稿を削除する + if(redraft_status_id != null) { + result = if(account.isMisskey) { + val params = account.putMisskeyApiToken(JsonObject()).apply { + put("noteId", redraft_status_id) } + client.request( + "/api/notes/delete", + params.toPostRequestBuilder() + ) + } else { + client.request( + "/api/v1/statuses/$redraft_status_id", + Request.Builder().delete() + ) + } - val count = tag_list.size - if(count > 0) { - TagSet.saveList(System.currentTimeMillis(), tag_list, 0, count) + log.d("delete redraft. result=$result") + Thread.sleep(2000L) + } else if(scheduledId != null) { + val r1 = client.request( + "/api/v1/scheduled_statuses/$scheduledId", + Request.Builder().delete() + ) + log.d("delete old scheduled status. result=$r1") + Thread.sleep(2000L) + } + + var visibility_checked : TootVisibility? = visibility + + val (instance, ri) = TootInstance.get(client) + instance ?: return ri + + if(instance.instanceType == TootInstance.InstanceType.Pixelfed) { + if(in_reply_to_id != null && attachment_list?.isNotEmpty() == true) { + return TootApiResult(activity.getString(R.string.pixelfed_does_not_allow_reply_with_media)) + } + if(in_reply_to_id == null && attachment_list?.isNotEmpty() != true) { + return TootApiResult(activity.getString(R.string.pixelfed_does_not_allow_post_without_media)) + } + } + + if(visibility == TootVisibility.WebSetting) { + visibility_checked = + if(account.isMisskey || instance.versionGE(TootInstance.VERSION_1_6)) { + null + } else { + val r2 = getCredential(client, parser) + val credential_tmp = this.credential_tmp ?: return r2 + val privacy = credential_tmp.source?.privacy + ?: return TootApiResult(activity.getString(R.string.cant_get_web_setting_visibility)) + TootVisibility.parseMastodon(privacy) + } + } + + val json = JsonObject() + try { + if(account.isMisskey) { + account.putMisskeyApiToken(json) + json["text"] = EmojiDecoder.decodeShortCode( + content, + emojiMapCustom = emojiMapCustom + ) + if(visibility_checked != null) { + + if(visibility_checked == TootVisibility.DirectSpecified || visibility_checked == TootVisibility.DirectPrivate) { + val userIds = JsonArray() + + val m = TootAccount.reMisskeyMentionPost.matcher(content) + while(m.find()) { + val username = m.groupEx(1) + val host = m.groupEx(2) // may null + + result = client.request( + "/api/users/show", + account.putMisskeyApiToken().apply { + if(username?.isNotEmpty() == true) + put("username", username) + if(host?.isNotEmpty() == true) + put("host", host) + }.toPostRequestBuilder() + ) + val id = result?.jsonObject?.string("id") + if(id?.isNotEmpty() == true) { + userIds.add(id) + } + } + json["visibility"] = when { + userIds.isNotEmpty() -> { + json["visibleUserIds"] = userIds + "specified" + } + + account.misskeyVersion >= 11 -> "specified" + else -> "private" + } + } else { + val localVis = visibility_checked.strMisskey.replace( + "^local-".toRegex(), + "" + ) + if(localVis != visibility_checked.strMisskey) { + json["localOnly"] = true + json["visibility"] = localVis + } else { + json["visibility"] = visibility_checked.strMisskey + } + } + } + + if(spoiler_text?.isNotEmpty() == true) { + json["cw"] = EmojiDecoder.decodeShortCode( + spoiler_text, + emojiMapCustom = emojiMapCustom + ) + } + + if(in_reply_to_id != null) { + if(useQuoteToot) { + json["renoteId"] = in_reply_to_id.toString() + } else { + json["replyId"] = in_reply_to_id.toString() + } + } + + json["viaMobile"] = true + + if(attachment_list != null) { + val array = JsonArray() + for(pa in attachment_list) { + val a = pa.attachment ?: continue + // Misskeyは画像の再利用に問題がないので redraftとバージョンのチェックは行わない + array.add(a.id.toString()) + + // Misskeyの場合、NSFWするにはアップロード済みの画像を drive/files/update で更新する + if(bNSFW) { + val r = client.request( + "/api/drive/files/update", + account.putMisskeyApiToken().apply { + put("fileId", a.id.toString()) + put("isSensitive", true) + } + .toPostRequestBuilder() + ) + if(r == null || r.error != null) return r + } + } + if(array.isNotEmpty()) json["mediaIds"] = array + } + + if(enquete_items?.isNotEmpty() == true) { + val choices = JsonArray().apply { + for(item in enquete_items) { + val text = EmojiDecoder.decodeShortCode( + item, + emojiMapCustom = emojiMapCustom + ) + if(text.isEmpty()) continue + add(text) + } + } + if(choices.isNotEmpty()) { + json["poll"] = jsonObject { + put("choices", choices) + } + } + } + + if(scheduledAt != 0L) { + return TootApiResult("misskey has no scheduled status API") + } + + } else { + json["status"] = EmojiDecoder.decodeShortCode( + content, + emojiMapCustom = emojiMapCustom + ) + if(visibility_checked != null) { + json["visibility"] = visibility_checked.strMastodon + } + json["sensitive"] = bNSFW + json["spoiler_text"] = EmojiDecoder.decodeShortCode( + spoiler_text ?: "", + emojiMapCustom = emojiMapCustom + ) + + if(in_reply_to_id != null) { + if(useQuoteToot) { + json["quote_id"] = in_reply_to_id.toString() + } else { + json["in_reply_to_id"] = in_reply_to_id.toString() + } + } + + if(attachment_list != null) { + json["media_ids"] = jsonArray { + for(pa in attachment_list) { + val a = pa.attachment ?: continue + if(a.redraft && ! instance.versionGE(TootInstance.VERSION_2_4_1)) continue + add(a.id.toString()) + } + } + } + + if(enquete_items?.isNotEmpty() == true) { + if(poll_type == TootPollsType.Mastodon) { + json["poll"] = jsonObject { + put("multiple", poll_multiple_choice) + put("hide_totals", poll_hide_totals) + put("expires_in", poll_expire_seconds) + put("options", + enquete_items.map { + EmojiDecoder.decodeShortCode( + it, + emojiMapCustom = emojiMapCustom + ) + } + .toJsonArray() + ) + } + } else { + json["isEnquete"] = true + json["enquete_items"] = enquete_items.map { + EmojiDecoder.decodeShortCode( + it, + emojiMapCustom = emojiMapCustom + ) + }.toJsonArray() + } + } + + if(scheduledAt != 0L) { + if(! instance.versionGE(TootInstance.VERSION_2_7_0_rc1)) { + return TootApiResult(activity.getString(R.string.scheduled_status_requires_mastodon_2_7_0)) + } + // UTCの日時を渡す + val c = GregorianCalendar.getInstance(TimeZone.getTimeZone("UTC")) + c.timeInMillis = scheduledAt + val sv = String.format( + "%d-%02d-%02d %02d:%02d:%02d", + c.get(Calendar.YEAR), + c.get(Calendar.MONTH) + 1, + c.get(Calendar.DAY_OF_MONTH), + c.get(Calendar.HOUR_OF_DAY), + c.get(Calendar.MINUTE), + c.get(Calendar.SECOND) + ) + json["scheduled_at"] = sv + } + + } + } catch(ex : JsonException) { + log.trace(ex) + log.e(ex, "status encoding failed.") + } + + val body_string = json.toString() + + val request_builder = body_string.toRequestBody(MEDIA_TYPE_JSON).toPost() + + if(! Pref.bpDontDuplicationCheck(pref)) { + val digest = (body_string + account.acct.ascii).digestSHA256Hex() + request_builder.header("Idempotency-Key", digest) + } + + result = if(account.isMisskey) { + // log.d("misskey json %s", body_string) + client.request("/api/notes/create", request_builder) + } else { + client.request("/api/v1/statuses", request_builder) + } + + val jsonObject = result?.jsonObject + + if(scheduledAt != 0L && jsonObject != null) { + // {"id":"3","scheduled_at":"2019-01-06T07:08:00.000Z","media_attachments":[]} + scheduledStatusSucceeded = true + return result + } + + val status = parser.status( + if(account.isMisskey) { + result?.jsonObject?.jsonObject("createdNote") ?: result?.jsonObject + } else { + result?.jsonObject + } + ) + this.status = status + if(status != null) { + + // タグを覚えておく + val s = status.decoded_content + val span_list = s.getSpans(0, s.length, MyClickableSpan::class.java) + if(span_list != null) { + val tag_list = ArrayList(span_list.size) + for(span in span_list) { + val start = s.getSpanStart(span) + val end = s.getSpanEnd(span) + val text = s.subSequence(start, end).toString() + if(text.startsWith("#")) { + tag_list.add(text.substring(1)) + } + } + val count = tag_list.size + if(count > 0) { + TagSet.saveList(System.currentTimeMillis(), tag_list, 0, count) + } + } } - + return result } - return result - } - - override fun handleResult(result : TootApiResult?) { - result ?: return - val status = this.status - when { - status != null -> { - // 連投してIdempotency が同じだった場合もエラーにはならず、ここを通る - callback.onPostComplete(account, status) - return - } - - scheduledStatusSucceeded -> { - callback.onScheduledPostComplete(account) - return + + override fun handleResult(result : TootApiResult?) { + result ?: return + val status = this.status + when { + status != null -> { + // 連投してIdempotency が同じだった場合もエラーにはならず、ここを通る + callback.onPostComplete(account, status) + return + } + scheduledStatusSucceeded -> { + callback.onScheduledPostComplete(account) + return + + } + + else -> activity.showToast(true, result.error) } - - else -> showToast(activity, true, result.error) } - } - }) - ) + }) + ) } /////////////////////////////////////////////////////////////////////////////////// @@ -890,12 +893,7 @@ class PostHelper( sb.append(item.alias) sb.append(": → ") sb.setSpan( - ForegroundColorSpan( - getAttributeColor( - activity, - R.attr.colorTimeSmall - ) - ), + ForegroundColorSpan(activity.getAttributeColor(R.attr.colorTimeSmall)), start, sb.length, Spanned.SPAN_EXCLUSIVE_EXCLUSIVE @@ -922,6 +920,7 @@ class PostHelper( } interface Callback2 { + fun onTextUpdate() fun canOpenPopup() : Boolean @@ -1053,7 +1052,10 @@ class PostHelper( proc_text_changed.run() // キーボードを再度表示する - App1.getAppState(activity,"PostHelper/EmojiPicker/cb").handler.post { et.showKeyboard() } + App1.getAppState( + activity, + "PostHelper/EmojiPicker/cb" + ).handler.post { et.showKeyboard() } }.show() } @@ -1091,7 +1093,7 @@ class PostHelper( fun openFeaturedTagList(list : List?) { val ad = ActionsDialog() - list?.forEach {tag-> + list?.forEach { tag -> ad.addAction("#${tag.name}") { val et = this.et ?: return@addAction @@ -1112,7 +1114,7 @@ class PostHelper( proc_text_changed.run() } } - ad.addAction( activity.getString(R.string.input_sharp_itself)){ + ad.addAction(activity.getString(R.string.input_sharp_itself)) { val et = this.et ?: return@addAction val src = et.text ?: "" @@ -1124,7 +1126,7 @@ class PostHelper( sb.append(src.subSequence(0, start)) if(! EmojiDecoder.canStartHashtag(sb, sb.length)) sb.append(' ') sb.append('#') - + val newSelection = sb.length if(end < src_length) sb.append(src.subSequence(end, src_length)) et.text = sb diff --git a/app/src/main/java/jp/juggler/subwaytooter/util/TypeAlias.kt b/app/src/main/java/jp/juggler/subwaytooter/util/TypeAlias.kt index 575857aa..19843e36 100644 --- a/app/src/main/java/jp/juggler/subwaytooter/util/TypeAlias.kt +++ b/app/src/main/java/jp/juggler/subwaytooter/util/TypeAlias.kt @@ -4,17 +4,12 @@ import android.content.DialogInterface import jp.juggler.subwaytooter.api.TootApiResult import jp.juggler.subwaytooter.table.SavedAccount -///////////////////////////////////////////////////////////////// -// callback (that returns Unit) - -typealias EmptyCallback = ()->Unit - typealias TootApiResultCallback = (result : TootApiResult) -> Unit - typealias SavedAccountCallback = (ai : SavedAccount) -> Unit -typealias DialogInterfaceCallback = (dialog: DialogInterface) -> Unit +typealias DialogInterfaceCallback = (dialog : DialogInterface) -> Unit +typealias ProgressResponseBodyCallback = (bytesRead : Long, bytesTotal : Long) -> Unit -typealias ProgressResponseBodyCallback = (bytesRead : Long, bytesTotal : Long)->Unit +val emptyCallback : () -> Unit = {} \ No newline at end of file diff --git a/app/src/main/java/jp/juggler/util/BitmapUtils.kt b/app/src/main/java/jp/juggler/util/BitmapUtils.kt index 086e63fc..5cd21b81 100644 --- a/app/src/main/java/jp/juggler/util/BitmapUtils.kt +++ b/app/src/main/java/jp/juggler/util/BitmapUtils.kt @@ -124,7 +124,7 @@ fun createResizedBitmap( var src_width = options.outWidth var src_height = options.outHeight if(src_width <= 0 || src_height <= 0) { - showToast(context, false, "could not get image bounds.") + context.showToast(false, "could not get image bounds.") return null } @@ -204,7 +204,7 @@ fun createResizedBitmap( } if(sourceBitmap == null) { - showToast(context, false, "could not decode image.") + context.showToast(false, "could not decode image.") return null } try { @@ -234,7 +234,7 @@ fun createResizedBitmap( Bitmap.createBitmap(dstSizeInt.x, dstSizeInt.y, Bitmap.Config.ARGB_8888) try { return if(dst == null) { - showToast(context, false, "bitmap creation failed.") + context.showToast(false, "bitmap creation failed.") null } else { val canvas = Canvas(dst) diff --git a/app/src/main/java/jp/juggler/util/ToastUtils.kt b/app/src/main/java/jp/juggler/util/ToastUtils.kt index 4e58cfcc..b9ba0b95 100644 --- a/app/src/main/java/jp/juggler/util/ToastUtils.kt +++ b/app/src/main/java/jp/juggler/util/ToastUtils.kt @@ -45,19 +45,19 @@ object ToastUtils { } -fun showToast(context : Context, bLong : Boolean, fmt : String?, vararg args : Any) { +fun Context.showToast(bLong : Boolean, fmt : String?, vararg args : Any) { val msg = if(fmt == null) "(null)" else if(args.isEmpty()) fmt else String.format(fmt, *args) - ToastUtils.showToastImpl(context, bLong, msg) + ToastUtils.showToastImpl(this, bLong, msg) } -fun showToast(context : Context, ex : Throwable, fmt : String?, vararg args : Any) { - ToastUtils.showToastImpl(context, true, ex.withCaption(fmt, *args)) +fun Context.showToast(ex : Throwable, fmt : String?, vararg args : Any) { + ToastUtils.showToastImpl(this, true, ex.withCaption(fmt, *args)) } -fun showToast(context : Context, bLong : Boolean, string_id : Int, vararg args : Any) { - ToastUtils.showToastImpl(context, bLong, context.getString(string_id, *args)) +fun Context.showToast(bLong : Boolean, string_id : Int, vararg args : Any) { + ToastUtils.showToastImpl(this, bLong, getString(string_id, *args)) } -fun showToast(context : Context, ex : Throwable, string_id : Int, vararg args : Any) { - ToastUtils.showToastImpl(context, true, ex.withCaption(context.resources, string_id, *args)) +fun Context.showToast(ex : Throwable, string_id : Int, vararg args : Any) { + ToastUtils.showToastImpl(this, true, ex.withCaption(resources, string_id, *args)) } diff --git a/app/src/main/java/jp/juggler/util/UiUtils.kt b/app/src/main/java/jp/juggler/util/UiUtils.kt index 86039c00..1d3389d3 100644 --- a/app/src/main/java/jp/juggler/util/UiUtils.kt +++ b/app/src/main/java/jp/juggler/util/UiUtils.kt @@ -37,8 +37,7 @@ fun Int.applyAlphaMultiplier(alphaMultiplier : Float? = null) : Int { } } -fun getAttributeColor(context : Context, attrId : Int) : Int { - val theme = context.theme +fun Context.getAttributeColor(attrId : Int) : Int { val a = theme.obtainStyledAttributes(intArrayOf(attrId)) val color = a.getColor(0, Color.BLACK) a.recycle() @@ -298,10 +297,10 @@ fun CharSequence.copyToClipboard(context : Context) { clipboard.setPrimaryClip(clip) - showToast(context, false, R.string.copy_complete) + context.showToast(false, R.string.copy_complete) } catch(ex : Throwable) { UiUtils.log.trace(ex) - showToast(context, ex, "copy failed.") + context.showToast(ex, "copy failed.") } } diff --git a/app/src/main/java/jp/juggler/util/ViewUtils.kt b/app/src/main/java/jp/juggler/util/ViewUtils.kt index 5d03da53..043f4896 100644 --- a/app/src/main/java/jp/juggler/util/ViewUtils.kt +++ b/app/src/main/java/jp/juggler/util/ViewUtils.kt @@ -98,23 +98,20 @@ var CompoundButton.isCheckedNoAnime : Boolean jumpDrawablesToCurrentState() } - - private fun mixColor(col1 : Int, col2 : Int) : Int = Color.rgb( (Color.red(col1) + Color.red(col2)) ushr 1, (Color.green(col1) + Color.green(col2)) ushr 1, (Color.blue(col1) + Color.blue(col2)) ushr 1 ) -fun setSwitchColor( - activity : AppCompatActivity, +fun Context.setSwitchColor( pref : SharedPreferences, root : View? ) { - val colorBg = getAttributeColor(activity, R.attr.colorWindowBackground) + val colorBg = getAttributeColor(R.attr.colorWindowBackground) val colorOn = Pref.ipSwitchOnColor(pref) val colorOff = /* Pref.ipSwitchOffColor(pref).notZero() ?: */ - getAttributeColor(activity, android.R.attr.colorPrimary) + getAttributeColor(android.R.attr.colorPrimary) val colorDisabled = mixColor(colorBg, colorOff) @@ -157,7 +154,6 @@ fun setSwitchColor( } } - private fun rgbToLab(rgb : Int) : Triple { fun Int.revGamma() : Float { @@ -193,9 +189,9 @@ private fun rgbToLab(rgb : Int) : Triple { ) } -fun setStatusBarColor(activity : Activity, forceDark : Boolean = false) { +fun AppCompatActivity.setStatusBarColor(forceDark : Boolean = false) { - activity.window?.apply { + window?.apply { // 古い端末ではナビゲーションバーのアイコン色を設定できないため // メディアビューア画面ではステータスバーやナビゲーションバーの色を設定しない… @@ -211,7 +207,7 @@ fun setStatusBarColor(activity : Activity, forceDark : Boolean = false) { var c = when { forceDark -> Color.BLACK else -> Pref.ipStatusBarColor(App1.pref).notZero() - ?: getAttributeColor(activity, R.attr.colorPrimaryDark) + ?: getAttributeColor(R.attr.colorPrimaryDark) } statusBarColor = c or Color.BLACK