1
0
mirror of https://github.com/tateisu/SubwayTooter synced 2025-02-09 16:48:47 +01:00

firebase messaging のtoken id の取得方法が非同期になった。文字列リソース中のパーセント表記のエスケープを修正。

This commit is contained in:
tateisu 2020-12-07 03:32:21 +09:00
parent 9913f89d95
commit 15a845e0e2
19 changed files with 1628 additions and 1604 deletions

View File

@ -68,6 +68,7 @@
<w>ihdr</w> <w>ihdr</w>
<w>infos</w> <w>infos</w>
<w>iptc</w> <w>iptc</w>
<w>jetbrains</w>
<w>jfif</w> <w>jfif</w>
<w>jwcp</w> <w>jwcp</w>
<w>kapt</w> <w>kapt</w>

View File

@ -105,9 +105,10 @@ dependencies {
// PreferenceManager // PreferenceManager
implementation "androidx.preference:preference-ktx:1.1.1" implementation "androidx.preference:preference-ktx:1.1.1"
implementation "androidx.exifinterface:exifinterface:1.3.1" implementation "androidx.exifinterface:exifinterface:1.3.2"
// CustomTabs // CustomTabs
// TODO 1.3.0 調
implementation "androidx.browser:browser:1.2.0" implementation "androidx.browser:browser:1.2.0"
// Recyclerview // Recyclerview
@ -123,7 +124,8 @@ dependencies {
testImplementation "org.jetbrains.kotlin:kotlin-test:$kotlin_version" testImplementation "org.jetbrains.kotlin:kotlin-test:$kotlin_version"
implementation "org.jetbrains.kotlinx:kotlinx-coroutines-core:$kotlinx_coroutines_version" implementation "org.jetbrains.kotlinx:kotlinx-coroutines-core:$kotlinx_coroutines_version"
implementation "org.jetbrains.kotlinx:kotlinx-coroutines-android:$kotlinx_coroutines_version" implementation "org.jetbrains.kotlinx:kotlinx-coroutines-play-services:$kotlinx_coroutines_version"
implementation("ru.gildor.coroutines:kotlin-coroutines-okhttp:1.0")
// Anko Layouts // Anko Layouts
// sdk15, sdk19, sdk21, sdk23 are also available // sdk15, sdk19, sdk21, sdk23 are also available

View File

@ -35,6 +35,7 @@ import jp.juggler.util.*
import kotlinx.coroutines.Dispatchers import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.GlobalScope import kotlinx.coroutines.GlobalScope
import kotlinx.coroutines.launch import kotlinx.coroutines.launch
import kotlinx.coroutines.runBlocking
import okhttp3.MediaType import okhttp3.MediaType
import okhttp3.MediaType.Companion.toMediaType import okhttp3.MediaType.Companion.toMediaType
import okhttp3.MultipartBody import okhttp3.MultipartBody
@ -1580,7 +1581,9 @@ class ActAccountSetting : AsyncActivity(), View.OnClickListener,
) )
override fun background(client : TootApiClient) : TootApiResult? { override fun background(client : TootApiClient) : TootApiResult? {
return wps.updateSubscription(client, true) return runBlocking{
wps.updateSubscription(client, true)
}
} }
override fun handleResult(result : TootApiResult?) { override fun handleResult(result : TootApiResult?) {

View File

@ -538,7 +538,11 @@ class Column(
// プロフカラムでのアカウント情報 // プロフカラムでのアカウント情報
@Volatile @Volatile
internal var who_account : TootAccountRef? = null internal var who_account : TootAccountRef? = null
// プロフカラムでのfeatured tag 情報(Mastodon3.3.0)
@Volatile
internal var who_featured_tags : List<TootTag>? = null
// リストカラムでのリスト情報 // リストカラムでのリスト情報
@Volatile @Volatile
internal var list_info : TootList? = null internal var list_info : TootList? = null
@ -1733,8 +1737,14 @@ class Column(
client.request(String.format(Locale.JAPAN, PATH_ACCOUNT, profile_id))?.also { result1 -> client.request(String.format(Locale.JAPAN, PATH_ACCOUNT, profile_id))?.also { result1 ->
TootAccountRef.mayNull(parser, parser.account(result1.jsonObject))?.also { a -> TootAccountRef.mayNull(parser, parser.account(result1.jsonObject))?.also { a ->
this.who_account = a this.who_account = a
this.who_featured_tags = null
client.request("/api/v1/accounts/${profile_id}/featured_tags")?.also{ result2->
this.who_featured_tags =TootTag.parseListOrNull(parser,result2.jsonArray)
}
client.publishApiProgress("") // カラムヘッダの再表示 client.publishApiProgress("") // カラムヘッダの再表示
} }
} }
} }

File diff suppressed because it is too large Load Diff

View File

@ -2,6 +2,7 @@ package jp.juggler.subwaytooter
import android.app.Dialog import android.app.Dialog
import android.graphics.Color import android.graphics.Color
import android.text.Spannable
import android.text.SpannableStringBuilder import android.text.SpannableStringBuilder
import android.text.Spanned import android.text.Spanned
import android.text.style.ForegroundColorSpan import android.text.style.ForegroundColorSpan
@ -11,19 +12,16 @@ import jp.juggler.emoji.EmojiMap
import jp.juggler.subwaytooter.action.Action_Follow import jp.juggler.subwaytooter.action.Action_Follow
import jp.juggler.subwaytooter.action.Action_User import jp.juggler.subwaytooter.action.Action_User
import jp.juggler.subwaytooter.api.* import jp.juggler.subwaytooter.api.*
import jp.juggler.subwaytooter.api.entity.TootAccount import jp.juggler.subwaytooter.api.entity.*
import jp.juggler.subwaytooter.api.entity.TootAccountRef
import jp.juggler.subwaytooter.api.entity.TootStatus
import jp.juggler.subwaytooter.dialog.DlgTextInput import jp.juggler.subwaytooter.dialog.DlgTextInput
import jp.juggler.subwaytooter.span.EmojiImageSpan import jp.juggler.subwaytooter.span.EmojiImageSpan
import jp.juggler.subwaytooter.span.LinkInfo
import jp.juggler.subwaytooter.span.MyClickableSpan
import jp.juggler.subwaytooter.span.createSpan import jp.juggler.subwaytooter.span.createSpan
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.util.DecodeOptions import jp.juggler.subwaytooter.util.*
import jp.juggler.subwaytooter.util.NetworkEmojiInvalidator
import jp.juggler.subwaytooter.util.openCustomTab
import jp.juggler.subwaytooter.util.startMargin
import jp.juggler.subwaytooter.view.MyLinkMovementMethod import jp.juggler.subwaytooter.view.MyLinkMovementMethod
import jp.juggler.subwaytooter.view.MyNetworkImageView import jp.juggler.subwaytooter.view.MyNetworkImageView
import jp.juggler.subwaytooter.view.MyTextView import jp.juggler.subwaytooter.view.MyTextView
@ -38,6 +36,8 @@ internal class ViewHolderHeaderProfile(
private val ivBackground : MyNetworkImageView private val ivBackground : MyNetworkImageView
private val tvCreated : TextView private val tvCreated : TextView
private val tvLastStatusAt : TextView private val tvLastStatusAt : TextView
private val tvFeaturedTags : TextView
private val ivAvatar : MyNetworkImageView private val ivAvatar : MyNetworkImageView
private val tvDisplayName : TextView private val tvDisplayName : TextView
private val tvAcct : TextView private val tvAcct : TextView
@ -79,6 +79,7 @@ internal class ViewHolderHeaderProfile(
llProfile = viewRoot.findViewById(R.id.llProfile) llProfile = viewRoot.findViewById(R.id.llProfile)
tvCreated = viewRoot.findViewById(R.id.tvCreated) tvCreated = viewRoot.findViewById(R.id.tvCreated)
tvLastStatusAt = viewRoot.findViewById(R.id.tvLastStatusAt) tvLastStatusAt = viewRoot.findViewById(R.id.tvLastStatusAt)
tvFeaturedTags = viewRoot.findViewById(R.id.tvFeaturedTags)
ivAvatar = viewRoot.findViewById(R.id.ivAvatar) ivAvatar = viewRoot.findViewById(R.id.ivAvatar)
tvDisplayName = viewRoot.findViewById(R.id.tvDisplayName) tvDisplayName = viewRoot.findViewById(R.id.tvDisplayName)
tvAcct = viewRoot.findViewById(R.id.tvAcct) tvAcct = viewRoot.findViewById(R.id.tvAcct)
@ -160,6 +161,7 @@ internal class ViewHolderHeaderProfile(
tvMovedName.textSize = f tvMovedName.textSize = f
tvMoved.textSize = f tvMoved.textSize = f
tvPersonalNotes.textSize = f tvPersonalNotes.textSize = f
tvFeaturedTags.textSize = f
} }
f = activity.acct_font_size_sp f = activity.acct_font_size_sp
@ -187,7 +189,8 @@ internal class ViewHolderHeaderProfile(
btnStatusCount.textColor = contentColor btnStatusCount.textColor = contentColor
btnFollowing.textColor = contentColor btnFollowing.textColor = contentColor
btnFollowers.textColor = contentColor btnFollowers.textColor = contentColor
tvFeaturedTags.textColor = contentColor
setIconDrawableId( setIconDrawableId(
activity, activity,
btnMore, btnMore,
@ -208,6 +211,7 @@ internal class ViewHolderHeaderProfile(
tvCreated.textColor = acctColor tvCreated.textColor = acctColor
tvMovedAcct.textColor = acctColor tvMovedAcct.textColor = acctColor
tvLastStatusAt.textColor = acctColor tvLastStatusAt.textColor = acctColor
val whoRef = column.who_account val whoRef = column.who_account
this.whoRef = whoRef this.whoRef = whoRef
@ -231,6 +235,7 @@ internal class ViewHolderHeaderProfile(
relation = null relation = null
tvCreated.text = "" tvCreated.text = ""
tvLastStatusAt.vg(false) tvLastStatusAt.vg(false)
tvFeaturedTags.vg(false)
ivBackground.setImageDrawable(null) ivBackground.setImageDrawable(null)
ivAvatar.setImageDrawable(null) ivAvatar.setImageDrawable(null)
@ -259,6 +264,28 @@ internal class ViewHolderHeaderProfile(
invalidator = null, invalidator = null,
fromProfileHeader = true fromProfileHeader = true
) )
val featuredTagsText = column.who_featured_tags?.notEmpty()?.let{ tagList->
SpannableStringBuilder().apply {
append(activity.getString(R.string.featured_hashtags))
append(":")
tagList.forEach { tag ->
append(" ")
val tagWithSharp = "#" + tag.name
val start = length
append(tagWithSharp)
val end = length
tag.url?.notEmpty()?.let{ url->
val span = MyClickableSpan(LinkInfo(url = url, tag = tag.name, caption = tagWithSharp))
setSpan(span, start, end, Spannable.SPAN_EXCLUSIVE_EXCLUSIVE)
}
}
}
}
tvFeaturedTags.vg( featuredTagsText !=null)?.let{
it.text = featuredTagsText!!
it.movementMethod = MyLinkMovementMethod
}
ivBackground.setImageUrl( ivBackground.setImageUrl(
activity.pref, activity.pref,

View File

@ -24,10 +24,10 @@ class TootParser(
val misskeyUserRelationMap = HashMap<EntityId, UserRelation>() val misskeyUserRelationMap = HashMap<EntityId, UserRelation>()
// val misskeyAccountDetailMap = HashMap<EntityId, TootAccount>() // val misskeyAccountDetailMap = HashMap<EntityId, TootAccount>()
val apiHost : Host? val apiHost : Host
get() = linkHelper.apiHost get() = linkHelper.apiHost
val apDomain : Host? val apDomain : Host
get() = linkHelper.apDomain get() = linkHelper.apDomain
init { init {

View File

@ -127,9 +127,10 @@ open class TootAccount(parser : TootParser, src : JsonObject) : HostAndDomain {
init { init {
this.json = src this.json = src
src["_fromStream"] = parser.fromStream src["_fromStream"] = parser.fromStream
if(parser.serviceType == ServiceType.MISSKEY) { if(parser.serviceType == ServiceType.MISSKEY) {
this.custom_emojis = this.custom_emojis =
parseMapOrNull(CustomEmoji.decodeMisskey, src.jsonArray("emojis")) parseMapOrNull(CustomEmoji.decodeMisskey, src.jsonArray("emojis"))
this.profile_emojis = null this.profile_emojis = null

View File

@ -7,181 +7,187 @@ import jp.juggler.util.*
import java.util.regex.Pattern import java.util.regex.Pattern
open class TootTag constructor( open class TootTag constructor(
// The hashtag, not including the preceding # // The hashtag, not including the preceding #
val name : String, val name: String,
// The URL of the hashtag. may null if generated from TootContext // The URL of the hashtag. may null if generated from TootContext
val url : String? = null, val url: String? = null,
// Mastodon /api/v2/search provides history. // Mastodon /api/v2/search provides history.
val history : ArrayList<History>? = null val history: ArrayList<History>? = null
) : TimelineItem() { ) : TimelineItem() {
val countDaily : Int val countDaily: Int
val countWeekly : Int val countWeekly: Int
val accountDaily : Int val accountDaily: Int
val accountWeekly : Int val accountWeekly: Int
init { init {
countDaily = history?.first()?.uses ?: 0 countDaily = history?.first()?.uses ?: 0
countWeekly = history?.sumBy { it.uses } ?: 0 countWeekly = history?.sumBy { it.uses } ?: 0
accountDaily = history?.first()?.accounts ?: 0 accountDaily = history?.first()?.accounts ?: 0
accountWeekly = history?.map { it.accounts }?.maxOrNull() ?: accountDaily accountWeekly = history?.map { it.accounts }?.maxOrNull() ?: accountDaily
} }
class History(src : JsonObject) { class History(src: JsonObject) {
private val day : Long private val day: Long
val uses : Int val uses: Int
val accounts : Int val accounts: Int
init { init {
day = src.long("day") day = src.long("day")
?: throw RuntimeException("TootTrendTag.History: missing day") ?: throw RuntimeException("TootTrendTag.History: missing day")
uses = src.int("uses") uses = src.int("uses")
?: throw RuntimeException("TootTrendTag.History: missing uses") ?: throw RuntimeException("TootTrendTag.History: missing uses")
accounts = src.int("accounts") accounts = src.int("accounts")
?: throw RuntimeException("TootTrendTag.History: missing accounts") ?: throw RuntimeException("TootTrendTag.History: missing accounts")
} }
} }
companion object { companion object {
val log = LogCategory("TootTag") val log = LogCategory("TootTag")
fun parse(parser : TootParser, src : JsonObject) = private val reHeadSharp = """\A#""".toRegex()
if(parser.linkHelper.isMisskey) {
val name = src.stringOrThrow("tag") private val reUserTagUrl = """/@[^/]+/tagged/""".toRegex()
val url = "https://${parser.apiHost}/tags/${Uri.encode(name)}"
TootTag( fun parse(parser: TootParser, src: JsonObject) =
if (parser.linkHelper.isMisskey) {
val name = src.stringOrThrow("tag").replaceFirst(reHeadSharp, "")
TootTag(
name = name, name = name,
url = url, url = "https://${parser.apiHost}/tags/${Uri.encode(name)}"
history = null
) )
} else { } else {
TootTag( // /api/v1/accounts/$id/featured_tags の場合、
name = src.stringOrThrow("name"), // name部分は先頭に#がついているかもしれない。必要なら除去するべき。
url = src.string("url"), // url部分はユーザのタグTLになる。 https://nightly.fedibird.com/@noellabo/tagged/fedibird
// STはメニューから選べるので、URLは普通のタグURLの方が望ましい https://nightly.fedibird.com/tags/fedibird
TootTag(
name = src.stringOrThrow("name").replaceFirst(reHeadSharp, ""),
url = src.string("url")?.replaceFirst(reUserTagUrl, "/tags/"),
history = parseHistories(src.jsonArray("history")) history = parseHistories(src.jsonArray("history"))
) )
} }
private fun parseHistories(src : JsonArray?) : ArrayList<History>? { private fun parseHistories(src: JsonArray?): ArrayList<History>? {
src ?: return null src ?: return null
val dst = ArrayList<History>() val dst = ArrayList<History>()
src.objectList().forEach { src.objectList().forEach {
try { try {
dst.add(History(it)) dst.add(History(it))
} catch(ex : Throwable) { } catch (ex: Throwable) {
log.e(ex, "parseHistories failed.") log.e(ex, "parseHistories failed.")
} }
} }
return dst return dst
} }
fun parseListOrNull(parser : TootParser, array : JsonArray?) = fun parseListOrNull(parser: TootParser, array: JsonArray?) =
array?.mapNotNull { src-> array?.mapNotNull { src ->
try { try {
when(src) { when (src) {
null -> null null -> null
"" -> null "" -> null
is String -> TootTag(name = src) is String -> TootTag(name = src)
is JsonObject -> parse(parser, src) is JsonObject -> parse(parser, src)
else->null else -> null
} }
}catch(ex:Throwable){ } catch (ex: Throwable) {
log.e(ex,"parseListOrNull failed.") log.e(ex, "parseListOrNull failed.")
null null
} }
}?.notEmpty() }?.notEmpty()
fun parseList(parser : TootParser, array : JsonArray?) = fun parseList(parser: TootParser, array: JsonArray?) =
parseListOrNull(parser,array) ?: emptyList() parseListOrNull(parser, array) ?: emptyList()
private const val w = TootAccount.reRubyWord
private const val a = TootAccount.reRubyAlpha private const val w = TootAccount.reRubyWord
private const val s = "_\\u00B7\\u200c" // separators private const val a = TootAccount.reRubyAlpha
private const val s = "_\\u00B7\\u200c" // separators
private fun generateMastodonTagPattern() : Pattern {
val reMastodonTagName = """([_$w][$s$w]*[$s$a][$s$w]*[_$w])|([_$w]*[$a][_$w]*)""" private fun generateMastodonTagPattern(): Pattern {
return """(?:^|[^\w/)])#($reMastodonTagName)""".asciiPattern() val reMastodonTagName = """([_$w][$s$w]*[$s$a][$s$w]*[_$w])|([_$w]*[$a][_$w]*)"""
} return """(?:^|[^\w/)])#($reMastodonTagName)""".asciiPattern()
}
private val reMastodonTag = generateMastodonTagPattern()
private val reMastodonTag = generateMastodonTagPattern()
// https://medium.com/@alice/some-article#.abcdef123 => タグにならない
// https://en.wikipedia.org/wiki/Ghostbusters_(song)#Lawsuit => タグにならない // https://medium.com/@alice/some-article#.abcdef123 => タグにならない
// # => # // https://en.wikipedia.org/wiki/Ghostbusters_(song)#Lawsuit => タグにならない
// #3d => #3d // # => #
// #l33ts35k => #l33ts35k // #3d => #3d
// #world2016 => #world2016 // #l33ts35k => #l33ts35k
// #_test => #_test // #world2016 => #world2016
// #test_ => #test_ // #_test => #_test
// #one·two·three· => 末尾の・はタグに含まれない。#one·two·three までがハッシュタグになる。 // #test_ => #test_
// #0123456' => 数字だけのハッシュタグはタグとして認識されない // #one·two·three· => 末尾の・はタグに含まれない。#one·two·three までがハッシュタグになる
// #000_000 => 認識される。orの前半分が機能してるらしい // #0123456' => 数字だけのハッシュタグはタグとして認識されない。
// // #000_000 => 認識される。orの前半分が機能してるらしい
//
// タグに使えない文字
// 入力補完用なのでやや緩め // タグに使えない文字
private val reCharsNotTagMastodon = """[^$s$w$a]""".asciiPattern() // 入力補完用なのでやや緩め
private val reCharsNotTagMisskey = """[\s.,!?'${'"'}:/\[\]【】]""".asciiPattern() private val reCharsNotTagMastodon = """[^$s$w$a]""".asciiPattern()
private val reCharsNotTagMisskey = """[\s.,!?'${'"'}:/\[\]【】]""".asciiPattern()
// find hashtags in content text(raw)
// returns null if hashtags not found, or ArrayList of String (tag without #) // find hashtags in content text(raw)
fun findHashtags(src : String, isMisskey : Boolean) : ArrayList<String>? = // returns null if hashtags not found, or ArrayList of String (tag without #)
if(isMisskey) { fun findHashtags(src: String, isMisskey: Boolean): ArrayList<String>? =
MisskeyMarkdownDecoder.findHashtags(src) if (isMisskey) {
} else { MisskeyMarkdownDecoder.findHashtags(src)
var result : ArrayList<String>? = null } else {
val m = reMastodonTag.matcher(src) var result: ArrayList<String>? = null
while(m.find()) { val m = reMastodonTag.matcher(src)
if(result == null) result = ArrayList() while (m.find()) {
result.add(m.groupEx(1) !!) if (result == null) result = ArrayList()
} result.add(m.groupEx(1)!!)
result }
} result
}
fun isValid(src : String, isMisskey : Boolean) =
if(isMisskey) { fun isValid(src: String, isMisskey: Boolean) =
! reCharsNotTagMisskey.matcher(src).find() if (isMisskey) {
} else { !reCharsNotTagMisskey.matcher(src).find()
! reCharsNotTagMastodon.matcher(src).find() } else {
} !reCharsNotTagMastodon.matcher(src).find()
}
// https://mastodon.juggler.jp/tags/%E3%83%8F%E3%83%83%E3%82%B7%E3%83%A5%E3%82%BF%E3%82%B0
// あるサービスは /tags/... でなく /tag/... を使う // https://mastodon.juggler.jp/tags/%E3%83%8F%E3%83%83%E3%82%B7%E3%83%A5%E3%82%BF%E3%82%B0
private val reUrlHashTag = """\Ahttps://([^/]+)/tags?/([^?#・\s\-+.,:;/]+)(?:\z|[?#])""" // あるサービスは /tags/... でなく /tag/... を使う
.asciiPattern() private val reUrlHashTag = """\Ahttps://([^/]+)/tags?/([^?#・\s\-+.,:;/]+)(?:\z|[?#])"""
.asciiPattern()
// https://pixelfed.tokyo/discover/tags/SubwayTooter?src=hash
private val reUrlHashTagPixelfed = // https://pixelfed.tokyo/discover/tags/SubwayTooter?src=hash
"""\Ahttps://([^/]+)/discover/tags/([^?#・\s\-+.,:;/]+)(?:\z|[?#])""" private val reUrlHashTagPixelfed =
.asciiPattern() """\Ahttps://([^/]+)/discover/tags/([^?#・\s\-+.,:;/]+)(?:\z|[?#])"""
.asciiPattern()
// returns null or pair of ( decoded tag without sharp, host)
fun String.findHashtagFromUrl() : Pair<String, String>? { // returns null or pair of ( decoded tag without sharp, host)
var m = reUrlHashTag.matcher(this) fun String.findHashtagFromUrl(): Pair<String, String>? {
if(m.find()) { var m = reUrlHashTag.matcher(this)
val host = m.groupEx(1) !! if (m.find()) {
val tag = m.groupEx(2) !!.decodePercent() val host = m.groupEx(1)!!
return Pair(tag, host) val tag = m.groupEx(2)!!.decodePercent()
} return Pair(tag, host)
}
m = reUrlHashTagPixelfed.matcher(this)
if(m.find()) { m = reUrlHashTagPixelfed.matcher(this)
val host = m.groupEx(1) !! if (m.find()) {
val tag = m.groupEx(2) !!.decodePercent() val host = m.groupEx(1)!!
return Pair(tag, host) val tag = m.groupEx(2)!!.decodePercent()
} return Pair(tag, host)
}
return null
} return null
}
} }
} }

View File

@ -150,11 +150,11 @@ class PushSubscriptionHelper(
} }
} }
private fun updateSubscriptionMisskey(client: TootApiClient): TootApiResult? { private suspend fun updateSubscriptionMisskey(client: TootApiClient): TootApiResult? {
// 現在の購読状態を取得できないので、毎回購読の更新を行う // 現在の購読状態を取得できないので、毎回購読の更新を行う
// FCMのデバイスIDを取得 // FCMのデバイスIDを取得
val device_id = PollingWorker.getDeviceId(context) val device_id = PollingWorker.getFirebaseMessagingToken(context)
?: return TootApiResult(error = context.getString(R.string.missing_fcm_device_id)) ?: return TootApiResult(error = context.getString(R.string.missing_fcm_device_id))
// アクセストークン // アクセストークン
@ -221,7 +221,7 @@ class PushSubscriptionHelper(
} }
} }
private fun updateSubscriptionMastodon(client: TootApiClient, force: Boolean): TootApiResult? { private suspend fun updateSubscriptionMastodon(client: TootApiClient, force: Boolean): TootApiResult? {
// 現在の購読状態を取得 // 現在の購読状態を取得
// https://github.com/tootsuite/mastodon/pull/7471 // https://github.com/tootsuite/mastodon/pull/7471
@ -293,7 +293,7 @@ class PushSubscriptionHelper(
} }
// FCMのデバイスIDを取得 // FCMのデバイスIDを取得
val device_id = PollingWorker.getDeviceId(context) val device_id = PollingWorker.getFirebaseMessagingToken(context)
?: return TootApiResult(error = context.getString(R.string.missing_fcm_device_id)) ?: return TootApiResult(error = context.getString(R.string.missing_fcm_device_id))
// アクセストークン // アクセストークン
@ -508,7 +508,7 @@ class PushSubscriptionHelper(
} }
} }
fun updateSubscription(client: TootApiClient, force: Boolean = false): TootApiResult? = suspend fun updateSubscription(client: TootApiClient, force: Boolean = false): TootApiResult? =
try { try {
when { when {
isRecentlyChecked() -> isRecentlyChecked() ->

View File

@ -1,6 +1,5 @@
<?xml version="1.0" encoding="utf-8"?> <?xml version="1.0" encoding="utf-8"?>
<LinearLayout <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools" xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="wrap_content" android:layout_height="wrap_content"
@ -15,25 +14,23 @@
android:id="@+id/tvMoved" android:id="@+id/tvMoved"
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:layout_marginBottom="3dp"
android:layout_marginEnd="12dp"
android:layout_marginStart="12dp" android:layout_marginStart="12dp"
android:layout_marginTop="6dp" android:layout_marginTop="6dp"
android:layout_marginEnd="12dp"
android:layout_marginBottom="3dp"
android:drawablePadding="4dp" android:drawablePadding="4dp"
android:gravity="center" android:gravity="center"
tools:text="aaa\@bbb さんは引っ越しました" tools:text="aaa\@bbb さんは引っ越しました" />
/>
<LinearLayout <LinearLayout
android:id="@+id/llMoved" android:id="@+id/llMoved"
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:layout_marginEnd="12dp"
android:layout_marginStart="12dp" android:layout_marginStart="12dp"
android:layout_marginEnd="12dp"
android:background="@drawable/btn_bg_transparent_round6dp" android:background="@drawable/btn_bg_transparent_round6dp"
android:gravity="center_vertical" android:gravity="center_vertical"
android:orientation="horizontal" android:orientation="horizontal">
>
<jp.juggler.subwaytooter.view.MyNetworkImageView <jp.juggler.subwaytooter.view.MyNetworkImageView
android:id="@+id/ivMoved" android:id="@+id/ivMoved"
@ -49,33 +46,29 @@
android:layout_width="0dp" android:layout_width="0dp"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:layout_weight="1" android:layout_weight="1"
android:orientation="vertical" android:orientation="vertical">
>
<TextView <TextView
android:id="@+id/tvMovedName" android:id="@+id/tvMovedName"
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="wrap_content" android:layout_height="wrap_content"
tools:text="Follower Name" tools:text="Follower Name" />
/>
<TextView <TextView
android:id="@+id/tvMovedAcct" android:id="@+id/tvMovedAcct"
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:paddingEnd="4dp"
android:paddingStart="4dp" android:paddingStart="4dp"
android:paddingEnd="4dp"
android:textSize="12sp" android:textSize="12sp"
tools:text="aaaaaaaaaaaaaaaa" tools:text="aaaaaaaaaaaaaaaa" />
/>
</LinearLayout> </LinearLayout>
<FrameLayout <FrameLayout
android:layout_width="40dp" android:layout_width="40dp"
android:layout_height="40dp" android:layout_height="40dp"
android:layout_marginStart="4dp" android:layout_marginStart="4dp">
>
<ImageButton <ImageButton
android:id="@+id/btnMoved" android:id="@+id/btnMoved"
@ -84,8 +77,7 @@
android:background="@drawable/btn_bg_transparent_round6dp" android:background="@drawable/btn_bg_transparent_round6dp"
android:contentDescription="@string/follow" android:contentDescription="@string/follow"
android:scaleType="center" android:scaleType="center"
tools:src="@drawable/ic_follow_plus" tools:src="@drawable/ic_follow_plus" />
/>
<ImageView <ImageView
android:id="@+id/ivMovedBy" android:id="@+id/ivMovedBy"
@ -93,8 +85,7 @@
android:layout_height="match_parent" android:layout_height="match_parent"
android:scaleType="center" android:scaleType="center"
android:src="@drawable/ic_followed_by" android:src="@drawable/ic_followed_by"
tools:ignore="ContentDescription" tools:ignore="ContentDescription" />
/>
</FrameLayout> </FrameLayout>
</LinearLayout> </LinearLayout>
@ -104,20 +95,17 @@
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:gravity="end" android:gravity="end"
android:textSize="12sp" android:textSize="12sp"
tools:text="xxxx-xx-xx xx:xx:xx" tools:text="xxxx-xx-xx xx:xx:xx" />
/>
<FrameLayout <FrameLayout
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="wrap_content" android:layout_height="wrap_content">
>
<jp.juggler.subwaytooter.view.MyNetworkImageView <jp.juggler.subwaytooter.view.MyNetworkImageView
android:id="@+id/ivBackground" android:id="@+id/ivBackground"
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="match_parent" android:layout_height="match_parent"
android:scaleType="centerCrop" android:scaleType="centerCrop" />
/>
<LinearLayout <LinearLayout
android:id="@+id/llProfile" android:id="@+id/llProfile"
@ -125,16 +113,14 @@
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:gravity="center_horizontal" android:gravity="center_horizontal"
android:orientation="vertical" android:orientation="vertical"
android:padding="12dp" android:padding="12dp">
>
<jp.juggler.subwaytooter.view.MyNetworkImageView <jp.juggler.subwaytooter.view.MyNetworkImageView
android:id="@+id/ivAvatar" android:id="@+id/ivAvatar"
android:layout_width="128dp" android:layout_width="128dp"
android:layout_height="128dp" android:layout_height="128dp"
android:layout_marginTop="20dp" android:layout_marginTop="20dp"
android:background="@drawable/btn_bg_transparent_round6dp" android:background="@drawable/btn_bg_transparent_round6dp" />
/>
<TextView <TextView
android:id="@+id/tvDisplayName" android:id="@+id/tvDisplayName"
@ -143,8 +129,7 @@
android:layout_marginTop="8dp" android:layout_marginTop="8dp"
android:gravity="center" android:gravity="center"
android:textSize="20sp" android:textSize="20sp"
tools:text="ディスプレイネームディスプレイネームディスプレイネーム" tools:text="ディスプレイネームディスプレイネームディスプレイネーム" />
/>
<TextView <TextView
android:id="@+id/tvAcct" android:id="@+id/tvAcct"
@ -154,32 +139,28 @@
android:gravity="center" android:gravity="center"
android:textColor="?attr/colorLink" android:textColor="?attr/colorLink"
tools:text="\@fugahogehogera\@jugemujyugemugokounosurikire.jp" tools:text="\@fugahogehogera\@jugemujyugemugokounosurikire.jp" />
/>
<jp.juggler.subwaytooter.view.MyTextView <jp.juggler.subwaytooter.view.MyTextView
android:id="@+id/tvNote" android:id="@+id/tvNote"
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:gravity="center_horizontal" android:gravity="center_horizontal"
tools:text="説明文 説明文 説明文 説明文 説明文 説明文 説明文 説明文 説明文 説明文 説明文 説明文 説明文 説明文 説明文 説明文 説明文 説明文 説明文 説明文 説明文 " tools:text="説明文 説明文 説明文 説明文 説明文 説明文 説明文 説明文 説明文 説明文 説明文 説明文 説明文 説明文 説明文 説明文 説明文 説明文 説明文 説明文 説明文 " />
/>
<jp.juggler.subwaytooter.view.MyTextView <jp.juggler.subwaytooter.view.MyTextView
android:id="@+id/tvMisskeyExtra" android:id="@+id/tvMisskeyExtra"
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:gravity="center_horizontal" android:gravity="center_horizontal"
tools:text="説明文 説明文 説明文 説明文 説明文 説明文 説明文 説明文 説明文 説明文 説明文 説明文 説明文 説明文 説明文 説明文 説明文 説明文 説明文 説明文 説明文 " tools:text="説明文 説明文 説明文 説明文 説明文 説明文 説明文 説明文 説明文 説明文 説明文 説明文 説明文 説明文 説明文 説明文 説明文 説明文 説明文 説明文 説明文 " />
/>
</LinearLayout> </LinearLayout>
<FrameLayout <FrameLayout
android:layout_width="40dp" android:layout_width="40dp"
android:layout_height="40dp" android:layout_height="40dp"
android:layout_marginStart="12dp" android:layout_marginStart="12dp"
android:layout_marginTop="12dp" android:layout_marginTop="12dp">
>
<ImageButton <ImageButton
android:id="@+id/btnFollow" android:id="@+id/btnFollow"
@ -188,8 +169,7 @@
android:background="@drawable/btn_bg_transparent_round6dp" android:background="@drawable/btn_bg_transparent_round6dp"
android:contentDescription="@string/follow" android:contentDescription="@string/follow"
android:scaleType="center" android:scaleType="center"
tools:src="@drawable/ic_follow_plus" tools:src="@drawable/ic_follow_plus" />
/>
<ImageView <ImageView
android:id="@+id/ivFollowedBy" android:id="@+id/ivFollowedBy"
@ -197,61 +177,64 @@
android:layout_height="match_parent" android:layout_height="match_parent"
android:scaleType="center" android:scaleType="center"
android:src="@drawable/ic_followed_by" android:src="@drawable/ic_followed_by"
tools:ignore="ContentDescription" tools:ignore="ContentDescription" />
/>
</FrameLayout> </FrameLayout>
</FrameLayout> </FrameLayout>
<LinearLayout <LinearLayout
android:id="@+id/llFields"
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:layout_marginTop="3dp" android:layout_marginTop="3dp"
android:id="@+id/llFields" android:orientation="vertical" />
android:orientation="vertical"
/> <TextView
android:id="@+id/tvFeaturedTags"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginTop="3dp" />
<TextView <TextView
android:id="@+id/tvLastStatusAt" android:id="@+id/tvLastStatusAt"
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:layout_marginTop="3dp"
android:gravity="center" android:gravity="center"
android:textSize="12sp" android:textSize="12sp"
tools:text="xxxx-xx-xx xx:xx:xx" tools:text="xxxx-xx-xx xx:xx:xx" />
/>
<TextView <TextView
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:layout_marginTop="8dp" android:layout_marginTop="8dp"
android:gravity="start" android:gravity="start"
android:text="@string/personal_notes" android:text="@string/personal_notes" />
/>
<LinearLayout <LinearLayout
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:gravity="start|top" android:gravity="start|top"
android:orientation="horizontal" android:orientation="horizontal">
>
<TextView <TextView
android:id="@+id/tvPersonalNotes" android:id="@+id/tvPersonalNotes"
android:layout_width="0dp" android:layout_width="0dp"
android:layout_weight="1"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:layout_weight="1"
android:gravity="start" android:gravity="start"
android:padding="12dp" android:padding="12dp"
android:text="@string/personal_notes" android:text="@string/personal_notes" />
/>
<ImageButton <ImageButton
android:id="@+id/btnPersonalNotesEdit"
android:layout_width="40dp" android:layout_width="40dp"
android:layout_height="40dp" android:layout_height="40dp"
android:background="@drawable/btn_bg_transparent_round6dp"
android:layout_marginStart="4dp" android:layout_marginStart="4dp"
android:id="@+id/btnPersonalNotesEdit" android:background="@drawable/btn_bg_transparent_round6dp"
android:src="@drawable/ic_edit"
android:contentDescription="@string/edit" android:contentDescription="@string/edit"
/> android:src="@drawable/ic_edit" />
</LinearLayout> </LinearLayout>
<TextView <TextView
@ -262,40 +245,35 @@
android:background="@drawable/btn_bg_transparent_round6dp" android:background="@drawable/btn_bg_transparent_round6dp"
android:gravity="center" android:gravity="center"
android:padding="12dp" android:padding="12dp"
android:text="@string/remote_profile_warning" android:text="@string/remote_profile_warning" />
/>
<LinearLayout <LinearLayout
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:layout_marginTop="3dp" android:layout_marginTop="3dp"
android:gravity="center" android:gravity="center"
android:orientation="horizontal" android:orientation="horizontal">
>
<Button <Button
android:id="@+id/btnStatusCount" android:id="@+id/btnStatusCount"
android:layout_width="wrap_content" android:layout_width="wrap_content"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:background="@drawable/btn_bg_transparent_round6dp" android:background="@drawable/btn_bg_transparent_round6dp"
tools:text="statuses\n124" tools:text="statuses\n124" />
/>
<Button <Button
android:id="@+id/btnFollowing" android:id="@+id/btnFollowing"
android:layout_width="wrap_content" android:layout_width="wrap_content"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:background="@drawable/btn_bg_transparent_round6dp" android:background="@drawable/btn_bg_transparent_round6dp"
tools:text="following\n9999" tools:text="following\n9999" />
/>
<Button <Button
android:id="@+id/btnFollowers" android:id="@+id/btnFollowers"
android:layout_width="wrap_content" android:layout_width="wrap_content"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:background="@drawable/btn_bg_transparent_round6dp" android:background="@drawable/btn_bg_transparent_round6dp"
tools:text="followers\n9999" tools:text="followers\n9999" />
/>
<ImageButton <ImageButton
android:id="@+id/btnMore" android:id="@+id/btnMore"
@ -304,10 +282,9 @@
android:background="@drawable/btn_bg_transparent_round6dp" android:background="@drawable/btn_bg_transparent_round6dp"
android:contentDescription="@string/more" android:contentDescription="@string/more"
android:minWidth="48dp" android:minWidth="48dp"
android:paddingEnd="4dp"
android:paddingStart="4dp" android:paddingStart="4dp"
android:src="@drawable/ic_more" android:paddingEnd="4dp"
/> android:src="@drawable/ic_more" />
</LinearLayout> </LinearLayout>

View File

@ -634,7 +634,7 @@
<string name="always_show_application">Mostra (mitjançant) el nom de l\'aplicació, si és possible</string> <string name="always_show_application">Mostra (mitjançant) el nom de l\'aplicació, si és possible</string>
<string name="force_gap_when_refresh">Forçar que s\'afegeixi una separació en refrescar la part superior</string> <string name="force_gap_when_refresh">Forçar que s\'afegeixi una separació en refrescar la part superior</string>
<string name="avatar_icon_size">Mida d\'icona d\'avatar (Unitat:dp. per defecte:48. cal reiniciar aplicació)</string> <string name="avatar_icon_size">Mida d\'icona d\'avatar (Unitat:dp. per defecte:48. cal reiniciar aplicació)</string>
<string name="avatar_icon_round_ratio">Quocient d\'arrodoniment de la icona d\'avatar (Unitat:%. per defrecte:33. cal reiniciar aplicació)</string> <string name="avatar_icon_round_ratio">Quocient d\'arrodoniment de la icona d\'avatar (Unitat:%%. per defrecte:33. cal reiniciar aplicació)</string>
<string name="avatar_icon_dont_round">No arrodonir els angles de la icona d\'avatar (cal reiniciar l\'aplicació)</string> <string name="avatar_icon_dont_round">No arrodonir els angles de la icona d\'avatar (cal reiniciar l\'aplicació)</string>
<string name="share_view_pool">Comparteix la visualització entre pissarres</string> <string name="share_view_pool">Comparteix la visualització entre pissarres</string>
<string name="rename">Rebateja…</string> <string name="rename">Rebateja…</string>
@ -821,7 +821,7 @@
<string name="conversation_to">A:</string> <string name="conversation_to">A:</string>
<string name="use_quote_toot">Fer ús de \"Nota citada\"</string> <string name="use_quote_toot">Fer ús de \"Nota citada\"</string>
<string name="mute_application_confirm">Vols silenciar l\'aplicació \"%1$s\"\?</string> <string name="mute_application_confirm">Vols silenciar l\'aplicació \"%1$s\"\?</string>
<string name="boost_button_alpha">Augmenta l\'opacitat del botó de difusió (Unitat:%. cal reiniciar aplicació. també afecta al text de contingut alfa.)</string> <string name="boost_button_alpha">Augmenta l\'opacitat del botó de difusió (Unitat:%%. cal reiniciar aplicació. també afecta al text de contingut alfa.)</string>
<string name="toot_background_color">Color de fons dels brams</string> <string name="toot_background_color">Color de fons dels brams</string>
<string name="column_color_default">Color per defecte de les pissarres</string> <string name="column_color_default">Color per defecte de les pissarres</string>
<string name="header_background_color">Color de fons de la capçalera</string> <string name="header_background_color">Color de fons de la capçalera</string>

View File

@ -1,5 +1,5 @@
<?xml version="1.0" encoding="utf-8"?> <?xml version="1.0" encoding="utf-8"?>
<resources> <resources xmlns:tools="http://schemas.android.com/tools">
<string name="app_name">Subway Tooter</string> <string name="app_name">Subway Tooter</string>
<string name="action_settings">Einstellungen</string> <string name="action_settings">Einstellungen</string>
<string name="account_add">Konto hinzufügen</string> <string name="account_add">Konto hinzufügen</string>
@ -321,7 +321,7 @@
<string name="read_gap_head">Lese Kopfspalt</string> <string name="read_gap_head">Lese Kopfspalt</string>
<string name="remote_only">Nur entfernt</string> <string name="remote_only">Nur entfernt</string>
<string name="featured">Promotet</string> <string name="featured">Promotet</string>
<string name="announcements_period2">Ereignis-Zeitraum: %1$s...%2$s</string> <string name="announcements_period2">Ereignis-Zeitraum: %1$s%2$s</string>
<string name="announcements_period1">Ereignis-Zeitraum: %1$s</string> <string name="announcements_period1">Ereignis-Zeitraum: %1$s</string>
<string name="boost_with_visibility">Sichtbar boosten</string> <string name="boost_with_visibility">Sichtbar boosten</string>
<string name="hide_totals">Verberge die Summe bis zum Ablauf</string> <string name="hide_totals">Verberge die Summe bis zum Ablauf</string>
@ -424,7 +424,7 @@
<string name="notification_type_mention">Nennung</string> <string name="notification_type_mention">Nennung</string>
<string name="share_view_pool">Teile Anzeigenpool zwischen den Spalten</string> <string name="share_view_pool">Teile Anzeigenpool zwischen den Spalten</string>
<string name="allow_column_duplication">Erlaube Verdoppelung von Spalten</string> <string name="allow_column_duplication">Erlaube Verdoppelung von Spalten</string>
<string name="avatar_icon_round_ratio">Abrundungsfaktor des Avatarbildes (Einheit: %. Standard: 33. App-Neustart erforderlich)</string> <string name="avatar_icon_round_ratio">Abrundungsfaktor des Avatarbildes (Einheit: %%. Standard: 33. App-Neustart erforderlich)</string>
<string name="always_show_application">Zeige per App-Name, falls möglich</string> <string name="always_show_application">Zeige per App-Name, falls möglich</string>
<string name="domain_block_from_local">Kann Domänen auf deinem Server nicht blockieren.</string> <string name="domain_block_from_local">Kann Domänen auf deinem Server nicht blockieren.</string>
<string name="domain_block_from_pseudo">Kann Domäne nicht vom Pseudokonto aus blockieren.</string> <string name="domain_block_from_pseudo">Kann Domäne nicht vom Pseudokonto aus blockieren.</string>
@ -569,11 +569,11 @@
<string name="endorse_set">In deinem Profil promoten</string> <string name="endorse_set">In deinem Profil promoten</string>
<string name="already_voted">Bereits abgestimmt.</string> <string name="already_voted">Bereits abgestimmt.</string>
<string name="toot_background_color">Hintergrundfarbe des Toots</string> <string name="toot_background_color">Hintergrundfarbe des Toots</string>
<string name="boost_button_alpha">Deckkraft des Boost-Buttons (Einheit: %. App-Neustart erforderlich; wird auch von der Transparenz des Inhaltstextes beeinflusst)</string> <string name="boost_button_alpha">Deckkraft des Boost-Buttons (Einheit: %%. App-Neustart erforderlich; wird auch von der Transparenz des Inhaltstextes beeinflusst)</string>
<string name="mute_application_confirm">App \"%1$s\" stummschalten\?</string> <string name="mute_application_confirm">App \"%1$s\" stummschalten\?</string>
<string name="use_quote_toot">Benutze “Toot zitieren”. (Misskey oder individiualisierter Mastodonserver)</string> <string name="use_quote_toot">Benutze “Toot zitieren”. (Misskey oder individiualisierter Mastodonserver)</string>
<string name="conversation_to">An:</string> <string name="conversation_to">An:</string>
<string name="participants_and_more">...und weitere</string> <string name="participants_and_more">und weitere</string>
<string name="participants">Teilnehmer:</string> <string name="participants">Teilnehmer:</string>
<string name="show_conversation">Unterhaltung anzeigen</string> <string name="show_conversation">Unterhaltung anzeigen</string>
<string name="around_toot_limitation_warning">Das Feature \"Timeline um die angegebene Zeit herum\" ist auf Mastodonserver ab Version 2.6.0 beschränkt. Eine etwas neuere Timeline kann nicht abgerufen werden.</string> <string name="around_toot_limitation_warning">Das Feature \"Timeline um die angegebene Zeit herum\" ist auf Mastodonserver ab Version 2.6.0 beschränkt. Eine etwas neuere Timeline kann nicht abgerufen werden.</string>
@ -982,7 +982,7 @@
<string name="show_quick_toot_bar">Zeige „Schnell-Toot“-Leiste (App-Neustart erforderlich)</string> <string name="show_quick_toot_bar">Zeige „Schnell-Toot“-Leiste (App-Neustart erforderlich)</string>
<string name="timeline_font_size">Schriftgröße der Timeline <string name="timeline_font_size">Schriftgröße der Timeline
\n(Einheit: Skalierbare Pixel / SP. Leer lassen, um Standard zu benutzen. App-Neustart erforderlich) \n(Einheit: Skalierbare Pixel / SP. Leer lassen, um Standard zu benutzen. App-Neustart erforderlich)
\n... \n
\n…</string> \n…</string>
<string name="notification_sound">Benachrichtungston</string> <string name="notification_sound">Benachrichtungston</string>
<string name="open_local_timeline_for">Timeline von \"%1$s\" öffnen</string> <string name="open_local_timeline_for">Timeline von \"%1$s\" öffnen</string>
@ -1007,7 +1007,7 @@
<string name="blocked_domains">Blockierte Domains</string> <string name="blocked_domains">Blockierte Domains</string>
<string name="url_omitted">(URL ausgelassen)</string> <string name="url_omitted">(URL ausgelassen)</string>
<string name="enable_speech">Aktiviert Sprachausgabe</string> <string name="enable_speech">Aktiviert Sprachausgabe</string>
<string name="account_change_failed_old_draft_has_no_in_reply_to_url">Konnte Konto nicht wechseln. Alte Entwurfsdaten besitzen kein in_reply_to_url, kann für gewählten Server nicht in in_reply_to_url umgewandelt werden.</string> <string name="account_change_failed_old_draft_has_no_in_reply_to_url" tools:ignore="Typos">Konnte Konto nicht wechseln. Alte Entwurfsdaten besitzen kein in_reply_to_url, kann für gewählten Server nicht in in_reply_to_url umgewandelt werden.</string>
<string name="toot_button_default_account">Standardkonto, wenn der „Toot“-Button gedrückt wird</string> <string name="toot_button_default_account">Standardkonto, wenn der „Toot“-Button gedrückt wird</string>
<string name="notification_on_off_desc">Es gibt auch eine Konteneinstellung, um Benachrichtigungen ein- und auszuschalten.</string> <string name="notification_on_off_desc">Es gibt auch eine Konteneinstellung, um Benachrichtigungen ein- und auszuschalten.</string>
<string name="behavior">Verhalten</string> <string name="behavior">Verhalten</string>

View File

@ -602,7 +602,7 @@
<string name="always_show_application">Afficher (via) le nom de l\'application si possible</string> <string name="always_show_application">Afficher (via) le nom de l\'application si possible</string>
<string name="force_gap_when_refresh">Forcer lajout d\'un espace lors du rafraîchissement du dessus</string> <string name="force_gap_when_refresh">Forcer lajout d\'un espace lors du rafraîchissement du dessus</string>
<string name="avatar_icon_size">Taille de licône de lavatar (Unité:dp. par défaut:48. Redémarrage de lapp requis)</string> <string name="avatar_icon_size">Taille de licône de lavatar (Unité:dp. par défaut:48. Redémarrage de lapp requis)</string>
<string name="avatar_icon_round_ratio">Ratio de larrondi de licône de lavatar (Unité:%. défaut:33. redémarrage de l\'application requis)</string> <string name="avatar_icon_round_ratio">Ratio de larrondi de licône de lavatar (Unité:%%. défaut:33. redémarrage de l\'application requis)</string>
<string name="avatar_icon_dont_round">Ne pas arrondir les coins de lavatar (redémarrage requis)</string> <string name="avatar_icon_dont_round">Ne pas arrondir les coins de lavatar (redémarrage requis)</string>
<string name="share_view_pool">Partager le pool de vues entre les colonnes</string> <string name="share_view_pool">Partager le pool de vues entre les colonnes</string>
<string name="rename">Renommer …</string> <string name="rename">Renommer …</string>
@ -849,7 +849,7 @@
<string name="strip_icon_size">Taille de licône de la barre de colonne (Unité : dp. Défaut : 30. Redémarrage de lapplication requis)</string> <string name="strip_icon_size">Taille de licône de la barre de colonne (Unité : dp. Défaut : 30. Redémarrage de lapplication requis)</string>
<string name="show_acct_in_system_notification">Afficher le compte (au lieu du nom dutilisateur) dans les notifications système</string> <string name="show_acct_in_system_notification">Afficher le compte (au lieu du nom dutilisateur) dans les notifications système</string>
<string name="account_tl_around">Fil public autour …</string> <string name="account_tl_around">Fil public autour …</string>
<string name="boost_button_alpha">Transparence du bouton Boost (Unité:%. redémarrage de lapp nécessaire. Affecte également la transparence du contenu texte.)</string> <string name="boost_button_alpha">Transparence du bouton Boost (Unité:%%. redémarrage de lapp nécessaire. Affecte également la transparence du contenu texte.)</string>
<string name="move_notifications_quick_filter_to_column_setting">Afficher le filtre rapide des notifications dans la configuration de la colonne (redémarrage de lapp requis)</string> <string name="move_notifications_quick_filter_to_column_setting">Afficher le filtre rapide des notifications dans la configuration de la colonne (redémarrage de lapp requis)</string>
<string name="official_account">Compte officiel</string> <string name="official_account">Compte officiel</string>
<string name="releases">Sorties</string> <string name="releases">Sorties</string>

View File

@ -72,7 +72,7 @@
<string name="auto_cw_prefix">(自動CW)</string> <string name="auto_cw_prefix">(自動CW)</string>
<string name="available_mastodon_2_4_later">(マストドン2.4以降で利用可能)</string> <string name="available_mastodon_2_4_later">(マストドン2.4以降で利用可能)</string>
<string name="avatar_icon_dont_round">ユーザ画像を角丸にしない(アプリ再起動が必要)</string> <string name="avatar_icon_dont_round">ユーザ画像を角丸にしない(アプリ再起動が必要)</string>
<string name="avatar_icon_round_ratio">ユーザ画像の角丸率(単位:%。デフォルト:33。アプリ再起動が必要)</string> <string name="avatar_icon_round_ratio">ユーザ画像の角丸率(単位:%%。デフォルト:33。アプリ再起動が必要)</string>
<string name="avatar_icon_size">ユーザ画像の大きさ(単位:dp。デフォルト:48。アプリ再起動が必要)</string> <string name="avatar_icon_size">ユーザ画像の大きさ(単位:dp。デフォルト:48。アプリ再起動が必要)</string>
<string name="back_button_action">戻るボタンの動作</string> <string name="back_button_action">戻るボタンの動作</string>
<string name="back_to_column_list">戻るボタンでカラム一覧を開く</string> <string name="back_to_column_list">戻るボタンでカラム一覧を開く</string>
@ -809,7 +809,7 @@
<string name="conversation_to">送り先:</string> <string name="conversation_to">送り先:</string>
<string name="use_quote_toot">引用トゥートにする(MisskeyまたはカスタマイズされたMastodonサーバ)</string> <string name="use_quote_toot">引用トゥートにする(MisskeyまたはカスタマイズされたMastodonサーバ)</string>
<string name="mute_application_confirm">アプリ \"%1$s\" はミュートされます。よろしいですか?</string> <string name="mute_application_confirm">アプリ \"%1$s\" はミュートされます。よろしいですか?</string>
<string name="boost_button_alpha">ブーストボタンのアルファ不透明度(単位:%。アプリの再起動が必要。本文テキスト色のアルファ値の影響も受けます)</string> <string name="boost_button_alpha">ブーストボタンのアルファ不透明度(単位:%%。アプリの再起動が必要。本文テキスト色のアルファ値の影響も受けます)</string>
<string name="toot_background_color">トゥート背景色</string> <string name="toot_background_color">トゥート背景色</string>
<string name="unlisted_visibility">\'未収載\' 公開範囲</string> <string name="unlisted_visibility">\'未収載\' 公開範囲</string>
<string name="followers_visibility">\'フォロワーのみ\' 公開範囲</string> <string name="followers_visibility">\'フォロワーのみ\' 公開範囲</string>

View File

@ -611,7 +611,7 @@
<string name="always_show_application">가능하면 (경유) 앱 이름 보이기</string> <string name="always_show_application">가능하면 (경유) 앱 이름 보이기</string>
<string name="force_gap_when_refresh">위로 새로고침할 때 강제로 띄움 넣기</string> <string name="force_gap_when_refresh">위로 새로고침할 때 강제로 띄움 넣기</string>
<string name="avatar_icon_size">아바타 아이콘 크기 (단위:dp. 기본값:48. 앱 재시작 필요)</string> <string name="avatar_icon_size">아바타 아이콘 크기 (단위:dp. 기본값:48. 앱 재시작 필요)</string>
<string name="avatar_icon_round_ratio">아바타 아이콘 곡률 (Unit:%. 기본값:33. 앱 재시작 필요)</string> <string name="avatar_icon_round_ratio">아바타 아이콘 곡률 (Unit:%%. 기본값:33. 앱 재시작 필요)</string>
<string name="avatar_icon_dont_round">아바타 아이콘의 모서리를 둥글게 하지 않기 (앱 재시작 필요)</string> <string name="avatar_icon_dont_round">아바타 아이콘의 모서리를 둥글게 하지 않기 (앱 재시작 필요)</string>
<string name="share_view_pool">칼럼 사이에 뷰 풀을 공유</string> <string name="share_view_pool">칼럼 사이에 뷰 풀을 공유</string>
<string name="rename">이름 변경…</string> <string name="rename">이름 변경…</string>
@ -796,7 +796,7 @@
<string name="conversation_to">받을 이:</string> <string name="conversation_to">받을 이:</string>
<string name="use_quote_toot">\"인용 리노트\" 사용</string> <string name="use_quote_toot">\"인용 리노트\" 사용</string>
<string name="mute_application_confirm">앱 \"%1$s\"를 음소거할까요\?</string> <string name="mute_application_confirm">앱 \"%1$s\"를 음소거할까요\?</string>
<string name="boost_button_alpha">부스트 버튼 알파 불투명도 (단위:%. 앱 재시작 필요. 본문의 알파에 영향을 미침.)</string> <string name="boost_button_alpha">부스트 버튼 알파 불투명도 (단위:%%. 앱 재시작 필요. 본문의 알파에 영향을 미침.)</string>
<string name="toot_background_color">툿 배경색</string> <string name="toot_background_color">툿 배경색</string>
<string name="column_color_default">칼럼 색 기본값</string> <string name="column_color_default">칼럼 색 기본값</string>
<string name="header_background_color">헤더 배경색</string> <string name="header_background_color">헤더 배경색</string>

View File

@ -678,7 +678,7 @@
<string name="media_attachment_still_uploading">Media har ikke blitt lastet opp enda.</string> <string name="media_attachment_still_uploading">Media har ikke blitt lastet opp enda.</string>
<string name="highlight_word">Framhev nøkkelord</string> <string name="highlight_word">Framhev nøkkelord</string>
<string name="avatar_icon_size">Avatarikonstørrelse (enhet:dp. Forvalg:48. Programomstart kreves)</string> <string name="avatar_icon_size">Avatarikonstørrelse (enhet:dp. Forvalg:48. Programomstart kreves)</string>
<string name="avatar_icon_round_ratio">Avatarikonstørrelseforhold (enhet:%. Forvalg:33. Programomstart kreves)</string> <string name="avatar_icon_round_ratio">Avatarikonstørrelseforhold (enhet:%%. Forvalg:33. Programomstart kreves)</string>
<string name="avatar_icon_dont_round">Ikke avrund avatarikonets hjørner (programomstart kreves)</string> <string name="avatar_icon_dont_round">Ikke avrund avatarikonets hjørner (programomstart kreves)</string>
<string name="allow_column_duplication">Tillat duplisering av kolonner</string> <string name="allow_column_duplication">Tillat duplisering av kolonner</string>
<string name="system_notification_not_related">Ikke valgt når systemmerknad trykkes</string> <string name="system_notification_not_related">Ikke valgt når systemmerknad trykkes</string>

View File

@ -621,7 +621,7 @@
<string name="always_show_application">Show (via) application name if possible</string> <string name="always_show_application">Show (via) application name if possible</string>
<string name="force_gap_when_refresh">Force adding gap when refreshing top</string> <string name="force_gap_when_refresh">Force adding gap when refreshing top</string>
<string name="avatar_icon_size">Avatar icon size (Unit:dp. default:48. app restart required)</string> <string name="avatar_icon_size">Avatar icon size (Unit:dp. default:48. app restart required)</string>
<string name="avatar_icon_round_ratio">Avatar icon round ratio (Unit:%. default:33. app restart required)</string> <string name="avatar_icon_round_ratio">Avatar icon round ratio (Unit:%%. default:33. app restart required)</string>
<string name="avatar_icon_dont_round">Don\'t round corner of avatar icon (app restart required)</string> <string name="avatar_icon_dont_round">Don\'t round corner of avatar icon (app restart required)</string>
<string name="share_view_pool">Share view pool between columns</string> <string name="share_view_pool">Share view pool between columns</string>
<string name="rename">Rename…</string> <string name="rename">Rename…</string>
@ -815,7 +815,7 @@
<string name="conversation_to">To:</string> <string name="conversation_to">To:</string>
<string name="use_quote_toot">Use \"Quote Toot\". (Misskey or some customized Mastodon server)</string> <string name="use_quote_toot">Use \"Quote Toot\". (Misskey or some customized Mastodon server)</string>
<string name="mute_application_confirm">Mute the app \"%1$s\"?</string> <string name="mute_application_confirm">Mute the app \"%1$s\"?</string>
<string name="boost_button_alpha">Boost button alpha opacity (Unit:%. app restart required. also affected of content text alpha.)</string> <string name="boost_button_alpha">Boost button alpha opacity (Unit:%%. app restart required. also affected of content text alpha.)</string>
<string name="toot_background_color">Toot background color</string> <string name="toot_background_color">Toot background color</string>
<string name="column_color_default">Column color default</string> <string name="column_color_default">Column color default</string>
<string name="header_background_color">Header background color</string> <string name="header_background_color">Header background color</string>

View File

@ -122,8 +122,8 @@ for my $lang ( sort keys %langs ){
# 残りの部分に%が登場したらエラー # 残りの部分に%が登場したらエラー
my $sv = $value; my $sv = $value;
$sv =~ s/(%\d+\$[\d\.]*[sdxf])//g; $sv =~ s/(%\d+\$[\d\.]*[sdxf])|%%//g;
if( $sv =~ /%/ && not $sv=~/:%/ ){ if( $sv =~ /%/ ){
$hasError =1; $hasError =1;
print "!! ($lang)$name : broken param: $sv // $value\n"; print "!! ($lang)$name : broken param: $sv // $value\n";
} }