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