(Misskey)ユーザのブロックと解除。被ブロック、被フォロー申請の表示。ただしブロックしたユーザの一覧を表示することはできない(APIがない)。
This commit is contained in:
parent
64d3aa4739
commit
486a91d996
|
@ -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
|
||||
|
|
|
@ -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
|
||||
)
|
||||
}
|
||||
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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,
|
||||
|
|
|
@ -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<TootConversationSummary> =
|
||||
{ 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<TootConversationSummary> =
|
||||
{ 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<AdapterChange>()
|
||||
|
||||
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<AdapterChange>()
|
||||
|
||||
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<AdapterChange>,
|
||||
list_new: ArrayList<TimelineItem>,
|
||||
list_data: BucketList<TimelineItem>
|
||||
){
|
||||
changeList : ArrayList<AdapterChange>,
|
||||
list_new : ArrayList<TimelineItem>,
|
||||
list_data : BucketList<TimelineItem>
|
||||
) {
|
||||
val removeSet = HashSet<EntityId>()
|
||||
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")
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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(
|
||||
|
|
|
@ -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) ) {
|
||||
/*
|
||||
ダウンロード完了通知がシステムからのものと重複することがある
|
||||
|
||||
|
|
|
@ -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
|
||||
}
|
||||
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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)
|
||||
}
|
||||
}
|
||||
})
|
||||
|
|
|
@ -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
|
||||
|
||||
}
|
||||
|
|
|
@ -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")
|
||||
|
|
|
@ -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<Array<String?>>() {
|
||||
override fun initialValue() : Array<String?> {
|
||||
|
@ -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
|
||||
|
|
|
@ -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) {
|
||||
|
|
|
@ -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
|
||||
}
|
||||
|
||||
|
|
|
@ -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
|
||||
}
|
||||
|
||||
|
|
|
@ -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() {
|
||||
|
|
|
@ -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) {
|
||||
|
|
|
@ -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)
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -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)
|
||||
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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) {
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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")
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -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
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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)
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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);
|
||||
|
||||
|
|
Loading…
Reference in New Issue