add push policy in account settings
This commit is contained in:
parent
970264bd3a
commit
3589e2a054
|
@ -22,6 +22,7 @@ import okio.ByteString
|
|||
import org.junit.Assert.*
|
||||
import org.junit.Test
|
||||
import org.junit.runner.RunWith
|
||||
import java.util.concurrent.atomic.AtomicReference
|
||||
|
||||
@Suppress("MemberVisibilityCanPrivate")
|
||||
@RunWith(AndroidJUnit4::class)
|
||||
|
@ -354,7 +355,7 @@ class TestTootApiClient {
|
|||
|
||||
// json error
|
||||
response = createResponseErrorCode()
|
||||
message = TootApiClient.simplifyErrorHtml(response, response.body?.string() ?: "")
|
||||
message = TootApiClient.simplifyErrorHtml(response)
|
||||
assertEquals("Error!", message)
|
||||
|
||||
// HTML error
|
||||
|
@ -367,7 +368,7 @@ class TestTootApiClient {
|
|||
.body("""<html><body>Error!</body></html>""".toResponseBody(mediaTypeHtml))
|
||||
.build()
|
||||
|
||||
message = TootApiClient.simplifyErrorHtml(response, response.body?.string() ?: "")
|
||||
message = TootApiClient.simplifyErrorHtml(response)
|
||||
assertEquals("Error!", message)
|
||||
|
||||
// other error
|
||||
|
@ -383,7 +384,7 @@ class TestTootApiClient {
|
|||
.body("Error!".toResponseBody("text/plain".toMediaType()))
|
||||
.build()
|
||||
|
||||
message = TootApiClient.simplifyErrorHtml(response, response.body?.string() ?: "")
|
||||
message =TootApiClient.simplifyErrorHtml(response)
|
||||
assertEquals("Error!", message)
|
||||
|
||||
// empty body
|
||||
|
@ -399,7 +400,7 @@ class TestTootApiClient {
|
|||
.body("".toResponseBody("text/plain".toMediaType()))
|
||||
.build()
|
||||
|
||||
message = TootApiClient.simplifyErrorHtml(response, response.body?.string() ?: "")
|
||||
message = TootApiClient.simplifyErrorHtml(response=response,caption="caption" )
|
||||
assertEquals("", message)
|
||||
}
|
||||
|
||||
|
@ -423,7 +424,7 @@ class TestTootApiClient {
|
|||
.message("This is test")
|
||||
.build()
|
||||
|
||||
message = TootApiClient.formatResponse(response, "caption", null)
|
||||
message = TootApiClient.formatResponse(response,"caption")
|
||||
|
||||
assertEquals("(HTTP 500 This is test) caption", message)
|
||||
|
||||
|
@ -440,7 +441,7 @@ class TestTootApiClient {
|
|||
.body("""{"error":"Error!"}""".toResponseBody(MEDIA_TYPE_JSON))
|
||||
.build()
|
||||
|
||||
message = TootApiClient.formatResponse(response, "caption", null)
|
||||
message = TootApiClient.formatResponse(response,"caption")
|
||||
assertEquals("Error! (HTTP 500 status-message) caption", message)
|
||||
|
||||
// json error (after reading body)
|
||||
|
@ -459,7 +460,7 @@ class TestTootApiClient {
|
|||
|
||||
bodyString = response.body?.string()
|
||||
|
||||
message = TootApiClient.formatResponse(response, "caption", bodyString)
|
||||
message = TootApiClient.formatResponse(response,"caption",bodyString)
|
||||
assertEquals("Error! (HTTP 500 status-message) caption", message)
|
||||
|
||||
// without status message
|
||||
|
@ -477,9 +478,8 @@ class TestTootApiClient {
|
|||
|
||||
bodyString = response.body?.string()
|
||||
|
||||
message = TootApiClient.formatResponse(response, "caption", bodyString)
|
||||
message = TootApiClient.formatResponse(response = response,caption = "caption",bodyString = bodyString)
|
||||
assertEquals("Error! (HTTP 500) caption", message)
|
||||
|
||||
}
|
||||
|
||||
@Test
|
||||
|
@ -1051,7 +1051,8 @@ class TestTootApiClient {
|
|||
println(url)
|
||||
|
||||
// ブラウザからコールバックで受け取ったcodeを処理する
|
||||
result = client.authentication2Mastodon(clientName, "DUMMY_CODE")
|
||||
val refToken = AtomicReference<String>(null)
|
||||
result = client.authentication2Mastodon(clientName, "DUMMY_CODE",refToken)
|
||||
jsonObject = result?.jsonObject
|
||||
assertNotNull(jsonObject)
|
||||
if (jsonObject == null) return@runBlocking
|
||||
|
|
|
@ -167,9 +167,15 @@ class ActAccountSetting : AsyncActivity(), View.OnClickListener,
|
|||
|
||||
private lateinit var spResizeImage: Spinner
|
||||
|
||||
private class ResizeItems(val config: ResizeConfig, val caption: String)
|
||||
private lateinit var spPushPolicy: Spinner
|
||||
|
||||
private lateinit var imageResizeItems: List<ResizeItems>
|
||||
private class ResizeItem(val config: ResizeConfig, val caption: String)
|
||||
|
||||
private lateinit var imageResizeItems: List<ResizeItem>
|
||||
|
||||
private class PushPolicyItem(val id: String?, val caption: String)
|
||||
|
||||
private lateinit var pushPolicyItems: List<PushPolicyItem>
|
||||
|
||||
///////////////////////////////////////////////////
|
||||
|
||||
|
@ -336,6 +342,7 @@ class ActAccountSetting : AsyncActivity(), View.OnClickListener,
|
|||
etMediaSizeMax = findViewById(R.id.etMediaSizeMax)
|
||||
etMovieSizeMax = findViewById(R.id.etMovieSizeMax)
|
||||
spResizeImage = findViewById(R.id.spResizeImage)
|
||||
spPushPolicy = findViewById(R.id.spPushPolicy)
|
||||
|
||||
imageResizeItems = SavedAccount.resizeConfigList.map {
|
||||
val caption = when (it.type) {
|
||||
|
@ -355,7 +362,7 @@ class ActAccountSetting : AsyncActivity(), View.OnClickListener,
|
|||
)
|
||||
}
|
||||
}
|
||||
ResizeItems(it, caption)
|
||||
ResizeItem(it, caption)
|
||||
}
|
||||
spResizeImage.adapter = ArrayAdapter(
|
||||
this,
|
||||
|
@ -365,6 +372,22 @@ class ActAccountSetting : AsyncActivity(), View.OnClickListener,
|
|||
setDropDownViewResource(R.layout.lv_spinner_dropdown)
|
||||
}
|
||||
|
||||
pushPolicyItems = listOf(
|
||||
PushPolicyItem(null, getString(R.string.unspecified)),
|
||||
PushPolicyItem("all", getString(R.string.all)),
|
||||
PushPolicyItem("followed", getString(R.string.following)),
|
||||
PushPolicyItem("follower", getString(R.string.followers)),
|
||||
PushPolicyItem("none", getString(R.string.no_one)),
|
||||
)
|
||||
|
||||
spPushPolicy.adapter = ArrayAdapter(
|
||||
this,
|
||||
android.R.layout.simple_spinner_item,
|
||||
pushPolicyItems.map { it.caption }.toTypedArray()
|
||||
).apply {
|
||||
setDropDownViewResource(R.layout.lv_spinner_dropdown)
|
||||
}
|
||||
|
||||
listEtFieldName = arrayOf(
|
||||
R.id.etFieldName1,
|
||||
R.id.etFieldName2,
|
||||
|
@ -438,6 +461,7 @@ class ActAccountSetting : AsyncActivity(), View.OnClickListener,
|
|||
|
||||
spResizeImage.onItemSelectedListener = this
|
||||
|
||||
spPushPolicy.onItemSelectedListener = this
|
||||
|
||||
btnNotificationStyleEditReply.vg(Pref.bpSeparateReplyNotificationGroup(pref))
|
||||
|
||||
|
@ -587,18 +611,28 @@ class ActAccountSetting : AsyncActivity(), View.OnClickListener,
|
|||
etMediaSizeMax.setText(a.image_max_megabytes ?: "")
|
||||
etMovieSizeMax.setText(a.movie_max_megabytes ?: "")
|
||||
} else {
|
||||
etMediaSizeMax.setText(a.image_max_megabytes
|
||||
?: a.getImageMaxBytes(ti).div(1000000).toString())
|
||||
etMovieSizeMax.setText(a.movie_max_megabytes
|
||||
?: a.getMovieMaxBytes(ti).div(1000000).toString())
|
||||
etMediaSizeMax.setText(
|
||||
a.image_max_megabytes
|
||||
?: a.getImageMaxBytes(ti).div(1000000).toString()
|
||||
)
|
||||
etMovieSizeMax.setText(
|
||||
a.movie_max_megabytes
|
||||
?: a.getMovieMaxBytes(ti).div(1000000).toString()
|
||||
)
|
||||
}
|
||||
|
||||
val currentResizeConfig = a.getResizeConfig()
|
||||
var index = imageResizeItems.indexOfFirst { it.config.spec == currentResizeConfig.spec }
|
||||
log.d("ResizeItem current ${currentResizeConfig.spec} index=$index ")
|
||||
if (index == -1) index = imageResizeItems.indexOfFirst { it.config.spec == SavedAccount.defaultResizeConfig.spec }
|
||||
if (index == -1) index =
|
||||
imageResizeItems.indexOfFirst { it.config.spec == SavedAccount.defaultResizeConfig.spec }
|
||||
spResizeImage.setSelection(index, false)
|
||||
|
||||
val currentPushPolicy = a.push_policy
|
||||
index = pushPolicyItems.indexOfFirst { it.id == currentPushPolicy }
|
||||
if (index == -1) index = 0
|
||||
spPushPolicy.setSelection(index, false)
|
||||
|
||||
showVisibility()
|
||||
showAcctColor()
|
||||
}
|
||||
|
@ -657,6 +691,9 @@ class ActAccountSetting : AsyncActivity(), View.OnClickListener,
|
|||
?: SavedAccount.defaultResizeConfig
|
||||
).spec
|
||||
|
||||
account.push_policy =
|
||||
pushPolicyItems.elementAtOrNull(spPushPolicy.selectedItemPosition)?.id
|
||||
|
||||
account.saveSetting()
|
||||
|
||||
}
|
||||
|
|
|
@ -577,9 +577,9 @@ class ActMediaViewer : AppCompatActivity(), View.OnClickListener {
|
|||
|
||||
if (client.isApiCancelled) return Pair(null, null)
|
||||
|
||||
val response = requireNotNull(result.response)
|
||||
val response = result.response!!
|
||||
if (!response.isSuccessful) {
|
||||
result.setError(TootApiClient.formatResponse(response, result.caption))
|
||||
result.parseErrorResponse()
|
||||
return Pair(result, null)
|
||||
}
|
||||
|
||||
|
@ -594,7 +594,7 @@ class ActMediaViewer : AppCompatActivity(), View.OnClickListener {
|
|||
if (client.isApiCancelled) return Pair(null, null)
|
||||
return Pair(result, ba)
|
||||
} catch (ex: Throwable) {
|
||||
result.setError(TootApiClient.formatResponse(response, result.caption, "?"))
|
||||
result.parseErrorResponse( "?")
|
||||
return Pair(result, null)
|
||||
}
|
||||
}
|
||||
|
|
|
@ -369,17 +369,14 @@ class ActPost : AsyncActivity(),
|
|||
val request = Request.Builder().url(url).build()
|
||||
val call = App1.ok_http_client.newCall(request)
|
||||
val response = call.await()
|
||||
if (response.isSuccessful) {
|
||||
return true
|
||||
}
|
||||
log.e(TootApiClient.formatResponse(response, "check_exist failed."))
|
||||
if (response.isSuccessful) return true
|
||||
|
||||
log.e(TootApiClient.formatResponse(response,"check_exist failed."))
|
||||
} catch (ex: Throwable) {
|
||||
log.trace(ex)
|
||||
}
|
||||
|
||||
return false
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
private lateinit var btnAccount: Button
|
||||
|
|
|
@ -124,8 +124,9 @@ class App1 : Application() {
|
|||
// 2020/9/20 56=>57 SavedAccountテーブルに項目追加
|
||||
// 2020/9/20 57=>58 UserRelationテーブルに項目追加
|
||||
// 2021/2/10 58=>59 SavedAccountテーブルに項目追加
|
||||
// 2021/5/11 59=>60 SavedAccountテーブルに項目追加
|
||||
|
||||
internal const val DB_VERSION = 59
|
||||
internal const val DB_VERSION = 60
|
||||
|
||||
private val tableList = arrayOf(
|
||||
LogData,
|
||||
|
|
|
@ -42,82 +42,10 @@ class TootApiClient(
|
|||
|
||||
private val reStartJsonArray = """\A\s*\[""".asciiPattern()
|
||||
private val reStartJsonObject = """\A\s*\{""".asciiPattern()
|
||||
private val reWhiteSpace = """\s+""".asciiPattern()
|
||||
|
||||
|
||||
val DEFAULT_JSON_ERROR_PARSER =
|
||||
{ json: JsonObject -> json["error"]?.toString() }
|
||||
|
||||
internal fun simplifyErrorHtml(
|
||||
response: Response,
|
||||
sv: String,
|
||||
jsonErrorParser: (json: JsonObject) -> String? = DEFAULT_JSON_ERROR_PARSER
|
||||
): String {
|
||||
|
||||
// JsonObjectとして解釈できるならエラーメッセージを検出する
|
||||
try {
|
||||
val json = sv.decodeJsonObject()
|
||||
val error_message =
|
||||
jsonErrorParser(json)?.notEmpty()
|
||||
if (error_message != null) {
|
||||
return error_message
|
||||
}
|
||||
} catch (_: Throwable) {
|
||||
}
|
||||
|
||||
// HTMLならタグの除去を試みる
|
||||
val ct = response.body?.contentType()
|
||||
if (ct?.subtype == "html") {
|
||||
val decoded = DecodeOptions().decodeHTML(sv).toString()
|
||||
return reWhiteSpace.matcher(decoded).replaceAll(" ").trim()
|
||||
}
|
||||
|
||||
// XXX: Amazon S3 が403を返した場合にcontent-typeが?/xmlでserverがAmazonならXMLをパースしてエラーを整形することもできるが、多分必要ない
|
||||
|
||||
return reWhiteSpace.matcher(sv).replaceAll(" ").trim()
|
||||
}
|
||||
|
||||
fun formatResponse(
|
||||
response: Response,
|
||||
caption: String,
|
||||
bodyString: String? = null,
|
||||
jsonErrorParser: (json: JsonObject) -> String? = DEFAULT_JSON_ERROR_PARSER
|
||||
): String {
|
||||
val sb = StringBuilder()
|
||||
try {
|
||||
// body は既に読み終わっているか、そうでなければこれから読む
|
||||
if (bodyString != null) {
|
||||
sb.append(simplifyErrorHtml(response, bodyString, jsonErrorParser))
|
||||
} else {
|
||||
try {
|
||||
val string = response.body?.string()
|
||||
if (string != null) {
|
||||
sb.append(simplifyErrorHtml(response, string, jsonErrorParser))
|
||||
}
|
||||
} catch (ex: Throwable) {
|
||||
log.e(ex, "missing response body.")
|
||||
sb.append("(missing response body)")
|
||||
}
|
||||
}
|
||||
|
||||
if (sb.isNotEmpty()) sb.append(' ')
|
||||
sb.append("(HTTP ").append(response.code.toString())
|
||||
|
||||
val message = response.message
|
||||
if (message.isNotEmpty()) sb.append(' ').append(message)
|
||||
sb.append(")")
|
||||
|
||||
if (caption.isNotEmpty()) {
|
||||
sb.append(' ').append(caption)
|
||||
}
|
||||
|
||||
} catch (ex: Throwable) {
|
||||
log.trace(ex)
|
||||
}
|
||||
|
||||
return sb.toString().replace("\n+".toRegex(), "\n")
|
||||
}
|
||||
|
||||
fun getScopeString(ti: TootInstance?) = when {
|
||||
// 古いサーバ
|
||||
ti?.versionGE(TootInstance.VERSION_2_4_0_rc1) == false -> "read+write+follow"
|
||||
|
@ -198,6 +126,25 @@ class TootApiClient(
|
|||
return encodeScopeArray(a) == encodeScopeArray(b)
|
||||
}
|
||||
|
||||
fun formatResponse(
|
||||
response: Response,
|
||||
caption: String = "?",
|
||||
bodyString: String? = null
|
||||
) = TootApiResult(
|
||||
response = response,
|
||||
caption = caption,
|
||||
bodyString = bodyString
|
||||
).apply { parseErrorResponse() }.error ?: "(null)"
|
||||
|
||||
fun simplifyErrorHtml(
|
||||
response: Response,
|
||||
caption:String = "?",
|
||||
bodyString:String =response.body?.string() ?: "",
|
||||
jsonErrorParser: (json: JsonObject) -> String? = DEFAULT_JSON_ERROR_PARSER
|
||||
) = TootApiResult(
|
||||
response = response,
|
||||
caption = caption,
|
||||
).simplifyErrorHtml( bodyString,jsonErrorParser)
|
||||
}
|
||||
|
||||
// 認証に関する設定を保存する
|
||||
|
@ -345,11 +292,8 @@ class TootApiClient(
|
|||
}
|
||||
|
||||
if (!response.isSuccessful || bodyString?.isEmpty() != false) {
|
||||
|
||||
result.error = formatResponse(
|
||||
response,
|
||||
result.caption,
|
||||
if (bodyString?.isNotEmpty() == true) bodyString else NO_INFORMATION,
|
||||
result.parseErrorResponse(
|
||||
bodyString?.notEmpty() ?: NO_INFORMATION,
|
||||
jsonErrorParser
|
||||
)
|
||||
}
|
||||
|
@ -388,11 +332,8 @@ class TootApiClient(
|
|||
if (isApiCancelled) return null
|
||||
|
||||
if (!response.isSuccessful || bodyBytes?.isEmpty() != false) {
|
||||
|
||||
result.error = formatResponse(
|
||||
response,
|
||||
result.caption,
|
||||
if (bodyBytes?.isNotEmpty() == true) bodyBytes.decodeUTF8() else NO_INFORMATION,
|
||||
result.parseErrorResponse(
|
||||
bodyBytes?.notEmpty()?.decodeUTF8() ?: NO_INFORMATION,
|
||||
jsonErrorParser
|
||||
)
|
||||
}
|
||||
|
@ -411,16 +352,12 @@ class TootApiClient(
|
|||
progressPath: String? = null,
|
||||
jsonErrorParser: (json: JsonObject) -> String? = DEFAULT_JSON_ERROR_PARSER
|
||||
): TootApiResult? {
|
||||
|
||||
val response = result.response!! // nullにならないはず
|
||||
|
||||
try {
|
||||
readBodyBytes(result, progressPath, jsonErrorParser)
|
||||
?: return if (isApiCancelled) null else result
|
||||
} catch (ex: Throwable) {
|
||||
log.trace(ex)
|
||||
result.error =
|
||||
formatResponse(response, result.caption, result.bodyString ?: NO_INFORMATION)
|
||||
result.parseErrorResponse(result.bodyString ?: NO_INFORMATION)
|
||||
}
|
||||
return result
|
||||
}
|
||||
|
@ -430,19 +367,14 @@ class TootApiClient(
|
|||
progressPath: String? = null,
|
||||
jsonErrorParser: (json: JsonObject) -> String? = DEFAULT_JSON_ERROR_PARSER
|
||||
): TootApiResult? {
|
||||
|
||||
val response = result.response!! // nullにならないはず
|
||||
|
||||
try {
|
||||
val bodyString = readBodyString(result, progressPath, jsonErrorParser)
|
||||
?: return if (isApiCancelled) null else result
|
||||
|
||||
result.data = bodyString
|
||||
|
||||
} catch (ex: Throwable) {
|
||||
log.trace(ex)
|
||||
result.error =
|
||||
formatResponse(response, result.caption, result.bodyString ?: NO_INFORMATION)
|
||||
result.parseErrorResponse(result.bodyString ?: NO_INFORMATION)
|
||||
}
|
||||
return result
|
||||
}
|
||||
|
@ -506,8 +438,7 @@ class TootApiClient(
|
|||
|
||||
} catch (ex: Throwable) {
|
||||
log.trace(ex)
|
||||
result.error =
|
||||
formatResponse(response, result.caption, result.bodyString ?: NO_INFORMATION)
|
||||
result.parseErrorResponse(result.bodyString ?: NO_INFORMATION)
|
||||
}
|
||||
return result
|
||||
|
||||
|
|
|
@ -1,5 +1,6 @@
|
|||
package jp.juggler.subwaytooter.api
|
||||
|
||||
import jp.juggler.subwaytooter.util.DecodeOptions
|
||||
import jp.juggler.util.*
|
||||
import okhttp3.Response
|
||||
import okhttp3.WebSocket
|
||||
|
@ -8,6 +9,7 @@ open class TootApiResult(
|
|||
@Suppress("unused") val dummy : Int = 0,
|
||||
var error : String? = null,
|
||||
var response : Response? = null,
|
||||
var caption : String = "?",
|
||||
var bodyString : String? = null
|
||||
) {
|
||||
|
||||
|
@ -15,6 +17,8 @@ open class TootApiResult(
|
|||
|
||||
private val log = LogCategory("TootApiResult")
|
||||
|
||||
private val reWhiteSpace = """\s+""".asciiPattern()
|
||||
|
||||
private val reLinkURL = """<([^>]+)>;\s*rel="([^"]+)"""".asciiPattern()
|
||||
|
||||
fun makeWithCaption(caption : String?) : TootApiResult {
|
||||
|
@ -52,7 +56,7 @@ open class TootApiResult(
|
|||
|
||||
var link_older : String? = null // より古いデータへのリンク
|
||||
var link_newer : String? = null // より新しいデータへの
|
||||
var caption : String = "?"
|
||||
|
||||
|
||||
constructor() : this(0)
|
||||
|
||||
|
@ -97,4 +101,75 @@ open class TootApiResult(
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
// アカウント作成APIのdetailsを読むため、エラー応答のjsonオブジェクトを保持する
|
||||
var errorJson : JsonObject? = null
|
||||
|
||||
internal fun simplifyErrorHtml(
|
||||
sv: String,
|
||||
jsonErrorParser: (json: JsonObject) -> String? = TootApiClient.DEFAULT_JSON_ERROR_PARSER
|
||||
): String {
|
||||
val response = this.response!!
|
||||
|
||||
// JsonObjectとして解釈できるならエラーメッセージを検出する
|
||||
try {
|
||||
val json = sv.decodeJsonObject()
|
||||
this.errorJson = json
|
||||
jsonErrorParser(json)?.notEmpty()?.let{ return it }
|
||||
} catch (_: Throwable) {
|
||||
}
|
||||
|
||||
// HTMLならタグの除去を試みる
|
||||
val ct = response.body?.contentType()
|
||||
if (ct?.subtype == "html") {
|
||||
val decoded = DecodeOptions().decodeHTML(sv).toString()
|
||||
return reWhiteSpace.matcher(decoded).replaceAll(" ").trim()
|
||||
}
|
||||
|
||||
// XXX: Amazon S3 が403を返した場合にcontent-typeが?/xmlでserverがAmazonならXMLをパースしてエラーを整形することもできるが、多分必要ない
|
||||
|
||||
return reWhiteSpace.matcher(sv).replaceAll(" ").trim()
|
||||
}
|
||||
|
||||
fun parseErrorResponse(
|
||||
bodyString: String? = null,
|
||||
jsonErrorParser: (json: JsonObject) -> String? = TootApiClient.DEFAULT_JSON_ERROR_PARSER
|
||||
){
|
||||
val response = this.response!!
|
||||
|
||||
val sb = StringBuilder()
|
||||
try {
|
||||
// body は既に読み終わっているか、そうでなければこれから読む
|
||||
if (bodyString != null) {
|
||||
sb.append(simplifyErrorHtml( bodyString, jsonErrorParser))
|
||||
} else {
|
||||
try {
|
||||
val string = response.body?.string()
|
||||
if (string != null) {
|
||||
sb.append(simplifyErrorHtml( string, jsonErrorParser))
|
||||
}
|
||||
} catch (ex: Throwable) {
|
||||
log.e(ex, "missing response body.")
|
||||
sb.append("(missing response body)")
|
||||
}
|
||||
}
|
||||
|
||||
if (sb.isNotEmpty()) sb.append(' ')
|
||||
sb.append("(HTTP ").append(response.code.toString())
|
||||
|
||||
val message = response.message
|
||||
if (message.isNotEmpty()) sb.append(' ').append(message)
|
||||
sb.append(")")
|
||||
|
||||
if (caption.isNotEmpty()) {
|
||||
sb.append(' ').append(caption)
|
||||
}
|
||||
|
||||
} catch (ex: Throwable) {
|
||||
log.trace(ex)
|
||||
}
|
||||
|
||||
this.error = sb.toString().replace("\n+".toRegex(), "\n")
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -397,7 +397,7 @@ class PollingWorker private constructor(contextArg: Context) {
|
|||
|
||||
private val workerNotifier = Channel<Unit>(capacity = Channel.CONFLATED)
|
||||
|
||||
fun notifyWorker(){
|
||||
fun notifyWorker() {
|
||||
GlobalScope.launch { workerNotifier.send(Unit) }
|
||||
}
|
||||
|
||||
|
@ -607,7 +607,6 @@ class PollingWorker private constructor(contextArg: Context) {
|
|||
}
|
||||
|
||||
|
||||
|
||||
// JobService#onStopJob から呼ばれる
|
||||
// return True to indicate to the JobManager whether you'd like to reschedule this job based on the retry criteria provided at job creation-time.
|
||||
// return False to drop the job. Regardless of the value returned, your job must stop executing.
|
||||
|
@ -616,7 +615,7 @@ class PollingWorker private constructor(contextArg: Context) {
|
|||
|
||||
// 同じジョブ番号がジョブリストにあるか?
|
||||
synchronized(startedJobList) {
|
||||
startedJobList.removeFirst { it.jobId == jobId }?.let{ item->
|
||||
startedJobList.removeFirst { it.jobId == jobId }?.let { item ->
|
||||
log.w("onStopJob: jobId=${jobId}, set cancel flag.")
|
||||
// リソースがなくてStopされるのだからrescheduleはtrue
|
||||
item.cancel(true)
|
||||
|
@ -644,12 +643,11 @@ class PollingWorker private constructor(contextArg: Context) {
|
|||
}
|
||||
|
||||
|
||||
|
||||
// ポーリングが完了した
|
||||
fun onPollingComplete(requiredNextPolling:Boolean) {
|
||||
when(requiredNextPolling) {
|
||||
fun onPollingComplete(requiredNextPolling: Boolean) {
|
||||
when (requiredNextPolling) {
|
||||
// まだスケジュールされてないなら登録する
|
||||
true-> if (! scheduler.allPendingJobs.any { it.id == JobId.Polling.int } ) {
|
||||
true -> if (!scheduler.allPendingJobs.any { it.id == JobId.Polling.int }) {
|
||||
log.d("registering next polling…")
|
||||
scheduleJob(context, JobId.Polling)
|
||||
}
|
||||
|
@ -664,7 +662,7 @@ class PollingWorker private constructor(contextArg: Context) {
|
|||
}
|
||||
|
||||
// ジョブ完了後にメインスレッドで呼ばれる
|
||||
fun onJobComplete(item:JobItem) {
|
||||
fun onJobComplete(item: JobItem) {
|
||||
|
||||
synchronized(startedJobList) {
|
||||
startedJobList.remove(item)
|
||||
|
@ -683,7 +681,7 @@ class PollingWorker private constructor(contextArg: Context) {
|
|||
}
|
||||
|
||||
// return false if app data import started.
|
||||
fun onStartTask(taskId: TaskId):Boolean {
|
||||
fun onStartTask(taskId: TaskId): Boolean {
|
||||
@Suppress("NON_EXHAUSTIVE_WHEN")
|
||||
when (taskId) {
|
||||
TaskId.AppDataImportBefore -> {
|
||||
|
|
|
@ -16,10 +16,7 @@ import jp.juggler.subwaytooter.api.TootApiClient
|
|||
import jp.juggler.subwaytooter.api.TootApiResult
|
||||
import jp.juggler.subwaytooter.api.TootParser
|
||||
import jp.juggler.subwaytooter.api.entity.*
|
||||
import jp.juggler.subwaytooter.table.AcctColor
|
||||
import jp.juggler.subwaytooter.table.NotificationCache
|
||||
import jp.juggler.subwaytooter.table.NotificationTracking
|
||||
import jp.juggler.subwaytooter.table.SavedAccount
|
||||
import jp.juggler.subwaytooter.table.*
|
||||
import jp.juggler.subwaytooter.util.PushSubscriptionHelper
|
||||
import jp.juggler.util.*
|
||||
import kotlinx.coroutines.*
|
||||
|
@ -35,7 +32,7 @@ class TaskRunner(
|
|||
private val taskId: TaskId,
|
||||
private val taskData: JsonObject
|
||||
) {
|
||||
companion object{
|
||||
companion object {
|
||||
private val log = LogCategory("TaskRunner")
|
||||
|
||||
private var workerStatus = ""
|
||||
|
@ -70,7 +67,7 @@ class TaskRunner(
|
|||
pollingWorker.processInjectedData(job.injectedAccounts)
|
||||
|
||||
TaskId.ResetTrackingState ->
|
||||
NotificationTracking.resetTrackingState( taskData.long(PollingWorker.EXTRA_DB_ID))
|
||||
NotificationTracking.resetTrackingState(taskData.long(PollingWorker.EXTRA_DB_ID))
|
||||
|
||||
// プッシュ通知が届いた
|
||||
TaskId.FcmMessage -> {
|
||||
|
@ -106,7 +103,8 @@ class TaskRunner(
|
|||
|
||||
TaskId.NotificationDelete -> {
|
||||
val db_id = taskData.long(PollingWorker.EXTRA_DB_ID)
|
||||
val type = TrackingType.parseStr(taskData.string(PollingWorker.EXTRA_NOTIFICATION_TYPE))
|
||||
val type =
|
||||
TrackingType.parseStr(taskData.string(PollingWorker.EXTRA_NOTIFICATION_TYPE))
|
||||
val typeName = type.typeName
|
||||
val id = taskData.string(PollingWorker.EXTRA_NOTIFICATION_ID)
|
||||
log.d("Notification deleted! db_id=$db_id,type=$type,id=$id")
|
||||
|
@ -118,7 +116,8 @@ class TaskRunner(
|
|||
|
||||
TaskId.NotificationClick -> {
|
||||
val db_id = taskData.long(PollingWorker.EXTRA_DB_ID)
|
||||
val type = TrackingType.parseStr(taskData.string(PollingWorker.EXTRA_NOTIFICATION_TYPE))
|
||||
val type =
|
||||
TrackingType.parseStr(taskData.string(PollingWorker.EXTRA_NOTIFICATION_TYPE))
|
||||
val typeName = type.typeName
|
||||
val id = taskData.string(PollingWorker.EXTRA_NOTIFICATION_ID).notEmpty()
|
||||
log.d("Notification clicked! db_id=$db_id,type=$type,id=$id")
|
||||
|
@ -132,7 +131,10 @@ class TaskRunner(
|
|||
val itemTag = "$notification_tag/$id"
|
||||
notification_manager.cancel(itemTag, PollingWorker.NOTIFICATION_ID)
|
||||
} else {
|
||||
notification_manager.cancel(notification_tag, PollingWorker.NOTIFICATION_ID)
|
||||
notification_manager.cancel(
|
||||
notification_tag,
|
||||
PollingWorker.NOTIFICATION_ID
|
||||
)
|
||||
}
|
||||
// DB更新処理
|
||||
NotificationTracking.updateRead(db_id, typeName)
|
||||
|
@ -179,7 +181,8 @@ class TaskRunner(
|
|||
liveSet.add(t.account.apiHost)
|
||||
}
|
||||
if (liveSet.isEmpty()) break
|
||||
PollingWorker.workerStatus = "waiting ${liveSet.joinToString(", ") { it.pretty }}"
|
||||
PollingWorker.workerStatus =
|
||||
"waiting ${liveSet.joinToString(", ") { it.pretty }}"
|
||||
delay(if (job.isJobCancelled) 100L else 1000L)
|
||||
}
|
||||
|
||||
|
@ -208,6 +211,36 @@ class TaskRunner(
|
|||
|
||||
private var currentCall: WeakReference<Call>? = null
|
||||
|
||||
private var policyFilter: (TootNotification) -> Boolean = when (account.push_policy) {
|
||||
|
||||
"followed" -> { it ->
|
||||
val who = it.account
|
||||
when {
|
||||
who == null -> true
|
||||
account.isMe(who) -> true
|
||||
|
||||
else -> UserRelation.load(account.db_id, who.id).following
|
||||
}
|
||||
}
|
||||
|
||||
"follower" -> { it ->
|
||||
val who = it.account
|
||||
when {
|
||||
it.type == TootNotification.TYPE_FOLLOW ||
|
||||
it.type == TootNotification.TYPE_FOLLOW_REQUEST -> true
|
||||
|
||||
who == null -> true
|
||||
account.isMe(who) -> true
|
||||
|
||||
else -> UserRelation.load(account.db_id, who.id).followed_by
|
||||
}
|
||||
}
|
||||
|
||||
"none" -> { _ -> false }
|
||||
|
||||
else -> { _ -> true }
|
||||
}
|
||||
|
||||
///////////////////
|
||||
|
||||
val isActive: Boolean
|
||||
|
@ -353,11 +386,14 @@ class TaskRunner(
|
|||
private val duplicate_check = HashSet<EntityId>()
|
||||
private val dstListData = LinkedList<NotificationData>()
|
||||
|
||||
|
||||
fun checkAccount() {
|
||||
|
||||
this.nr = NotificationTracking.load(account.acct.pretty, account.db_id, trackingName)
|
||||
this.nr =
|
||||
NotificationTracking.load(account.acct.pretty, account.db_id, trackingName)
|
||||
|
||||
fun JsonObject.isMention() = when (NotificationCache.parseNotificationType(account, this)) {
|
||||
fun JsonObject.isMention() =
|
||||
when (NotificationCache.parseNotificationType(account, this)) {
|
||||
TootNotification.TYPE_REPLY, TootNotification.TYPE_MENTION -> true
|
||||
else -> false
|
||||
}
|
||||
|
@ -425,6 +461,9 @@ class TaskRunner(
|
|||
}
|
||||
}
|
||||
|
||||
// Mastodon 3.4.0rc1 push policy
|
||||
if (!policyFilter(notification)) return
|
||||
|
||||
// 後から処理したものが先頭に来る
|
||||
dstListData.add(0, NotificationData(account, notification))
|
||||
}
|
||||
|
@ -692,7 +731,7 @@ class TaskRunner(
|
|||
// FLAG_ACTIVITY_LAUNCHED_FROM_HISTORY を付与してはいけない
|
||||
addFlags(Intent.FLAG_ACTIVITY_NEW_TASK)
|
||||
},
|
||||
PendingIntent.FLAG_UPDATE_CURRENT or (if(Build.VERSION.SDK_INT>=23) PendingIntent.FLAG_IMMUTABLE else 0)
|
||||
PendingIntent.FLAG_UPDATE_CURRENT or (if (Build.VERSION.SDK_INT >= 23) PendingIntent.FLAG_IMMUTABLE else 0)
|
||||
)
|
||||
)
|
||||
|
||||
|
@ -705,7 +744,7 @@ class TaskRunner(
|
|||
data =
|
||||
"subwaytooter://notification_delete/?$params".toUri()
|
||||
},
|
||||
PendingIntent.FLAG_UPDATE_CURRENT or (if(Build.VERSION.SDK_INT>=23) PendingIntent.FLAG_IMMUTABLE else 0)
|
||||
PendingIntent.FLAG_UPDATE_CURRENT or (if (Build.VERSION.SDK_INT >= 23) PendingIntent.FLAG_IMMUTABLE else 0)
|
||||
)
|
||||
)
|
||||
|
||||
|
@ -730,7 +769,11 @@ class TaskRunner(
|
|||
|
||||
log.d("showNotification[${account.acct.pretty}] set notification...")
|
||||
|
||||
notification_manager.notify(notification_tag, PollingWorker.NOTIFICATION_ID, builder.build())
|
||||
notification_manager.notify(
|
||||
notification_tag,
|
||||
PollingWorker.NOTIFICATION_ID,
|
||||
builder.build()
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -748,7 +791,7 @@ class TaskRunner(
|
|||
context,
|
||||
3,
|
||||
intent_click,
|
||||
PendingIntent.FLAG_UPDATE_CURRENT or (if(Build.VERSION.SDK_INT>=23) PendingIntent.FLAG_IMMUTABLE else 0)
|
||||
PendingIntent.FLAG_UPDATE_CURRENT or (if (Build.VERSION.SDK_INT >= 23) PendingIntent.FLAG_IMMUTABLE else 0)
|
||||
)
|
||||
|
||||
val builder = if (Build.VERSION.SDK_INT >= 26) {
|
||||
|
@ -799,7 +842,6 @@ class TaskRunner(
|
|||
}
|
||||
|
||||
|
||||
|
||||
private fun NotificationData.getNotificationLine(): String {
|
||||
|
||||
val name = when (Pref.bpShowAcctInSystemNotification(pref)) {
|
||||
|
@ -861,7 +903,7 @@ class TaskRunner(
|
|||
}
|
||||
|
||||
private fun deleteCacheData(db_id: Long?) {
|
||||
if(db_id != null) {
|
||||
if (db_id != null) {
|
||||
log.d("Notification clear! db_id=$db_id")
|
||||
SavedAccount.loadAccount(context, db_id) ?: return
|
||||
NotificationCache.deleteCache(db_id)
|
||||
|
|
|
@ -80,6 +80,8 @@ class SavedAccount(
|
|||
var image_max_megabytes : String? = null
|
||||
var movie_max_megabytes : String? = null
|
||||
|
||||
var push_policy : String? = null
|
||||
|
||||
init {
|
||||
val tmpAcct = Acct.parse(acctArg)
|
||||
this.username = tmpAcct.username
|
||||
|
@ -165,6 +167,7 @@ class SavedAccount(
|
|||
image_resize = cursor.getStringOrNull(COL_IMAGE_RESIZE)
|
||||
image_max_megabytes = cursor.getStringOrNull(COL_IMAGE_MAX_MEGABYTES)
|
||||
movie_max_megabytes = cursor.getStringOrNull(COL_MOVIE_MAX_MEGABYTES)
|
||||
push_policy = cursor.getStringOrNull(COL_PUSH_POLICY)
|
||||
}
|
||||
|
||||
val isNA : Boolean
|
||||
|
@ -232,6 +235,7 @@ class SavedAccount(
|
|||
cv.putOrNull(COL_IMAGE_RESIZE,image_resize)
|
||||
cv.putOrNull(COL_IMAGE_MAX_MEGABYTES, image_max_megabytes)
|
||||
cv.putOrNull(COL_MOVIE_MAX_MEGABYTES, movie_max_megabytes)
|
||||
cv.putOrNull(COL_PUSH_POLICY,push_policy)
|
||||
|
||||
// UIからは更新しない
|
||||
// notification_tag
|
||||
|
@ -298,6 +302,7 @@ class SavedAccount(
|
|||
this.image_resize = b.image_resize
|
||||
this.image_max_megabytes = b.image_max_megabytes
|
||||
this.movie_max_megabytes = b.movie_max_megabytes
|
||||
this.push_policy = b.push_policy
|
||||
}
|
||||
|
||||
fun getFullAcct(who : TootAccount?) = getFullAcct(who?.acct)
|
||||
|
@ -400,6 +405,8 @@ class SavedAccount(
|
|||
private const val COL_IMAGE_MAX_MEGABYTES = "image_max_megabytes" // スキーマ59
|
||||
private const val COL_MOVIE_MAX_MEGABYTES = "movie_max_megabytes" // スキーマ59
|
||||
|
||||
private const val COL_PUSH_POLICY = "push_policy" // スキーマ60
|
||||
|
||||
/////////////////////////////////
|
||||
// login information
|
||||
const val INVALID_DB_ID = - 1L
|
||||
|
@ -497,6 +504,9 @@ class SavedAccount(
|
|||
+ ",$COL_IMAGE_MAX_MEGABYTES text default null"
|
||||
+ ",$COL_MOVIE_MAX_MEGABYTES text default null"
|
||||
|
||||
// スキーマ60から
|
||||
+ ",$COL_PUSH_POLICY text default null"
|
||||
|
||||
+ ")"
|
||||
)
|
||||
db.execSQL("create index if not exists ${table}_user on ${table}(u)")
|
||||
|
@ -504,7 +514,11 @@ class SavedAccount(
|
|||
}
|
||||
|
||||
override fun onDBUpgrade(db : SQLiteDatabase, oldVersion : Int, newVersion : Int) {
|
||||
if(oldVersion < 2 && newVersion >= 2) {
|
||||
fun isUpgraded(n:Int,block:()->Unit){
|
||||
if( oldVersion < n && newVersion >= n ) block()
|
||||
}
|
||||
|
||||
isUpgraded(2){
|
||||
try {
|
||||
db.execSQL("alter table $table add column notification_mention integer default 1")
|
||||
} catch(ex : Throwable) {
|
||||
|
@ -530,7 +544,7 @@ class SavedAccount(
|
|||
}
|
||||
|
||||
}
|
||||
if(oldVersion < 10 && newVersion >= 10) {
|
||||
isUpgraded( 10) {
|
||||
try {
|
||||
db.execSQL("alter table $table add column $COL_CONFIRM_FOLLOW integer default 1")
|
||||
} catch(ex : Throwable) {
|
||||
|
@ -556,7 +570,7 @@ class SavedAccount(
|
|||
}
|
||||
|
||||
}
|
||||
if(oldVersion < 13 && newVersion >= 13) {
|
||||
isUpgraded( 13) {
|
||||
try {
|
||||
db.execSQL("alter table $table add column $COL_NOTIFICATION_TAG text default ''")
|
||||
} catch(ex : Throwable) {
|
||||
|
@ -564,7 +578,7 @@ class SavedAccount(
|
|||
}
|
||||
|
||||
}
|
||||
if(oldVersion < 14 && newVersion >= 14) {
|
||||
isUpgraded( 14) {
|
||||
try {
|
||||
db.execSQL("alter table $table add column $COL_REGISTER_KEY text default ''")
|
||||
} catch(ex : Throwable) {
|
||||
|
@ -578,7 +592,7 @@ class SavedAccount(
|
|||
}
|
||||
|
||||
}
|
||||
if(oldVersion < 16 && newVersion >= 16) {
|
||||
isUpgraded( 16) {
|
||||
try {
|
||||
db.execSQL("alter table $table add column $COL_SOUND_URI text default ''")
|
||||
} catch(ex : Throwable) {
|
||||
|
@ -586,7 +600,7 @@ class SavedAccount(
|
|||
}
|
||||
|
||||
}
|
||||
if(oldVersion < 18 && newVersion >= 18) {
|
||||
isUpgraded( 18) {
|
||||
try {
|
||||
db.execSQL("alter table $table add column $COL_DONT_SHOW_TIMEOUT integer default 0")
|
||||
} catch(ex : Throwable) {
|
||||
|
@ -594,7 +608,7 @@ class SavedAccount(
|
|||
}
|
||||
|
||||
}
|
||||
if(oldVersion < 23 && newVersion >= 23) {
|
||||
isUpgraded( 23) {
|
||||
try {
|
||||
db.execSQL("alter table $table add column $COL_CONFIRM_FAVOURITE integer default 1")
|
||||
} catch(ex : Throwable) {
|
||||
|
@ -602,7 +616,7 @@ class SavedAccount(
|
|||
}
|
||||
|
||||
}
|
||||
if(oldVersion < 24 && newVersion >= 24) {
|
||||
isUpgraded( 24) {
|
||||
try {
|
||||
db.execSQL("alter table $table add column $COL_CONFIRM_UNFAVOURITE integer default 1")
|
||||
} catch(ex : Throwable) {
|
||||
|
@ -615,7 +629,7 @@ class SavedAccount(
|
|||
}
|
||||
|
||||
}
|
||||
if(oldVersion < 27 && newVersion >= 27) {
|
||||
isUpgraded( 27) {
|
||||
try {
|
||||
db.execSQL("alter table $table add column $COL_DEFAULT_TEXT text default ''")
|
||||
} catch(ex : Throwable) {
|
||||
|
@ -623,7 +637,7 @@ class SavedAccount(
|
|||
}
|
||||
|
||||
}
|
||||
if(oldVersion < 28 && newVersion >= 28) {
|
||||
isUpgraded( 28) {
|
||||
try {
|
||||
db.execSQL("alter table $table add column $COL_MISSKEY_VERSION integer default 0")
|
||||
} catch(ex : Throwable) {
|
||||
|
@ -631,7 +645,7 @@ class SavedAccount(
|
|||
}
|
||||
}
|
||||
|
||||
if(oldVersion < 33 && newVersion >= 33) {
|
||||
isUpgraded( 33) {
|
||||
try {
|
||||
db.execSQL("alter table $table add column $COL_NOTIFICATION_REACTION integer default 1")
|
||||
} catch(ex : Throwable) {
|
||||
|
@ -644,7 +658,7 @@ class SavedAccount(
|
|||
}
|
||||
}
|
||||
|
||||
if(oldVersion < 38 && newVersion >= 38) {
|
||||
isUpgraded( 38) {
|
||||
try {
|
||||
db.execSQL("alter table $table add column $COL_DEFAULT_SENSITIVE integer default 0")
|
||||
} catch(ex : Throwable) {
|
||||
|
@ -658,7 +672,7 @@ class SavedAccount(
|
|||
|
||||
}
|
||||
|
||||
if(oldVersion < 39 && newVersion >= 39) {
|
||||
isUpgraded( 39) {
|
||||
try {
|
||||
db.execSQL("alter table $table add column $COL_MAX_TOOT_CHARS integer default 0")
|
||||
} catch(ex : Throwable) {
|
||||
|
@ -666,7 +680,7 @@ class SavedAccount(
|
|||
}
|
||||
}
|
||||
|
||||
if(oldVersion < 42 && newVersion >= 42) {
|
||||
isUpgraded( 42) {
|
||||
try {
|
||||
db.execSQL("alter table $table add column $COL_LAST_NOTIFICATION_ERROR text")
|
||||
} catch(ex : Throwable) {
|
||||
|
@ -674,7 +688,7 @@ class SavedAccount(
|
|||
}
|
||||
}
|
||||
|
||||
if(oldVersion < 44 && newVersion >= 44) {
|
||||
isUpgraded( 44) {
|
||||
try {
|
||||
db.execSQL("alter table $table add column $COL_NOTIFICATION_FOLLOW_REQUEST integer default 1")
|
||||
} catch(ex : Throwable) {
|
||||
|
@ -682,28 +696,28 @@ class SavedAccount(
|
|||
}
|
||||
}
|
||||
|
||||
if(oldVersion < 45 && newVersion >= 45) {
|
||||
isUpgraded( 45) {
|
||||
try {
|
||||
db.execSQL("alter table $table add column $COL_LAST_SUBSCRIPTION_ERROR text")
|
||||
} catch(ex : Throwable) {
|
||||
log.trace(ex)
|
||||
}
|
||||
}
|
||||
if(oldVersion < 46 && newVersion >= 46) {
|
||||
isUpgraded(46) {
|
||||
try {
|
||||
db.execSQL("alter table $table add column $COL_LAST_PUSH_ENDPOINT text")
|
||||
} catch(ex : Throwable) {
|
||||
log.trace(ex)
|
||||
}
|
||||
}
|
||||
if(oldVersion < 56 && newVersion >= 56) {
|
||||
isUpgraded( 56) {
|
||||
try {
|
||||
db.execSQL("alter table $table add column $COL_DOMAIN text")
|
||||
} catch(ex : Throwable) {
|
||||
log.trace(ex)
|
||||
}
|
||||
}
|
||||
if(oldVersion < 57 && newVersion >= 57) {
|
||||
isUpgraded( 57) {
|
||||
try {
|
||||
db.execSQL("alter table $table add column $COL_NOTIFICATION_POST integer default 1")
|
||||
} catch(ex : Throwable) {
|
||||
|
@ -711,7 +725,7 @@ class SavedAccount(
|
|||
}
|
||||
|
||||
}
|
||||
if(oldVersion < 59 && newVersion >= 59) {
|
||||
isUpgraded( 59) {
|
||||
try {
|
||||
db.execSQL("alter table $table add column $COL_IMAGE_RESIZE text default null")
|
||||
} catch(ex : Throwable) {
|
||||
|
@ -728,6 +742,13 @@ class SavedAccount(
|
|||
log.trace(ex)
|
||||
}
|
||||
}
|
||||
isUpgraded( 60) {
|
||||
try {
|
||||
db.execSQL("alter table $table add column $COL_PUSH_POLICY text default null")
|
||||
} catch(ex : Throwable) {
|
||||
log.trace(ex)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
val defaultResizeConfig = ResizeConfig(ResizeType.LongSide, 1280)
|
||||
|
|
|
@ -480,6 +480,7 @@ class PushSubscriptionHelper(
|
|||
})
|
||||
put("data", JsonObject().apply {
|
||||
put("alerts", newAlerts)
|
||||
account.push_policy?.let{ put("policy",it )}
|
||||
})
|
||||
}
|
||||
|
||||
|
|
|
@ -8,3 +8,6 @@ fun <E : List<*>> E?.notEmpty(): E? =
|
|||
|
||||
fun <E : Map<*, *>> E?.notEmpty(): E? =
|
||||
if (this?.isNotEmpty() == true) this else null
|
||||
|
||||
fun ByteArray?.notEmpty(): ByteArray? =
|
||||
if (this?.isNotEmpty() == true) this else null
|
||||
|
|
|
@ -458,152 +458,109 @@
|
|||
style="@style/setting_row_label"
|
||||
android:text="@string/confirmation" />
|
||||
|
||||
<LinearLayout style="@style/setting_row_form">
|
||||
|
||||
<CheckBox
|
||||
android:id="@+id/cbConfirmFollow"
|
||||
style="@style/setting_horizontal_stretch"
|
||||
style="@style/setting_row_form"
|
||||
android:text="@string/follow" />
|
||||
|
||||
</LinearLayout>
|
||||
|
||||
<LinearLayout style="@style/setting_row_form">
|
||||
|
||||
<CheckBox
|
||||
android:id="@+id/cbConfirmFollowLockedUser"
|
||||
style="@style/setting_horizontal_stretch"
|
||||
style="@style/setting_row_form"
|
||||
android:text="@string/follow_locked_user" />
|
||||
|
||||
</LinearLayout>
|
||||
|
||||
<LinearLayout style="@style/setting_row_form">
|
||||
|
||||
<CheckBox
|
||||
android:id="@+id/cbConfirmUnfollow"
|
||||
style="@style/setting_horizontal_stretch"
|
||||
style="@style/setting_row_form"
|
||||
android:text="@string/unfollow" />
|
||||
|
||||
</LinearLayout>
|
||||
|
||||
<LinearLayout style="@style/setting_row_form">
|
||||
|
||||
<CheckBox
|
||||
android:id="@+id/cbConfirmBoost"
|
||||
style="@style/setting_wrap"
|
||||
style="@style/setting_row_form"
|
||||
android:text="@string/boost" />
|
||||
|
||||
</LinearLayout>
|
||||
|
||||
<LinearLayout style="@style/setting_row_form">
|
||||
|
||||
<CheckBox
|
||||
android:id="@+id/cbConfirmUnboost"
|
||||
style="@style/setting_wrap"
|
||||
style="@style/setting_row_form"
|
||||
android:text="@string/unboost" />
|
||||
|
||||
</LinearLayout>
|
||||
|
||||
<LinearLayout style="@style/setting_row_form">
|
||||
|
||||
<CheckBox
|
||||
android:id="@+id/cbConfirmFavourite"
|
||||
style="@style/setting_wrap"
|
||||
style="@style/setting_row_form"
|
||||
android:text="@string/favourite" />
|
||||
|
||||
</LinearLayout>
|
||||
|
||||
<LinearLayout style="@style/setting_row_form">
|
||||
|
||||
<CheckBox
|
||||
android:id="@+id/cbConfirmUnfavourite"
|
||||
style="@style/setting_wrap"
|
||||
style="@style/setting_row_form"
|
||||
android:text="@string/unfavourite" />
|
||||
|
||||
</LinearLayout>
|
||||
|
||||
<LinearLayout style="@style/setting_row_form">
|
||||
|
||||
<CheckBox
|
||||
android:id="@+id/cbConfirmToot"
|
||||
style="@style/setting_wrap"
|
||||
style="@style/setting_row_form"
|
||||
android:text="@string/act_post" />
|
||||
|
||||
</LinearLayout>
|
||||
|
||||
<View style="@style/setting_divider" />
|
||||
|
||||
<TextView
|
||||
style="@style/setting_row_label"
|
||||
android:text="@string/notifications" />
|
||||
|
||||
<LinearLayout style="@style/setting_row_form">
|
||||
|
||||
<CheckBox
|
||||
android:id="@+id/cbNotificationMention"
|
||||
style="@style/setting_horizontal_stretch"
|
||||
style="@style/setting_row_form"
|
||||
android:text="@string/mention2" />
|
||||
</LinearLayout>
|
||||
|
||||
<LinearLayout style="@style/setting_row_form">
|
||||
|
||||
<CheckBox
|
||||
android:id="@+id/cbNotificationBoost"
|
||||
style="@style/setting_horizontal_stretch"
|
||||
style="@style/setting_row_form"
|
||||
android:text="@string/boost" />
|
||||
</LinearLayout>
|
||||
|
||||
<LinearLayout style="@style/setting_row_form">
|
||||
|
||||
<CheckBox
|
||||
android:id="@+id/cbNotificationFavourite"
|
||||
style="@style/setting_horizontal_stretch"
|
||||
style="@style/setting_row_form"
|
||||
android:text="@string/favourite" />
|
||||
</LinearLayout>
|
||||
|
||||
<LinearLayout style="@style/setting_row_form">
|
||||
|
||||
<CheckBox
|
||||
android:id="@+id/cbNotificationFollow"
|
||||
style="@style/setting_horizontal_stretch"
|
||||
style="@style/setting_row_form"
|
||||
android:text="@string/follow" />
|
||||
</LinearLayout>
|
||||
|
||||
<LinearLayout style="@style/setting_row_form">
|
||||
|
||||
<CheckBox
|
||||
android:id="@+id/cbNotificationFollowRequest"
|
||||
style="@style/setting_horizontal_stretch"
|
||||
style="@style/setting_row_form"
|
||||
android:text="@string/follow_request" />
|
||||
</LinearLayout>
|
||||
|
||||
<LinearLayout style="@style/setting_row_form">
|
||||
|
||||
<CheckBox
|
||||
android:id="@+id/cbNotificationReaction"
|
||||
style="@style/setting_horizontal_stretch"
|
||||
style="@style/setting_row_form"
|
||||
android:text="@string/reaction" />
|
||||
</LinearLayout>
|
||||
|
||||
<LinearLayout style="@style/setting_row_form">
|
||||
|
||||
<CheckBox
|
||||
android:id="@+id/cbNotificationVote"
|
||||
style="@style/setting_horizontal_stretch"
|
||||
style="@style/setting_row_form"
|
||||
android:text="@string/vote_polls" />
|
||||
</LinearLayout>
|
||||
|
||||
<LinearLayout style="@style/setting_row_form">
|
||||
|
||||
<CheckBox
|
||||
android:id="@+id/cbNotificationPost"
|
||||
style="@style/setting_horizontal_stretch"
|
||||
style="@style/setting_row_form"
|
||||
android:text="@string/notification_type_post" />
|
||||
</LinearLayout>
|
||||
|
||||
<TextView
|
||||
style="@style/setting_row_form"
|
||||
android:layout_marginTop="12dp"
|
||||
android:text="@string/push_notification_filter" />
|
||||
|
||||
<Spinner
|
||||
android:id="@+id/spPushPolicy"
|
||||
style="@style/setting_row_button"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:minHeight="40dp"
|
||||
/>
|
||||
|
||||
<Button
|
||||
android:id="@+id/btnPushSubscription"
|
||||
style="@style/setting_row_button"
|
||||
android:layout_marginTop="12dp"
|
||||
android:ellipsize="start"
|
||||
android:text="@string/update_push_subscription"
|
||||
android:textAllCaps="false" />
|
||||
|
|
|
@ -865,7 +865,7 @@
|
|||
<string name="header_icon_size">ヘッダ部アイコンの大きさ(単位:dp。デフォルト:24。アプリ再起動が必要)</string>
|
||||
<string name="header_text_size">ヘッダ部テキストの大きさ(単位:sp。デフォルト:14。アプリ再起動が必要)</string>
|
||||
<string name="strip_icon_size">カラムストリップのアイコンの大きさ(単位:dp。デフォルト:30。アプリ再起動が必要)</string>
|
||||
<string name="all">All</string>
|
||||
<string name="all">全て</string>
|
||||
<string name="show_links_in_context_menu">本文中のリンクをコンテキストメニューに表示する</string>
|
||||
<string name="scheduled_status_requires_mastodon_2_7_0">予約投稿はマストドン2.7.0以降で使えます</string>
|
||||
<string name="move_notifications_quick_filter_to_column_setting">通知カラムのクイックフィルタをカラム設定内部に表示する(アプリ再起動が必要)</string>
|
||||
|
@ -1077,5 +1077,7 @@
|
|||
<string name="update_mail_address">登録メールアドレスを変更する</string>
|
||||
<string name="resend_confirm_mail_requested">確認メールの再送を要求しました。</string>
|
||||
<string name="confirm_mail_description">確認メールの再送を要求した後の手順:\n- あなたのメーラーで新着メールが届くのを確認する。\n- メール中の確認リンクを開く。\n- このダイアログを閉じてカラムをリロードする。</string>
|
||||
<string name="push_notification_filter">プッシュ通知フィルタ(Mastodon 3.4.0以降。プッシュ通知の更新が必要)</string>
|
||||
<string name="no_one">誰もいない</string>
|
||||
|
||||
</resources>
|
||||
|
|
|
@ -1091,4 +1091,6 @@
|
|||
<string name="update_mail_address">Update e-mail address</string>
|
||||
<string name="resend_confirm_mail_requested">Resending confirm E-mail was requested.</string>
|
||||
<string name="confirm_mail_description">After requesting resending confirm E-mail,\n- please check the mail on your mailer.\n- open confirm link in the mail.\n- close this dialog and reload column.</string>
|
||||
<string name="push_notification_filter">Push notification filter (Mastodon 3.4.0+, requires update push subscription)</string>
|
||||
<string name="no_one">No one</string>
|
||||
</resources>
|
||||
|
|
Loading…
Reference in New Issue