diff --git a/app/src/main/java/jp/juggler/subwaytooter/ActAppSetting.kt b/app/src/main/java/jp/juggler/subwaytooter/ActAppSetting.kt index 65ad5c61..0124fdec 100644 --- a/app/src/main/java/jp/juggler/subwaytooter/ActAppSetting.kt +++ b/app/src/main/java/jp/juggler/subwaytooter/ActAppSetting.kt @@ -19,34 +19,22 @@ import android.text.TextWatcher import android.util.JsonWriter import android.view.View import android.view.ViewGroup -import android.widget.AdapterView -import android.widget.ArrayAdapter -import android.widget.BaseAdapter -import android.widget.CompoundButton -import android.widget.EditText -import android.widget.ImageView -import android.widget.Spinner -import android.widget.TextView - +import android.widget.* import com.jrummyapps.android.colorpicker.ColorPickerDialog import com.jrummyapps.android.colorpicker.ColorPickerDialogListener import jp.juggler.subwaytooter.dialog.ProgressDialogEx - -import org.apache.commons.io.IOUtils -import org.apache.commons.io.output.FileWriterWithEncoding - -import java.io.File -import java.io.FileOutputStream -import java.text.NumberFormat -import java.util.ArrayList -import java.util.Locale - import jp.juggler.subwaytooter.table.AcctColor import jp.juggler.subwaytooter.table.SavedAccount -import jp.juggler.subwaytooter.util.* -import org.json.JSONObject -import java.io.FileInputStream +import jp.juggler.subwaytooter.util.LogCategory +import jp.juggler.subwaytooter.util.handleGetContentResult +import jp.juggler.subwaytooter.util.intentOpenDocument +import jp.juggler.subwaytooter.util.showToast +import org.apache.commons.io.IOUtils +import java.io.File +import java.io.FileOutputStream import java.io.OutputStreamWriter +import java.text.NumberFormat +import java.util.* import java.util.zip.ZipEntry import java.util.zip.ZipOutputStream @@ -868,11 +856,11 @@ class ActAppSetting : AppCompatActivity() c = footer_button_fg_color if(c == 0) { - Styler.setIconDefaultColor(this, ivFooterToot, R.attr.ic_edit) - Styler.setIconDefaultColor(this, ivFooterMenu, R.attr.ic_hamburger) + Styler.setIconAttr(this, ivFooterToot, R.attr.ic_edit) + Styler.setIconAttr(this, ivFooterMenu, R.attr.ic_hamburger) } else { - Styler.setIconCustomColor(this, ivFooterToot, c, R.attr.ic_edit) - Styler.setIconCustomColor(this, ivFooterMenu, c, R.attr.ic_hamburger) + Styler.setIconAttr(this, ivFooterToot, R.attr.ic_edit,color=c) + Styler.setIconAttr(this, ivFooterMenu, R.attr.ic_hamburger,color=c) } c = footer_tab_bg_color diff --git a/app/src/main/java/jp/juggler/subwaytooter/ActColumnCustomize.kt b/app/src/main/java/jp/juggler/subwaytooter/ActColumnCustomize.kt index 280c0dae..996b15a2 100644 --- a/app/src/main/java/jp/juggler/subwaytooter/ActColumnCustomize.kt +++ b/app/src/main/java/jp/juggler/subwaytooter/ActColumnCustomize.kt @@ -414,18 +414,18 @@ class ActColumnCustomize : AppCompatActivity(), View.OnClickListener, ColorPicke android.R.attr.textColorPrimary ) ) - Styler.setIconDefaultColor( + Styler.setIconAttr( this, ivColumnHeader, column.getIconAttrId(column.column_type) ) } else { tvColumnName.setTextColor(c) - Styler.setIconCustomColor( + Styler.setIconAttr( this, ivColumnHeader, - c, - column.getIconAttrId(column.column_type) + column.getIconAttrId(column.column_type), + color = c ) } diff --git a/app/src/main/java/jp/juggler/subwaytooter/ActMain.kt b/app/src/main/java/jp/juggler/subwaytooter/ActMain.kt index 066f3c81..31ad532c 100644 --- a/app/src/main/java/jp/juggler/subwaytooter/ActMain.kt +++ b/app/src/main/java/jp/juggler/subwaytooter/ActMain.kt @@ -1046,19 +1046,21 @@ class ActMain : AppCompatActivity() , bAllowPseudo = false , args = arrayOf("", false) ) + R.id.nav_add_mutes -> Action_Account.timeline( this , defaultInsertPosition , Column.TYPE_MUTES , bAllowPseudo = false ) + R.id.nav_add_blocks -> Action_Account.timeline( this , defaultInsertPosition , Column.TYPE_BLOCKS , bAllowPseudo = false - , bAllowMisskey = false ) + R.id.nav_keyword_filter -> Action_Account.timeline( this , defaultInsertPosition @@ -1421,9 +1423,9 @@ class ActMain : AppCompatActivity() c = column.header_fg_color if(c == 0) { - Styler.setIconDefaultColor(this, ivIcon, column.getIconAttrId(column.column_type)) + Styler.setIconAttr(this, ivIcon, column.getIconAttrId(column.column_type)) } else { - Styler.setIconCustomColor(this, ivIcon, c, column.getIconAttrId(column.column_type)) + Styler.setIconAttr(this, ivIcon, column.getIconAttrId(column.column_type),c) } // @@ -2266,13 +2268,13 @@ class ActMain : AppCompatActivity() c = footer_button_fg_color if(c == 0) { - Styler.setIconDefaultColor(this, btnToot, R.attr.ic_edit) - Styler.setIconDefaultColor(this, btnMenu, R.attr.ic_hamburger) - Styler.setIconDefaultColor(this, btnQuickToot, R.attr.btn_post) + Styler.setIconAttr(this, btnToot, R.attr.ic_edit) + Styler.setIconAttr(this, btnMenu, R.attr.ic_hamburger) + Styler.setIconAttr(this, btnQuickToot, R.attr.btn_post) } else { - Styler.setIconCustomColor(this, btnToot, c, R.attr.ic_edit) - Styler.setIconCustomColor(this, btnMenu, c, R.attr.ic_hamburger) - Styler.setIconCustomColor(this, btnQuickToot, c, R.attr.btn_post) + Styler.setIconAttr(this, btnToot, R.attr.ic_edit,c) + Styler.setIconAttr(this, btnMenu, R.attr.ic_hamburger,c) + Styler.setIconAttr(this, btnQuickToot, R.attr.btn_post,c) } c = footer_tab_bg_color diff --git a/app/src/main/java/jp/juggler/subwaytooter/App1.kt b/app/src/main/java/jp/juggler/subwaytooter/App1.kt index 5bf5a9ec..852623ae 100644 --- a/app/src/main/java/jp/juggler/subwaytooter/App1.kt +++ b/app/src/main/java/jp/juggler/subwaytooter/App1.kt @@ -108,7 +108,10 @@ class App1 : Application() { // 2018/8/19 v268 30 => 31 (29)で失敗しておかしくなったContentWarningとMediaShownを作り直す // 2018/8/28 v279 31 => 32 UserRelation,UserRelationMisskey にendorsedを追加 // 2018/8/28 v280 32 => 33 NotificationTracking テーブルの作り直し。SavedAccountに通知二種類を追加 - internal const val DB_VERSION = 33 + // 2018/10/31 v296 33 => 34 UserRelationMisskey に blocked_by を追加 + // 2018/10/31 v296 34 => 35 UserRelationMisskey に requested_by を追加 + + internal const val DB_VERSION = 35 private val tableList = arrayOf( LogData, diff --git a/app/src/main/java/jp/juggler/subwaytooter/Column.kt b/app/src/main/java/jp/juggler/subwaytooter/Column.kt index 5baa8fce..2829bf2e 100644 --- a/app/src/main/java/jp/juggler/subwaytooter/Column.kt +++ b/app/src/main/java/jp/juggler/subwaytooter/Column.kt @@ -769,8 +769,8 @@ class Column( } } - private fun JSONObject.putIfTrue(key:String,value:Boolean){ - if(value) put( key,true) + private fun JSONObject.putIfTrue(key : String, value : Boolean) { + if(value) put(key, true) } @Throws(JSONException::class) @@ -1556,41 +1556,43 @@ class Column( internal fun loadProfileAccount( client : TootApiClient, + parser : TootParser, bForceReload : Boolean ) : TootApiResult? { - return if(bForceReload || this.who_account == null) { + + return if(this.who_account != null && ! bForceReload) { + // リロード不要なら何もしない + null + } else if(isMisskey) { + val params = access_info.putMisskeyApiToken(JSONObject()) + .put("userId", profile_id) - if(isMisskey) { - val params = access_info.putMisskeyApiToken(JSONObject()) - .put("userId", profile_id) - val result = client.request(PATH_MISSKEY_PROFILE, params.toPostRequestBuilder()) - val parser = TootParser( - context, - access_info, - misskeyDecodeProfilePin = true - ) + val result = client.request(PATH_MISSKEY_PROFILE, params.toPostRequestBuilder()) + + // ユーザリレーションの取り扱いのため、別のparserを作ってはいけない + parser.misskeyDecodeProfilePin = true + try { val a = TootAccountRef.mayNull(parser, parser.account(result?.jsonObject)) if(a != null) { this.who_account = a client.publishApiProgress("") // カラムヘッダの再表示 } - result - - } else { - val result = client.request(String.format(Locale.JAPAN, PATH_ACCOUNT, profile_id)) - val parser = TootParser(context, access_info) - val a = TootAccountRef.mayNull(parser, parser.account(result?.jsonObject)) - if(a != null) { - this.who_account = a - client.publishApiProgress("") // カラムヘッダの再表示 - } - result - + } finally { + parser.misskeyDecodeProfilePin = false } + result + } else { - null + val result = client.request(String.format(Locale.JAPAN, PATH_ACCOUNT, profile_id)) + val a = TootAccountRef.mayNull(parser, parser.account(result?.jsonObject)) + if(a != null) { + this.who_account = a + client.publishApiProgress("") // カラムヘッダの再表示 + } + result } + } internal fun loadListInfo(client : TootApiClient, bForceReload : Boolean) { @@ -1756,7 +1758,7 @@ class Column( // DMカラム更新時に新APIの利用に成功したなら真 internal var useConversationSummarys = false - + // DMカラムのストリーミングイベントで新形式のイベントを利用できたなら真 internal var useConversationSummaryStreaming = false @@ -2432,12 +2434,12 @@ class Column( TYPE_DIRECT_MESSAGES -> { useConversationSummarys = false - if(! use_old_api){ - + if(! use_old_api) { + // try 2.6.0 new API https://github.com/tootsuite/mastodon/pull/8832 val resultCS = getConversationSummary(client, PATH_DIRECT_MESSAGES2) - - when{ + + when { // cancelled resultCS == null -> return null @@ -2475,7 +2477,7 @@ class Column( TYPE_PROFILE -> { - val who_result = loadProfileAccount(client, true) + val who_result = loadProfileAccount(client, parser, true) if(client.isApiCancelled || who_account == null) return who_result @@ -2594,7 +2596,11 @@ class Column( } TYPE_KEYWORD_FILTER -> return parseFilterList(client, PATH_FILTERS) - TYPE_BLOCKS -> return parseAccountList(client, PATH_BLOCKS) + TYPE_BLOCKS -> return if(isMisskey){ + TootApiResult("Misskey has no API to get block list") + }else{ + parseAccountList(client, PATH_BLOCKS) + } TYPE_DOMAIN_BLOCKS -> return parseDomainList(client, PATH_DOMAIN_BLOCK) @@ -2825,7 +2831,7 @@ class Column( // カードを取得する if(! Pref.bpDontRetrievePreviewCard(context)) { this.list_tmp?.forEach { o -> - if( o is TootStatus && o.card==null ) + if(o is TootStatus && o.card == null) o.card = parseItem( ::TootCard, client.request("/api/v1/statuses/" + o.id + "/card")?.jsonObject @@ -3893,7 +3899,7 @@ class Column( aroundMin : Boolean = false, misskeyParams : JSONObject? = null, misskeyCustomParser : (parser : TootParser, jsonArray : JSONArray) -> ArrayList = - { parser, jsonArray -> parseList(::TootConversationSummary,parser,jsonArray) } + { parser, jsonArray -> parseList(::TootConversationSummary, parser, jsonArray) } ) : TootApiResult? { val isMisskey = access_info.isMisskey @@ -4397,7 +4403,6 @@ class Column( return firstResult } - var filterUpdated = false override fun doInBackground(vararg unused : Void) : TootApiResult? { @@ -4431,7 +4436,7 @@ class Column( TYPE_DIRECT_MESSAGES -> if(useConversationSummarys) { // try 2.6.0 new API https://github.com/tootsuite/mastodon/pull/8832 getConversationSummaryList(client, PATH_DIRECT_MESSAGES2) - }else { + } else { // fallback to old api getStatusList(client, PATH_DIRECT_MESSAGES) } @@ -4518,7 +4523,7 @@ class Column( ) TYPE_PROFILE -> { - loadProfileAccount(client, false) + loadProfileAccount(client, parser, false) when(profile_tab) { @@ -4800,7 +4805,7 @@ class Column( } } - replaceConversationSummary(changeList,list_new,list_data) + replaceConversationSummary(changeList, list_new, list_data) // 投稿後のリフレッシュなら当該投稿の位置を探す var status_index = - 1 @@ -5352,14 +5357,13 @@ class Column( return result } - fun getConversationSummaryList( client : TootApiClient, path_base : String, misskeyParams : JSONObject? = null , misskeyCustomParser : (parser : TootParser, jsonArray : JSONArray) -> ArrayList = - { parser, jsonArray -> parseList(::TootConversationSummary,parser,jsonArray) } + { parser, jsonArray -> parseList(::TootConversationSummary, parser, jsonArray) } ) : TootApiResult? { val isMisskey = access_info.isMisskey @@ -5647,14 +5651,13 @@ class Column( } } - TYPE_DIRECT_MESSAGES -> if(useConversationSummarys) { + TYPE_DIRECT_MESSAGES -> if(useConversationSummarys) { // try 2.6.0 new API https://github.com/tootsuite/mastodon/pull/8832 getConversationSummaryList(client, PATH_DIRECT_MESSAGES2) - }else { + } else { // fallback to old api getStatusList(client, PATH_DIRECT_MESSAGES) } - else -> getStatusList(client, makeHomeTlUrl()) } @@ -5700,14 +5703,14 @@ class Column( fireShowContent(reason = "gap list_tmp is null", changeList = ArrayList()) return } - + val list_new = duplicate_map.filterDuplicate(list_tmp) // 0個でもギャップを消すために以下の処理を続ける val added = list_new.size // may 0 val changeList = ArrayList() - replaceConversationSummary(changeList,list_new,list_data) + replaceConversationSummary(changeList, list_new, list_data) val position = list_data.indexOf(gap) if(position == - 1) { @@ -5732,7 +5735,7 @@ class Column( } } } - + list_data.removeAt(position) list_data.addAll(position, list_new) @@ -6021,32 +6024,31 @@ class Column( } } - override fun onTimelineItem(item : TimelineItem) { if(is_dispose.get()) return if(item is TootConversationSummary) { if(column_type != TYPE_DIRECT_MESSAGES) return if(isFiltered(item.last_status)) return - if( use_old_api ){ + if(use_old_api) { useConversationSummaryStreaming = false return - }else{ + } else { useConversationSummaryStreaming = true } - }else if(item is TootNotification) { + } else if(item is TootNotification) { if(column_type != TYPE_NOTIFICATIONS) return if(isFiltered(item)) return } else if(item is TootStatus) { if(column_type == TYPE_NOTIFICATIONS) return - + // マストドン2.6.0形式のDMカラム用イベントを利用したならば、その直後に発生する普通の投稿イベントを無視する - if( useConversationSummaryStreaming ) return + if(useConversationSummaryStreaming) return if(column_type == TYPE_LOCAL && ! isMisskey && item.account.acct.indexOf('@') != - 1) return if(isFiltered(item)) return } - + stream_data_queue.add(item) val handler = App1.getAppState(context).handler @@ -6171,8 +6173,6 @@ class Column( } } - - // 最新のIDをsince_idとして覚える(ソートはしない) var new_id_max : EntityId? = null var new_id_min : EntityId? = null @@ -6243,12 +6243,12 @@ class Column( val added = list_new.size val changeList = ArrayList() - - replaceConversationSummary(changeList,list_new,list_data) + + replaceConversationSummary(changeList, list_new, list_data) loop@ for(o in list_new) { when(o) { - + is TootStatus -> { val highlight_sound = o.highlight_sound if(highlight_sound != null) { @@ -6258,7 +6258,7 @@ class Column( } } } - + changeList.add(AdapterChange(AdapterChangeType.RangeInsert, 0, added)) list_data.addAll(0, list_new) @@ -6299,21 +6299,21 @@ class Column( } private fun replaceConversationSummary( - changeList :ArrayList, - list_new: ArrayList, - list_data: BucketList - ){ + changeList : ArrayList, + list_new : ArrayList, + list_data : BucketList + ) { val removeSet = HashSet() loop@ for(o in list_new) { - if( o is TootConversationSummary ) { - removeSet.add( o.getOrderId() ) + if(o is TootConversationSummary) { + removeSet.add(o.getOrderId()) } } - if( list_data .isNotEmpty() && removeSet.isNotEmpty() ){ - for( i in list_data.size-1 downTo 0 ){ + if(list_data.isNotEmpty() && removeSet.isNotEmpty()) { + for(i in list_data.size - 1 downTo 0) { val o = list_data[i] - if( o is TootConversationSummary && removeSet.contains(o.id) ){ + if(o is TootConversationSummary && removeSet.contains(o.id)) { changeList.add(AdapterChange(AdapterChangeType.RangeRemove, i, 1)) list_data.removeAt(i) log.d("remove old TootConversationSummary") diff --git a/app/src/main/java/jp/juggler/subwaytooter/ColumnViewHolder.kt b/app/src/main/java/jp/juggler/subwaytooter/ColumnViewHolder.kt index 718837c8..c22a951a 100644 --- a/app/src/main/java/jp/juggler/subwaytooter/ColumnViewHolder.kt +++ b/app/src/main/java/jp/juggler/subwaytooter/ColumnViewHolder.kt @@ -624,27 +624,27 @@ class ColumnViewHolder( android.R.attr.textColorPrimary ) ) - Styler.setIconDefaultColor( + Styler.setIconAttr( activity, ivColumnIcon, column.getIconAttrId(column.column_type) ) - Styler.setIconDefaultColor(activity, btnColumnSetting, R.attr.ic_tune) - Styler.setIconDefaultColor(activity, btnColumnReload, R.attr.btn_refresh) - Styler.setIconDefaultColor(activity, btnColumnClose, R.attr.btn_close) + Styler.setIconAttr(activity, btnColumnSetting, R.attr.ic_tune) + Styler.setIconAttr(activity, btnColumnReload, R.attr.btn_refresh) + Styler.setIconAttr(activity, btnColumnClose, R.attr.btn_close) } else { tvColumnIndex.setTextColor(c) tvColumnStatus.setTextColor(c) tvColumnName.setTextColor(c) - Styler.setIconCustomColor( + Styler.setIconAttr( activity, ivColumnIcon, - c, - column.getIconAttrId(column.column_type) + column.getIconAttrId(column.column_type), + c ) - Styler.setIconCustomColor(activity, btnColumnSetting, c, R.attr.ic_tune) - Styler.setIconCustomColor(activity, btnColumnReload, c, R.attr.btn_refresh) - Styler.setIconCustomColor(activity, btnColumnClose, c, R.attr.btn_close) + Styler.setIconAttr(activity, btnColumnSetting, R.attr.ic_tune,c) + Styler.setIconAttr(activity, btnColumnReload, R.attr.btn_refresh,c) + Styler.setIconAttr(activity, btnColumnClose, R.attr.btn_close,c) } c = column.column_bg_color diff --git a/app/src/main/java/jp/juggler/subwaytooter/DlgContextMenu.kt b/app/src/main/java/jp/juggler/subwaytooter/DlgContextMenu.kt index 7a6a6d34..57bfb5c9 100644 --- a/app/src/main/java/jp/juggler/subwaytooter/DlgContextMenu.kt +++ b/app/src/main/java/jp/juggler/subwaytooter/DlgContextMenu.kt @@ -496,7 +496,12 @@ internal class DlgContextMenu( R.id.btnBlock -> if(relation.blocking) { - Action_User.block(activity, access_info, who, false) + Action_User.block( + activity, + access_info, + who, + false + ) } else { AlertDialog.Builder(activity) .setMessage( diff --git a/app/src/main/java/jp/juggler/subwaytooter/DownloadReceiver.kt b/app/src/main/java/jp/juggler/subwaytooter/DownloadReceiver.kt index 7e3e5047..ac944d3c 100644 --- a/app/src/main/java/jp/juggler/subwaytooter/DownloadReceiver.kt +++ b/app/src/main/java/jp/juggler/subwaytooter/DownloadReceiver.kt @@ -4,6 +4,8 @@ import android.app.DownloadManager import android.content.BroadcastReceiver import android.content.Context import android.content.Intent +import jp.juggler.subwaytooter.util.getIntOrNull +import jp.juggler.subwaytooter.util.getStringOrNull import jp.juggler.subwaytooter.util.showToast @@ -22,12 +24,10 @@ class DownloadReceiver : BroadcastReceiver() { val query = DownloadManager.Query().setFilterById(id) downloadManager.query(query)?.use { cursor -> if(cursor.moveToFirst()) { - val idx_status = cursor.getColumnIndex(DownloadManager.COLUMN_STATUS) - val idx_title = cursor.getColumnIndex(DownloadManager.COLUMN_TITLE) - val title = cursor.getString(idx_title) + val title = cursor.getStringOrNull(DownloadManager.COLUMN_TITLE) - if(DownloadManager.STATUS_SUCCESSFUL == cursor.getInt(idx_status)) { + if(DownloadManager.STATUS_SUCCESSFUL == cursor.getIntOrNull(DownloadManager.COLUMN_STATUS) ) { /* ダウンロード完了通知がシステムからのものと重複することがある diff --git a/app/src/main/java/jp/juggler/subwaytooter/Styler.kt b/app/src/main/java/jp/juggler/subwaytooter/Styler.kt index a4775cd4..792738f9 100644 --- a/app/src/main/java/jp/juggler/subwaytooter/Styler.kt +++ b/app/src/main/java/jp/juggler/subwaytooter/Styler.kt @@ -58,22 +58,31 @@ object Styler { ) } - // ImageViewにアイコンを設定する - fun setIconDefaultColor(context : Context, imageView : ImageView, iconAttrId : Int) { - imageView.setImageResource(getAttributeResourceId(context, iconAttrId)) - } - - // ImageViewにアイコンを設定する。色を変えてしまう - fun setIconCustomColor( + private fun setIconDrawableId( context : Context, imageView : ImageView, - color : Int, - iconAttrId : Int + drawableId : Int, + color:Int? = null ) { - val d = getAttributeDrawable(context, iconAttrId) - d.mutate() // 色指定が他のアイコンに影響しないようにする - d.setColorFilter(color, PorterDuff.Mode.SRC_ATOP) - imageView.setImageDrawable(d) + if( color == null) { + // ImageViewにアイコンを設定する。デフォルトの色 + imageView.setImageResource(drawableId) + }else{ + // ImageViewにアイコンを設定する。色を変えてしまう + val d = ContextCompat.getDrawable(context,drawableId) ?: return + d.mutate() // 色指定が他のアイコンに影響しないようにする + d.setColorFilter(color, PorterDuff.Mode.SRC_ATOP) + imageView.setImageDrawable(d) + } + } + + fun setIconAttr( + context : Context, + imageView : ImageView, + iconAttrId : Int, + color:Int? = null + ) { + setIconDrawableId(context,imageView,getAttributeResourceId(context, iconAttrId),color) } fun getVisibilityIconAttr(isMisskeyData:Boolean ,visibility : TootVisibility):Int { @@ -162,15 +171,34 @@ object Styler { ) { // 被フォロー状態 - if(! relation.followed_by) { - ivDot.visibility = View.GONE - } else { - ivDot.visibility = View.VISIBLE - setIconDefaultColor(context, ivDot, R.attr.ic_followed_by) + when { - // 被フォローリクエスト状態の時に followed_by が 真と偽の両方がありえるようなので - // Relationshipだけを見ても被フォローリクエスト状態は分からないっぽい - // 仕方ないので馬鹿正直に「 followed_byが真ならバッジをつける」しかできない + relation.blocked_by -> { + ivDot.visibility = View.VISIBLE + setIconDrawableId(context, ivDot, R.drawable.ic_blocked_by, + color=Styler.getAttributeColor(context, R.attr.colorRegexFilterError) + ) + } + + relation.requested_by -> { + ivDot.visibility = View.VISIBLE + setIconDrawableId(context, ivDot, R.drawable.ic_requested_by, + color=Styler.getAttributeColor(context, R.attr.colorRegexFilterError) + ) + } + + relation.followed_by-> { + ivDot.visibility = View.VISIBLE + setIconAttr(context, ivDot, R.attr.ic_followed_by) + + // 被フォローリクエスト状態の時に followed_by が 真と偽の両方がありえるようなので + // Relationshipだけを見ても被フォローリクエスト状態は分からないっぽい + // 仕方ないので馬鹿正直に「 followed_byが真ならバッジをつける」しかできない + } + + else -> { + ivDot.visibility = View.GONE + } } // フォローボタン @@ -211,8 +239,7 @@ object Styler { } } - val color = Styler.getAttributeColor(context, color_attr) - setIconCustomColor(context, ibFollow, color, icon_attr) + setIconAttr(context, ibFollow, icon_attr, color =Styler.getAttributeColor(context, color_attr) ) ibFollow.contentDescription = contentDescription } 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 09ba5871..0bd0b57e 100644 --- a/app/src/main/java/jp/juggler/subwaytooter/action/ActionUtils.kt +++ b/app/src/main/java/jp/juggler/subwaytooter/action/ActionUtils.kt @@ -122,17 +122,20 @@ fun makeAccountListNonPseudo( return list_same_host } -internal fun saveUserRelation(access_info : SavedAccount,src : TootRelationShip?) : UserRelation? { +internal fun saveUserRelation(access_info : SavedAccount, src : TootRelationShip?) : UserRelation? { src ?: return null val now = System.currentTimeMillis() return UserRelation.save1(now, access_info.db_id, src) } -internal fun saveUserRelationMisskey(access_info : SavedAccount,whoId:EntityId,parser:TootParser) : UserRelation? { + +internal fun saveUserRelationMisskey( + access_info : SavedAccount, + whoId : EntityId, + parser : TootParser +) : UserRelation? { val now = System.currentTimeMillis() val relation = parser.getMisskeyUserRelation(whoId) - if( relation != null){ - UserRelationMisskey.save1(now, access_info.db_id, whoId.toString(),relation) - } + UserRelationMisskey.save1(now, access_info.db_id, whoId.toString(), relation) return relation } @@ -141,7 +144,8 @@ internal fun loadRelation1Mastodon( client : TootApiClient, access_info : SavedAccount, who : TootAccount -):RelationResult{val rr = RelationResult() +) : RelationResult { + val rr = RelationResult() rr.result = client.request("/api/v1/accounts/relationships?id=${who.id}") val r2 = rr.result val jsonArray = r2?.jsonArray @@ -154,7 +158,6 @@ internal fun loadRelation1Mastodon( return rr } - // 別アカ操作と別タンスの関係 const val NOT_CROSS_ACCOUNT = 1 const val CROSS_ACCOUNT_SAME_INSTANCE = 2 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 7ef86be6..ccad68d0 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 @@ -12,6 +12,7 @@ import jp.juggler.subwaytooter.dialog.ReportForm import jp.juggler.subwaytooter.table.AcctColor import jp.juggler.subwaytooter.table.SavedAccount import jp.juggler.subwaytooter.table.UserRelation +import jp.juggler.subwaytooter.table.UserRelationMisskey import jp.juggler.subwaytooter.util.* import okhttp3.Request import okhttp3.RequestBody @@ -37,25 +38,31 @@ object Action_User { var relation : UserRelation? = null override fun background(client : TootApiClient) : TootApiResult? { - if(access_info.isMisskey){ + if(access_info.isMisskey) { val params = access_info.putMisskeyApiToken(JSONObject()) - .put("userId",who.id.toString()) + .put("userId", who.id.toString()) - val result = client.request(when(bMute){ - true-> "/api/mute/create" - else->"/api/mute/delete" - },params.toPostRequestBuilder()) - if( result?.jsonObject != null ){ + val result = client.request( + when(bMute) { + true -> "/api/mute/create" + else -> "/api/mute/delete" + }, params.toPostRequestBuilder() + ) + if(result?.jsonObject != null) { // 204 no content // update user relation - val ur = UserRelation.load(access_info.db_id,who.id) + val ur = UserRelation.load(access_info.db_id, who.id) ur.muting = bMute - saveUserRelationMisskey(access_info,who.id,TootParser(activity,access_info)) + saveUserRelationMisskey( + access_info, + who.id, + TootParser(activity, access_info) + ) this.relation = ur } return result - }else{ + } else { val request_builder = Request.Builder().post( if(! bMute) RequestBody.create(TootApiClient.MEDIA_TYPE_FORM_URL_ENCODED, "") @@ -126,7 +133,10 @@ object Action_User { // ユーザをブロック/ブロック解除する fun block( - activity : ActMain, access_info : SavedAccount, who : TootAccount, bBlock : Boolean + activity : ActMain, + access_info : SavedAccount, + who : TootAccount, + bBlock : Boolean ) { if(access_info.isMe(who)) { showToast(activity, false, R.string.it_is_you) @@ -138,23 +148,52 @@ object Action_User { var relation : UserRelation? = null override fun background(client : TootApiClient) : TootApiResult? { - val request_builder = Request.Builder().post( - RequestBody.create( - TootApiClient.MEDIA_TYPE_FORM_URL_ENCODED, "" // 空データ + if(access_info.isMisskey) { + val params = access_info.putMisskeyApiToken() + .put("userId", who.id) + val result = client.request( + if(bBlock) + "/api/blocking/create" + else + "/api/blocking/delete", + params.toPostRequestBuilder() ) - ) - - val result = client.request( - "/api/v1/accounts/" + who.id + if(bBlock) "/block" else "/unblock", - request_builder - ) - val jsonObject = result?.jsonObject - if(jsonObject != null) { - relation = - saveUserRelation(access_info, parseItem(::TootRelationShip, jsonObject)) + + if(result?.jsonObject != null) { + // ユーザ情報があるがリレーションが含まれないっぽい + + // update user relation + val ur = UserRelation.load(access_info.db_id, who.id) + ur.blocking = bBlock + saveUserRelationMisskey( + access_info, + who.id, + TootParser(activity, access_info) + ) + this.relation = ur + } + + + return result + } else { + val request_builder = Request.Builder().post( + RequestBody.create( + TootApiClient.MEDIA_TYPE_FORM_URL_ENCODED, "" // 空データ + ) + ) + + val result = client.request( + "/api/v1/accounts/" + who.id + if(bBlock) "/block" else "/unblock", + request_builder + ) + val jsonObject = result?.jsonObject + if(jsonObject != null) { + relation = + saveUserRelation(access_info, parseItem(::TootRelationShip, jsonObject)) + } + + return result } - - return result } override fun handleResult(result : TootApiResult?) { @@ -170,24 +209,38 @@ object Action_User { return } + for(column in App1.getAppState(activity).column_list) { - if(relation.blocking) { - if(column.column_type == Column.TYPE_PROFILE) { - // プロフページのトゥートはブロックしてても見れる - continue - } else { - column.removeAccountInTimeline(access_info, who.id) + when { + + //ブロック解除したら「ブロックしたユーザ」カラムのリストから消える + ! relation.blocking -> column.removeUser( + access_info, + Column.TYPE_BLOCKS, + who.id + ) + + // Misskeyのブロックはフォロー解除とフォロー拒否だけなので + // カラム中の投稿を消すなどの効果はない + access_info.isMisskey -> { } - } else { - //「ブロックしたユーザ」カラムのリストから消える - column.removeUser(access_info, Column.TYPE_BLOCKS, who.id) + + // プロフページのトゥートはブロックしてても見れる + column.column_type == Column.TYPE_PROFILE -> { + } + + // MastodonではブロックしたらTLからそのアカウントの投稿が消える + else -> column.removeAccountInTimeline(access_info, who.id) } } showToast( activity, false, - if(relation.blocking) R.string.block_succeeded else R.string.unblock_succeeded + if(relation.blocking) + R.string.block_succeeded + else + R.string.unblock_succeeded ) } else { @@ -206,7 +259,12 @@ object Action_User { who : TootAccount ) { when { - access_info.isMisskey -> activity.addColumn(pos, access_info, Column.TYPE_PROFILE, who.id) + access_info.isMisskey -> activity.addColumn( + pos, + access_info, + Column.TYPE_PROFILE, + who.id + ) access_info.isPseudo -> profileFromAnotherAccount(activity, pos, access_info, who) else -> activity.addColumn(pos, access_info, Column.TYPE_PROFILE, who.id) } @@ -223,7 +281,7 @@ object Action_User { var who_local : TootAccount? = null override fun background(client : TootApiClient) : TootApiResult? { - val result = client.syncAccountByUrl(access_info,who_url) + val result = client.syncAccountByUrl(access_info, who_url) who_local = result?.data as? TootAccount return result } @@ -422,7 +480,8 @@ object Action_User { client.request("/api/v1/accounts/" + who.id + "/follow", request_builder) val jsonObject = result?.jsonObject if(jsonObject != null) { - relation =saveUserRelation(access_info,parseItem(::TootRelationShip, jsonObject)) + relation = + saveUserRelation(access_info, parseItem(::TootRelationShip, jsonObject)) } return result } @@ -482,23 +541,23 @@ object Action_User { activity : ActMain, access_info : SavedAccount, who : TootAccount, - bConfirmed :Boolean = false + bConfirmed : Boolean = false ) { - if(!bConfirmed){ + if(! bConfirmed) { val name = who.decodeDisplayName(activity) AlertDialog.Builder(activity) - .setMessage( name.intoStringResource(activity,R.string.delete_succeeded_confirm)) - .setNegativeButton(R.string.cancel,null) - .setPositiveButton(R.string.ok){ _ , _ -> - deleteSuggestion(activity,access_info,who,bConfirmed=true) + .setMessage(name.intoStringResource(activity, R.string.delete_succeeded_confirm)) + .setNegativeButton(R.string.cancel, null) + .setPositiveButton(R.string.ok) { _, _ -> + deleteSuggestion(activity, access_info, who, bConfirmed = true) } .show() return } TootTaskRunner(activity).run(access_info, object : TootTask { override fun background(client : TootApiClient) : TootApiResult? { - return client.request("/api/v1/suggestions/${who.id}",Request.Builder().delete()) + return client.request("/api/v1/suggestions/${who.id}", Request.Builder().delete()) } override fun handleResult(result : TootApiResult?) { @@ -507,16 +566,16 @@ object Action_User { // error val error = result.error - if( error != null ){ - showToast(activity,true,result.error) + if(error != null) { + showToast(activity, true, result.error) return } - showToast(activity,false,R.string.delete_succeeded) - + showToast(activity, false, R.string.delete_succeeded) + // update suggestion column - for( column in activity.app_state.column_list){ - column.removeUser(access_info,Column.TYPE_FOLLOW_SUGGESTION,who.id) + for(column in activity.app_state.column_list) { + column.removeUser(access_info, Column.TYPE_FOLLOW_SUGGESTION, who.id) } } }) diff --git a/app/src/main/java/jp/juggler/subwaytooter/api/entity/TootAccount.kt b/app/src/main/java/jp/juggler/subwaytooter/api/entity/TootAccount.kt index 752bae1f..0aeb8b85 100644 --- a/app/src/main/java/jp/juggler/subwaytooter/api/entity/TootAccount.kt +++ b/app/src/main/java/jp/juggler/subwaytooter/api/entity/TootAccount.kt @@ -16,32 +16,32 @@ import java.util.regex.Pattern open class TootAccount(parser : TootParser, src : JSONObject) { class Field( - val name :String, - val value :String, - val verified_at: Long // 0L if not verified + val name : String, + val value : String, + val verified_at : Long // 0L if not verified ) companion object { private val log = LogCategory("TootAccount") - internal val reWhitespace:Pattern = Pattern.compile("[\\s\\t\\x0d\\x0a]+") + internal val reWhitespace : Pattern = Pattern.compile("[\\s\\t\\x0d\\x0a]+") // host, user ,(instance) - internal val reAccountUrl :Pattern = + internal val reAccountUrl : Pattern = Pattern.compile("\\Ahttps://([A-Za-z0-9._-]+)/@([A-Za-z0-9_]+(?:@[A-Za-z0-9._-]+)?)(?:\\z|[?#])") - fun getAcctFromUrl(url:String):String?{ + fun getAcctFromUrl(url : String) : String? { val m = reAccountUrl.matcher(url) - return if(m.find()){ + return if(m.find()) { val host = m.group(1) val user = m.group(2).unescapeUri() val instance = m.groupOrNull(3)?.unescapeUri() - if( instance?.isNotEmpty() == true){ + if(instance?.isNotEmpty() == true) { "$user@$instance" - }else{ + } else { "$user@$host" } - }else{ + } else { null } } @@ -79,7 +79,7 @@ open class TootAccount(parser : TootParser, src : JSONObject) { try { // たぶんどんなURLでもauthorityの部分にホスト名が来るだろう(慢心) val host = Uri.parse(url).authority - if( host?.isNotEmpty() == true){ + if(host?.isNotEmpty() == true) { return host.toLowerCase() } log.e("findHostFromUrl: can't parse host from URL $url") @@ -99,11 +99,11 @@ open class TootAccount(parser : TootParser, src : JSONObject) { val name = item.parseString("name") ?: continue val value = item.parseString("value") ?: continue val svVerifiedAt = item.parseString("verified_at") - val verifiedAt = when(svVerifiedAt){ + val verifiedAt = when(svVerifiedAt) { null -> 0L - else-> TootStatus.parseTime(svVerifiedAt) + else -> TootStatus.parseTime(svVerifiedAt) } - dst.add( Field(name,value,verifiedAt)) + dst.add(Field(name, value, verifiedAt)) } return if(dst.isEmpty()) { null @@ -113,7 +113,6 @@ open class TootAccount(parser : TootParser, src : JSONObject) { } } - //URL of the user's profile page (can be remote) // https://mastodon.juggler.jp/@tateisu // 疑似アカウントではnullになります @@ -250,7 +249,16 @@ open class TootAccount(parser : TootParser, src : JSONObject) { } - parser.misskeyUserRelationMap[id]=UserRelation.parseMisskeyUser(src) + // プロフカラムで ユーザのプロフ(A)とアカウントTL(B)を順に取得すると + // (A)ではisBlockingに情報が入っているが、(B)では情報が入っていない + // 対策として(A)でリレーションを取得済みのユーザは(B)のタイミングではリレーションを読み捨てる + val map = parser.misskeyUserRelationMap + if(map[id] == null) { + val relation = UserRelation.parseMisskeyUser(src) + if( relation != null) { + map[id] = relation + } + } } else { @@ -335,7 +343,7 @@ open class TootAccount(parser : TootParser, src : JSONObject) { } ServiceType.MSP -> { - this.id = EntityId.mayDefault(src.parseLong("id") ) + this.id = EntityId.mayDefault(src.parseLong("id")) // MSPはLTLの情報しか持ってないのでacctは常にホスト名部分を持たない this.host = findHostFromUrl(null, null, url) @@ -400,9 +408,8 @@ open class TootAccount(parser : TootParser, src : JSONObject) { ).decodeEmoji(sv) } - var _orderId : EntityId? = null - - fun getOrderId() :EntityId = _orderId ?: id + + fun getOrderId() : EntityId = _orderId ?: id } diff --git a/app/src/main/java/jp/juggler/subwaytooter/api/entity/TootRelationShip.kt b/app/src/main/java/jp/juggler/subwaytooter/api/entity/TootRelationShip.kt index 6795d0fd..118ce80d 100644 --- a/app/src/main/java/jp/juggler/subwaytooter/api/entity/TootRelationShip.kt +++ b/app/src/main/java/jp/juggler/subwaytooter/api/entity/TootRelationShip.kt @@ -35,6 +35,9 @@ class TootRelationShip(src : JSONObject) { val endorsed : Boolean init { + + // Misskey はこのEntityを使わない + this.id = EntityId.mayDefault( src.parseLong("id") ) var ov = src.opt("following") diff --git a/app/src/main/java/jp/juggler/subwaytooter/table/AcctColor.kt b/app/src/main/java/jp/juggler/subwaytooter/table/AcctColor.kt index 0af0759d..fa6c0a5a 100644 --- a/app/src/main/java/jp/juggler/subwaytooter/table/AcctColor.kt +++ b/app/src/main/java/jp/juggler/subwaytooter/table/AcctColor.kt @@ -11,6 +11,8 @@ import android.text.Spannable import android.text.SpannableStringBuilder import android.text.style.BackgroundColorSpan import android.text.style.ForegroundColorSpan +import jp.juggler.subwaytooter.util.getIntOrNull +import jp.juggler.subwaytooter.util.getStringOrNull import jp.juggler.subwaytooter.util.sanitizeBDI import java.util.Locale @@ -80,7 +82,7 @@ class AcctColor { private const val CHAR_REPLACE : Char = 0x328A.toChar() - private const val load_where = COL_ACCT + "=?" + private const val load_where = "$COL_ACCT=?" private val load_where_arg = object : ThreadLocal>() { override fun initialValue() : Array { @@ -138,22 +140,13 @@ class AcctColor { App1.database.query(table, null, load_where, where_arg, null, null, null) .use { cursor -> if(cursor.moveToNext()) { - var idx : Int val ac = AcctColor(acct) - - idx = cursor.getColumnIndex(COL_COLOR_FG) - ac.color_fg = if(cursor.isNull(idx)) 0 else cursor.getInt(idx) - - idx = cursor.getColumnIndex(COL_COLOR_BG) - ac.color_bg = if(cursor.isNull(idx)) 0 else cursor.getInt(idx) - - idx = cursor.getColumnIndex(COL_NICKNAME) - ac.nickname = if(cursor.isNull(idx)) null else cursor.getString(idx) - - idx = cursor.getColumnIndex(COL_NOTIFICATION_SOUND) - ac.notification_sound = - if(cursor.isNull(idx)) null else cursor.getString(idx) + + ac.color_fg = cursor.getIntOrNull(COL_COLOR_FG) ?: 0 + ac.color_bg = cursor.getIntOrNull(COL_COLOR_BG) ?: 0 + ac.nickname = cursor.getStringOrNull(COL_NICKNAME) + ac.notification_sound = cursor.getStringOrNull(COL_NOTIFICATION_SOUND) mMemoryCache.put(acct, ac) return ac diff --git a/app/src/main/java/jp/juggler/subwaytooter/table/ClientInfo.kt b/app/src/main/java/jp/juggler/subwaytooter/table/ClientInfo.kt index 3c352bce..d800371a 100644 --- a/app/src/main/java/jp/juggler/subwaytooter/table/ClientInfo.kt +++ b/app/src/main/java/jp/juggler/subwaytooter/table/ClientInfo.kt @@ -2,12 +2,11 @@ package jp.juggler.subwaytooter.table import android.content.ContentValues import android.database.sqlite.SQLiteDatabase - -import org.json.JSONObject - import jp.juggler.subwaytooter.App1 import jp.juggler.subwaytooter.util.LogCategory +import jp.juggler.subwaytooter.util.getString import jp.juggler.subwaytooter.util.toJsonObject +import org.json.JSONObject object ClientInfo :TableCompanion { private val log = LogCategory("ClientInfo") @@ -42,7 +41,7 @@ object ClientInfo :TableCompanion { App1.database.query(table, null, "h=? and cn=?", arrayOf(instance, client_name), null, null, null) .use { cursor -> if(cursor.moveToFirst()) { - return cursor.getString(cursor.getColumnIndex(COL_RESULT)).toJsonObject() + return cursor.getString(COL_RESULT).toJsonObject() } } } catch(ex : Throwable) { diff --git a/app/src/main/java/jp/juggler/subwaytooter/table/ContentWarning.kt b/app/src/main/java/jp/juggler/subwaytooter/table/ContentWarning.kt index a0346ff2..f842c779 100644 --- a/app/src/main/java/jp/juggler/subwaytooter/table/ContentWarning.kt +++ b/app/src/main/java/jp/juggler/subwaytooter/table/ContentWarning.kt @@ -7,6 +7,7 @@ import jp.juggler.subwaytooter.App1 import jp.juggler.subwaytooter.api.entity.EntityIdString import jp.juggler.subwaytooter.api.entity.TootStatus import jp.juggler.subwaytooter.util.LogCategory +import jp.juggler.subwaytooter.util.getInt object ContentWarning : TableCompanion { private val log = LogCategory("ContentWarning") @@ -66,7 +67,7 @@ object ContentWarning : TableCompanion { null ).use { cursor -> if(cursor.moveToFirst()) { - val iv = cursor.getInt(cursor.getColumnIndex(COL_SHOWN)) + val iv = cursor.getInt(COL_SHOWN) return 0 != iv } diff --git a/app/src/main/java/jp/juggler/subwaytooter/table/ContentWarningMisskey.kt b/app/src/main/java/jp/juggler/subwaytooter/table/ContentWarningMisskey.kt index b351035c..35aaa5e9 100644 --- a/app/src/main/java/jp/juggler/subwaytooter/table/ContentWarningMisskey.kt +++ b/app/src/main/java/jp/juggler/subwaytooter/table/ContentWarningMisskey.kt @@ -6,6 +6,7 @@ import android.database.sqlite.SQLiteDatabase import jp.juggler.subwaytooter.App1 import jp.juggler.subwaytooter.api.entity.TootStatus import jp.juggler.subwaytooter.util.LogCategory +import jp.juggler.subwaytooter.util.getInt object ContentWarningMisskey : TableCompanion { private val log = LogCategory("ContentWarningMisskey") @@ -58,7 +59,7 @@ object ContentWarningMisskey : TableCompanion { null ).use { cursor -> if(cursor.moveToFirst()) { - val iv = cursor.getInt(cursor.getColumnIndex(COL_SHOWN)) + val iv = cursor.getInt(COL_SHOWN) return 0 != iv } diff --git a/app/src/main/java/jp/juggler/subwaytooter/table/HighlightWord.kt b/app/src/main/java/jp/juggler/subwaytooter/table/HighlightWord.kt index 90536848..d52b761c 100644 --- a/app/src/main/java/jp/juggler/subwaytooter/table/HighlightWord.kt +++ b/app/src/main/java/jp/juggler/subwaytooter/table/HighlightWord.kt @@ -131,14 +131,12 @@ class HighlightWord { } constructor(cursor : Cursor) { - this.id = cursor.getLong(cursor.getColumnIndex(COL_ID)) - this.name = cursor.getString(cursor.getColumnIndex(COL_NAME)) - this.color_bg = cursor.getInt(cursor.getColumnIndex(COL_COLOR_BG)) - this.color_fg = cursor.getInt(cursor.getColumnIndex(COL_COLOR_FG)) - this.sound_type = cursor.getInt(cursor.getColumnIndex(COL_SOUND_TYPE)) - val colIdx_sound_uri = cursor.getColumnIndex(COL_SOUND_URI) - this.sound_uri = - if(cursor.isNull(colIdx_sound_uri)) null else cursor.getString(colIdx_sound_uri) + this.id = cursor.getLong(COL_ID) + this.name = cursor.getString(COL_NAME) + this.color_bg = cursor.getInt(COL_COLOR_BG) + this.color_fg = cursor.getInt(COL_COLOR_FG) + this.sound_type = cursor.getInt(COL_SOUND_TYPE) + this.sound_uri = cursor.getStringOrNull(COL_SOUND_URI) } fun save() { diff --git a/app/src/main/java/jp/juggler/subwaytooter/table/MediaShown.kt b/app/src/main/java/jp/juggler/subwaytooter/table/MediaShown.kt index 10eb7ee7..f0f1a10e 100644 --- a/app/src/main/java/jp/juggler/subwaytooter/table/MediaShown.kt +++ b/app/src/main/java/jp/juggler/subwaytooter/table/MediaShown.kt @@ -7,6 +7,7 @@ import jp.juggler.subwaytooter.App1 import jp.juggler.subwaytooter.api.entity.EntityIdString import jp.juggler.subwaytooter.api.entity.TootStatus import jp.juggler.subwaytooter.util.LogCategory +import jp.juggler.subwaytooter.util.getInt object MediaShown : TableCompanion { private val log = LogCategory("MediaShown") @@ -65,7 +66,7 @@ object MediaShown : TableCompanion { null ).use { cursor -> if(cursor.moveToFirst()) { - return 0 != cursor.getInt(cursor.getColumnIndex(COL_SHOWN)) + return 0 != cursor.getInt(COL_SHOWN) } } } catch(ex : Throwable) { diff --git a/app/src/main/java/jp/juggler/subwaytooter/table/MediaShownMisskey.kt b/app/src/main/java/jp/juggler/subwaytooter/table/MediaShownMisskey.kt index 03926272..5761d8cd 100644 --- a/app/src/main/java/jp/juggler/subwaytooter/table/MediaShownMisskey.kt +++ b/app/src/main/java/jp/juggler/subwaytooter/table/MediaShownMisskey.kt @@ -6,6 +6,7 @@ import android.database.sqlite.SQLiteDatabase import jp.juggler.subwaytooter.App1 import jp.juggler.subwaytooter.api.entity.TootStatus import jp.juggler.subwaytooter.util.LogCategory +import jp.juggler.subwaytooter.util.getInt object MediaShownMisskey : TableCompanion { private val log = LogCategory("MediaShownMisskey") @@ -58,7 +59,7 @@ object MediaShownMisskey : TableCompanion { null ).use { cursor -> if(cursor.moveToFirst()) { - return 0 != cursor.getInt(cursor.getColumnIndex(COL_SHOWN)) + return 0 != cursor.getInt(COL_SHOWN) } } diff --git a/app/src/main/java/jp/juggler/subwaytooter/table/NotificationTracking.kt b/app/src/main/java/jp/juggler/subwaytooter/table/NotificationTracking.kt index 3b66657e..73339aab 100644 --- a/app/src/main/java/jp/juggler/subwaytooter/table/NotificationTracking.kt +++ b/app/src/main/java/jp/juggler/subwaytooter/table/NotificationTracking.kt @@ -9,6 +9,7 @@ import jp.juggler.subwaytooter.api.entity.EntityId import jp.juggler.subwaytooter.api.entity.putMayNull import jp.juggler.subwaytooter.util.LogCategory import jp.juggler.subwaytooter.util.getStringOrNull +import jp.juggler.subwaytooter.util.getLong class NotificationTracking { @@ -160,13 +161,13 @@ class NotificationTracking { null )?.use { cursor -> if(cursor.moveToFirst()) { - dst.id = cursor.getLong(cursor.getColumnIndex(COL_ID)) - dst.last_load = cursor.getLong(cursor.getColumnIndex(COL_LAST_LOAD)) + dst.id = cursor.getLong(COL_ID) + dst.last_load = cursor.getLong(COL_LAST_LOAD) dst.nid_show = EntityId.from(cursor, COL_NID_SHOW) dst.nid_read = EntityId.from(cursor, COL_NID_READ) dst.post_id = EntityId.from(cursor, COL_POST_ID) - dst.post_time = cursor.getLong(cursor.getColumnIndex(COL_POST_TIME)) + dst.post_time = cursor.getLong(COL_POST_TIME) dst.last_data = cursor.getStringOrNull(COL_LAST_DATA) 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 83ff0f07..a28bd656 100644 --- a/app/src/main/java/jp/juggler/subwaytooter/table/SavedAccount.kt +++ b/app/src/main/java/jp/juggler/subwaytooter/table/SavedAccount.kt @@ -94,13 +94,13 @@ class SavedAccount( } constructor(context : Context, cursor : Cursor) : this( - cursor.getLong(cursor.getColumnIndex(COL_ID)), // db_id - cursor.getString(cursor.getColumnIndex(COL_USER)), // acct - cursor.getString(cursor.getColumnIndex(COL_HOST)) // host - , _isMisskey = cursor.getInt(cursor.getColumnIndex(COL_IS_MISSKEY)).i2b() + cursor.getLong(COL_ID), // db_id + cursor.getString(COL_USER), // acct + cursor.getString(COL_HOST) // host + , _isMisskey = cursor.getBoolean(COL_IS_MISSKEY) ) { - val jsonAccount = cursor.getString(cursor.getColumnIndex(COL_ACCOUNT)).toJsonObject() + val jsonAccount = cursor.getString(COL_ACCOUNT).toJsonObject() if(jsonAccount.opt("id") == null) { // 疑似アカウント this.loginAccount = null @@ -113,60 +113,45 @@ class SavedAccount( if(loginAccount == null) { log.e( "missing loginAccount for %s", - cursor.getString(cursor.getColumnIndex(COL_ACCOUNT)) + cursor.getString(COL_ACCOUNT) ) } this.loginAccount = loginAccount } - val colIdx_visibility = cursor.getColumnIndex(COL_VISIBILITY) - val sv = if(cursor.isNull(colIdx_visibility)) null else cursor.getString(colIdx_visibility) + val sv = cursor.getStringOrNull(COL_VISIBILITY) this.visibility = TootVisibility.parseSavedVisibility(sv) ?: TootVisibility.Public - this.confirm_boost = cursor.getInt(cursor.getColumnIndex(COL_CONFIRM_BOOST)).i2b() - this.confirm_favourite = cursor.getInt(cursor.getColumnIndex(COL_CONFIRM_FAVOURITE)).i2b() - this.confirm_unboost = cursor.getInt(cursor.getColumnIndex(COL_CONFIRM_UNBOOST)).i2b() - this.confirm_unfavourite = - cursor.getInt(cursor.getColumnIndex(COL_CONFIRM_UNFAVOURITE)).i2b() + this.confirm_boost = cursor.getBoolean(COL_CONFIRM_BOOST) + this.confirm_favourite = cursor.getBoolean(COL_CONFIRM_FAVOURITE) + this.confirm_unboost = cursor.getBoolean(COL_CONFIRM_UNBOOST) + this.confirm_unfavourite = cursor.getBoolean(COL_CONFIRM_UNFAVOURITE) + this.confirm_follow = cursor.getBoolean(COL_CONFIRM_FOLLOW) + this.confirm_follow_locked = cursor.getBoolean(COL_CONFIRM_FOLLOW_LOCKED) + this.confirm_unfollow = cursor.getBoolean(COL_CONFIRM_UNFOLLOW) + this.confirm_post = cursor.getBoolean(COL_CONFIRM_POST) - this.dont_hide_nsfw = cursor.getInt(cursor.getColumnIndex(COL_DONT_HIDE_NSFW)).i2b() - this.dont_show_timeout = cursor.getInt(cursor.getColumnIndex(COL_DONT_SHOW_TIMEOUT)).i2b() + this.notification_mention = cursor.getBoolean(COL_NOTIFICATION_MENTION) + this.notification_boost = cursor.getBoolean(COL_NOTIFICATION_BOOST) + this.notification_favourite = cursor.getBoolean(COL_NOTIFICATION_FAVOURITE) + this.notification_follow = cursor.getBoolean(COL_NOTIFICATION_FOLLOW) + this.notification_reaction = cursor.getBoolean(COL_NOTIFICATION_REACTION) + this.notification_vote = cursor.getBoolean(COL_NOTIFICATION_VOTE) + + this.dont_hide_nsfw = cursor.getBoolean(COL_DONT_HIDE_NSFW) + this.dont_show_timeout = cursor.getBoolean(COL_DONT_SHOW_TIMEOUT) - this.notification_mention = - cursor.getInt(cursor.getColumnIndex(COL_NOTIFICATION_MENTION)).i2b() - this.notification_boost = cursor.getInt(cursor.getColumnIndex(COL_NOTIFICATION_BOOST)).i2b() - this.notification_favourite = - cursor.getInt(cursor.getColumnIndex(COL_NOTIFICATION_FAVOURITE)).i2b() - this.notification_follow = - cursor.getInt(cursor.getColumnIndex(COL_NOTIFICATION_FOLLOW)).i2b() + this.notification_tag = cursor.getStringOrNull(COL_NOTIFICATION_TAG) - this.notification_reaction = - cursor.getInt(cursor.getColumnIndex(COL_NOTIFICATION_REACTION)).i2b() + this.register_key = cursor.getStringOrNull(COL_REGISTER_KEY) - this.notification_vote = - cursor.getInt(cursor.getColumnIndex(COL_NOTIFICATION_VOTE)).i2b() + this.register_time = cursor.getLong(COL_REGISTER_TIME) - this.confirm_follow = cursor.getInt(cursor.getColumnIndex(COL_CONFIRM_FOLLOW)).i2b() - this.confirm_follow_locked = - cursor.getInt(cursor.getColumnIndex(COL_CONFIRM_FOLLOW_LOCKED)).i2b() - this.confirm_unfollow = cursor.getInt(cursor.getColumnIndex(COL_CONFIRM_UNFOLLOW)).i2b() - this.confirm_post = cursor.getInt(cursor.getColumnIndex(COL_CONFIRM_POST)).i2b() + this.token_info = cursor.getString(COL_TOKEN).toJsonObject() - val idx_notification_tag = cursor.getColumnIndex(COL_NOTIFICATION_TAG) - this.notification_tag = - if(cursor.isNull(idx_notification_tag)) null else cursor.getString(idx_notification_tag) + this.sound_uri = cursor.getString(COL_SOUND_URI) - val idx_register_key = cursor.getColumnIndex(COL_REGISTER_KEY) - this.register_key = - if(cursor.isNull(idx_register_key)) null else cursor.getString(idx_register_key) - - this.register_time = cursor.getLong(cursor.getColumnIndex(COL_REGISTER_TIME)) - - this.token_info = cursor.getString(cursor.getColumnIndex(COL_TOKEN)).toJsonObject() - - this.sound_uri = cursor.getString(cursor.getColumnIndex(COL_SOUND_URI)) - - this.default_text = cursor.getString(cursor.getColumnIndex(COL_DEFAULT_TEXT)) ?: "" + this.default_text = cursor.getStringOrNull(COL_DEFAULT_TEXT) ?: "" } @@ -739,7 +724,7 @@ class SavedAccount( } catch(ex : Throwable) { log.trace(ex) log.e(ex, "loadAccountList failed.") - showToast(context,true,ex.withCaption("(SubwayTooter) broken in-app database?")) + showToast(context, true, ex.withCaption("(SubwayTooter) broken in-app database?")) } return result @@ -910,7 +895,7 @@ class SavedAccount( val misskeyApiToken : String? get() = token_info?.parseString(TootApiClient.KEY_API_KEY_MISSKEY) - fun putMisskeyApiToken(params : JSONObject =JSONObject()) : JSONObject { + fun putMisskeyApiToken(params : JSONObject = JSONObject()) : JSONObject { val apiKey = misskeyApiToken if(apiKey?.isNotEmpty() == true) params.put("i", apiKey) return params diff --git a/app/src/main/java/jp/juggler/subwaytooter/table/SubscriptionServerKey.kt b/app/src/main/java/jp/juggler/subwaytooter/table/SubscriptionServerKey.kt index b1d5cd17..2dc8571b 100644 --- a/app/src/main/java/jp/juggler/subwaytooter/table/SubscriptionServerKey.kt +++ b/app/src/main/java/jp/juggler/subwaytooter/table/SubscriptionServerKey.kt @@ -6,6 +6,7 @@ import android.provider.BaseColumns import jp.juggler.subwaytooter.App1 import jp.juggler.subwaytooter.util.LogCategory +import jp.juggler.subwaytooter.util.getString object SubscriptionServerKey : TableCompanion { @@ -58,8 +59,7 @@ object SubscriptionServerKey : TableCompanion { null )?.use { cursor -> if(cursor.moveToNext()) { - val idx = cursor.getColumnIndex(COL_SERVER_KEY) - return cursor.getString(idx) + return cursor.getString(COL_SERVER_KEY) } } } catch(ex : Throwable) { diff --git a/app/src/main/java/jp/juggler/subwaytooter/table/TableUtils.kt b/app/src/main/java/jp/juggler/subwaytooter/table/TableUtils.kt index 8b802378..0c692afc 100644 --- a/app/src/main/java/jp/juggler/subwaytooter/table/TableUtils.kt +++ b/app/src/main/java/jp/juggler/subwaytooter/table/TableUtils.kt @@ -1,5 +1,6 @@ package jp.juggler.subwaytooter.table +import android.database.Cursor import android.database.sqlite.SQLiteDatabase // SQLite にBooleanをそのまま保存することはできないのでInt型との変換が必要になる @@ -11,6 +12,12 @@ fun Boolean.b2i() = if(this) 1 else 0 fun Int.i2b() = this!=0 +fun Cursor.getBoolean(keyIdx:Int) = + getInt(keyIdx).i2b() + +fun Cursor.getBoolean(key:String) = + getBoolean(getColumnIndex(key)) + interface TableCompanion{ fun onDBCreate(db : SQLiteDatabase) diff --git a/app/src/main/java/jp/juggler/subwaytooter/table/UserRelation.kt b/app/src/main/java/jp/juggler/subwaytooter/table/UserRelation.kt index 6ee8bbda..b791157f 100644 --- a/app/src/main/java/jp/juggler/subwaytooter/table/UserRelation.kt +++ b/app/src/main/java/jp/juggler/subwaytooter/table/UserRelation.kt @@ -3,22 +3,24 @@ package jp.juggler.subwaytooter.table import android.content.ContentValues import android.database.sqlite.SQLiteDatabase import android.support.v4.util.LruCache - import jp.juggler.subwaytooter.App1 import jp.juggler.subwaytooter.api.entity.EntityId import jp.juggler.subwaytooter.api.entity.EntityIdString import jp.juggler.subwaytooter.api.entity.TootAccount import jp.juggler.subwaytooter.api.entity.TootRelationShip import jp.juggler.subwaytooter.util.LogCategory +import jp.juggler.subwaytooter.util.getInt import org.json.JSONObject class UserRelation { var following : Boolean = false // 認証ユーザからのフォロー状態にある var followed_by : Boolean = false // 認証ユーザは被フォロー状態にある - var blocking : Boolean = false + var blocking : Boolean = false // 認証ユーザからブロックした + var blocked_by : Boolean = false // 認証ユーザからブロックされた(Misskeyのみ。Mastodonでは常にfalse) var muting : Boolean = false var requested : Boolean = false // 認証ユーザからのフォローは申請中である + var requested_by : Boolean = false // 相手から認証ユーザへのフォローリクエスト申請中(Misskeyのみ。Mastodonでは常にfalse) var following_reblogs : Int = 0 // このユーザからのブーストをTLに表示する var endorsed : Boolean = false // ユーザをプロフィールで紹介する @@ -221,14 +223,13 @@ class UserRelation { .use { cursor -> if(cursor.moveToNext()) { val dst = UserRelation() - dst.following = cursor.getInt(cursor.getColumnIndex(COL_FOLLOWING)).i2b() - dst.followed_by =cursor.getInt(cursor.getColumnIndex(COL_FOLLOWED_BY)).i2b() - dst.blocking = cursor.getInt(cursor.getColumnIndex(COL_BLOCKING)).i2b() - dst.muting = cursor.getInt(cursor.getColumnIndex(COL_MUTING)).i2b() - dst.requested = cursor.getInt(cursor.getColumnIndex(COL_REQUESTED)).i2b() - dst.following_reblogs = - cursor.getInt(cursor.getColumnIndex(COL_FOLLOWING_REBLOGS)) - dst.endorsed = cursor.getInt(cursor.getColumnIndex(COL_ENDORSED)).i2b() + dst.following = cursor.getBoolean(COL_FOLLOWING) + dst.followed_by =cursor.getBoolean(COL_FOLLOWED_BY) + dst.blocking = cursor.getBoolean(COL_BLOCKING) + dst.muting = cursor.getBoolean(COL_MUTING) + dst.requested = cursor.getBoolean(COL_REQUESTED) + dst.following_reblogs = cursor.getInt(COL_FOLLOWING_REBLOGS) + dst.endorsed = cursor.getBoolean(COL_ENDORSED) return dst } } @@ -240,13 +241,21 @@ class UserRelation { } // Misskey用 - fun parseMisskeyUser(src : JSONObject) = UserRelation().apply { - following = src.optBoolean("isFollowing") - followed_by = src.optBoolean("isFollowed") - muting = src.optBoolean("isMuted") - blocking = false - endorsed = false - requested = src.optBoolean("hasPendingFollowRequestFromYou") + fun parseMisskeyUser(src : JSONObject) :UserRelation? { + + // リレーションを返さない場合がある + src.opt("isFollowing") ?: return null + + return UserRelation().apply { + following = src.optBoolean("isFollowing") + followed_by = src.optBoolean("isFollowed") + muting = src.optBoolean("isMuted") + blocking = src.optBoolean("isBlocking") + blocked_by = src.optBoolean("isBlocked") + endorsed = false + requested = src.optBoolean("hasPendingFollowRequestFromYou") + requested_by = src.optBoolean("hasPendingFollowRequestToYou") + } } } diff --git a/app/src/main/java/jp/juggler/subwaytooter/table/UserRelationMisskey.kt b/app/src/main/java/jp/juggler/subwaytooter/table/UserRelationMisskey.kt index cbe0313a..2cd8e8a0 100644 --- a/app/src/main/java/jp/juggler/subwaytooter/table/UserRelationMisskey.kt +++ b/app/src/main/java/jp/juggler/subwaytooter/table/UserRelationMisskey.kt @@ -5,6 +5,7 @@ import android.database.sqlite.SQLiteDatabase import jp.juggler.subwaytooter.App1 import jp.juggler.subwaytooter.api.entity.EntityId import jp.juggler.subwaytooter.util.LogCategory +import jp.juggler.subwaytooter.util.getInt object UserRelationMisskey : TableCompanion { @@ -21,6 +22,8 @@ object UserRelationMisskey : TableCompanion { private const val COL_REQUESTED = "requested" private const val COL_FOLLOWING_REBLOGS = "following_reblogs" private const val COL_ENDORSED = "endorsed" + private const val COL_BLOCKED_BY = "blocked_by" + private const val COL_REQUESTED_BY = "requested_by" override fun onDBCreate(db : SQLiteDatabase) { log.d("onDBCreate!") @@ -38,6 +41,8 @@ object UserRelationMisskey : TableCompanion { ,$COL_REQUESTED integer not null ,$COL_FOLLOWING_REBLOGS integer not null ,$COL_ENDORSED integer default 0 + ,$COL_BLOCKED_BY integer default 0 + ,$COL_REQUESTED_BY integer default 0 )""" ) db.execSQL( @@ -60,9 +65,24 @@ object UserRelationMisskey : TableCompanion { log.trace(ex) } } + if(oldVersion < 34 && newVersion >= 34) { + try { + db.execSQL("alter table $table add column $COL_BLOCKED_BY integer default 0") + } catch(ex : Throwable) { + log.trace(ex) + } + } + if(oldVersion < 35 && newVersion >= 35) { + try { + db.execSQL("alter table $table add column $COL_REQUESTED_BY integer default 0") + } catch(ex : Throwable) { + log.trace(ex) + } + } } - fun save1(now : Long, db_id : Long, whoId : String, src : UserRelation) { + fun save1(now : Long, db_id : Long, whoId : String, src : UserRelation?) { + src?:return try { val cv = ContentValues() cv.put(COL_TIME_SAVE, now) @@ -75,6 +95,8 @@ object UserRelationMisskey : TableCompanion { cv.put(COL_REQUESTED, src.requested.b2i()) cv.put(COL_FOLLOWING_REBLOGS, src.following_reblogs) cv.put(COL_ENDORSED, src.endorsed.b2i()) + cv.put(COL_BLOCKED_BY,src.blocked_by.b2i()) + cv.put(COL_REQUESTED_BY,src.requested_by.b2i()) App1.database.replace(table, null, cv) val key = String.format("%s:%s", db_id, whoId) @@ -113,6 +135,8 @@ object UserRelationMisskey : TableCompanion { cv.put(COL_REQUESTED, src.requested.b2i()) cv.put(COL_FOLLOWING_REBLOGS, src.following_reblogs) cv.put(COL_ENDORSED, src.endorsed.b2i()) + cv.put(COL_BLOCKED_BY,src.blocked_by.b2i()) + cv.put(COL_REQUESTED_BY,src.requested_by.b2i()) db.replace(table, null, cv) } bOK = true @@ -151,15 +175,15 @@ object UserRelationMisskey : TableCompanion { .use { cursor -> if(cursor.moveToNext()) { val dst = UserRelation() - dst.following = cursor.getInt(cursor.getColumnIndex(COL_FOLLOWING)).i2b() - dst.followed_by = - cursor.getInt(cursor.getColumnIndex(COL_FOLLOWED_BY)).i2b() - dst.blocking = cursor.getInt(cursor.getColumnIndex(COL_BLOCKING)).i2b() - dst.muting = cursor.getInt(cursor.getColumnIndex(COL_MUTING)).i2b() - dst.requested = cursor.getInt(cursor.getColumnIndex(COL_REQUESTED)).i2b() - dst.following_reblogs = - cursor.getInt(cursor.getColumnIndex(COL_FOLLOWING_REBLOGS)) - dst.endorsed = cursor.getInt(cursor.getColumnIndex(COL_ENDORSED)).i2b() + dst.following = cursor.getBoolean(COL_FOLLOWING) + dst.followed_by = cursor.getBoolean(COL_FOLLOWED_BY) + dst.blocking = cursor.getBoolean(COL_BLOCKING) + dst.muting = cursor.getBoolean(COL_MUTING) + dst.requested = cursor.getBoolean(COL_REQUESTED) + dst.following_reblogs = cursor.getInt(COL_FOLLOWING_REBLOGS) + dst.endorsed =cursor.getBoolean(COL_ENDORSED) + dst.blocked_by = cursor.getBoolean(COL_BLOCKED_BY) + dst.requested_by = cursor.getBoolean(COL_REQUESTED_BY) return dst } } diff --git a/app/src/main/java/jp/juggler/subwaytooter/util/StorageUtils.kt b/app/src/main/java/jp/juggler/subwaytooter/util/StorageUtils.kt index 67c6a3f4..c6155fa9 100644 --- a/app/src/main/java/jp/juggler/subwaytooter/util/StorageUtils.kt +++ b/app/src/main/java/jp/juggler/subwaytooter/util/StorageUtils.kt @@ -9,8 +9,7 @@ import android.os.Environment import android.os.storage.StorageManager import android.webkit.MimeTypeMap import java.io.File -import java.util.ArrayList -import java.util.HashMap +import java.util.* object StorageUtils{ @@ -145,7 +144,7 @@ object StorageUtils{ val type = cursor.getType(i) if(type != Cursor.FIELD_TYPE_STRING) continue val name = cursor.getColumnName(i) - val value = if(cursor.isNull(i)) null else cursor.getString(i) + val value = cursor.getStringOrNull(i) if(value != null && value.isNotEmpty() && "filePath" == name) return File(value) } } diff --git a/app/src/main/java/jp/juggler/subwaytooter/util/Utils.kt b/app/src/main/java/jp/juggler/subwaytooter/util/Utils.kt index b204347a..67d2a781 100644 --- a/app/src/main/java/jp/juggler/subwaytooter/util/Utils.kt +++ b/app/src/main/java/jp/juggler/subwaytooter/util/Utils.kt @@ -905,14 +905,35 @@ fun showToast(context : Context, ex : Throwable, string_id : Int, vararg args : Utils.showToastImpl(context, true, ex.withCaption(context.resources, string_id, *args)) } -fun Cursor.getStringOrNull(colName : String) : String? { - val colIdx = getColumnIndex(colName) - return if(isNull(colIdx)) { - null - } else { - getString(colIdx) - } -} + +fun Cursor.getInt(key:String) = + getInt(getColumnIndex(key)) + +fun Cursor.getIntOrNull(idx:Int) = + if(isNull(idx)) null else getInt(idx) + +fun Cursor.getIntOrNull(key:String) = + getIntOrNull(getColumnIndex(key)) + +fun Cursor.getLong(key:String) = + getLong(getColumnIndex(key)) + +//fun Cursor.getLongOrNull(idx:Int) = +// if(isNull(idx)) null else getLong(idx) + +//fun Cursor.getLongOrNull(key:String) = +// getLongOrNull(getColumnIndex(key)) + +fun Cursor.getString(key:String) :String = + getString(getColumnIndex(key)) + +fun Cursor.getStringOrNull(keyIdx:Int) = + if(isNull(keyIdx)) null else getString(keyIdx) + +fun Cursor.getStringOrNull(key:String) = + getStringOrNull(getColumnIndex(key)) + + fun getDocumentName(contentResolver:ContentResolver,uri : Uri) : String { val errorName = "no_name" @@ -921,12 +942,7 @@ fun getDocumentName(contentResolver:ContentResolver,uri : Uri) : String { return if(! cursor.moveToFirst()) { errorName } else { - val colIdx = cursor.getColumnIndex(OpenableColumns.DISPLAY_NAME) - if(cursor.isNull(colIdx)) { - errorName - } else { - cursor.getString(colIdx) - } + cursor.getStringOrNull(OpenableColumns.DISPLAY_NAME) ?: errorName } } ?: errorName diff --git a/resizeLauncherIcon.pl b/resizeLauncherIcon.pl index bc91a5e9..c7a3e963 100644 --- a/resizeLauncherIcon.pl +++ b/resizeLauncherIcon.pl @@ -141,5 +141,8 @@ my $res_dir = "app/src/main/res"; # resize_scales( "_ArtWork/ic_medal.png" ,$res_dir,"drawable","ic_authorized",0,24); -resize_scales( "../extra-SubwayTooter/_ArtWork/ic_unread.png" ,$res_dir,"drawable","ic_unread",0,24); +#resize_scales( "../extra-SubwayTooter/_ArtWork/ic_unread.png" ,$res_dir,"drawable","ic_unread",0,24); + +resize_scales( "../extra-SubwayTooter/_ArtWork/ic_blocked_by.png" ,$res_dir,"drawable","ic_blocked_by",0,32); +resize_scales( "../extra-SubwayTooter/_ArtWork/ic_requested_by.png" ,$res_dir,"drawable","ic_requested_by",0,32);