リアクションした投稿の一覧をめいすきーでも見れるようにした
This commit is contained in:
parent
a5d16a6934
commit
bc3f56c22d
|
@ -2682,7 +2682,7 @@ class ActPost : AsyncActivity(),
|
|||
TootVisibility.DirectPrivate
|
||||
)
|
||||
|
||||
true == ti?.hasCapability(InstanceCapability.VisibilityMutual) ->
|
||||
InstanceCapability.visibilityMutual(ti) ->
|
||||
arrayOf(
|
||||
TootVisibility.WebSetting,
|
||||
TootVisibility.Public,
|
||||
|
@ -2693,7 +2693,7 @@ class ActPost : AsyncActivity(),
|
|||
TootVisibility.DirectSpecified
|
||||
)
|
||||
|
||||
true == ti?.hasCapability(InstanceCapability.VisibilityLimited) ->
|
||||
InstanceCapability.visibilityLimited(ti)->
|
||||
arrayOf(
|
||||
TootVisibility.WebSetting,
|
||||
TootVisibility.Public,
|
||||
|
|
|
@ -692,28 +692,52 @@ enum class ColumnType(
|
|||
REACTIONS(
|
||||
42,
|
||||
iconId = { R.drawable.ic_face },
|
||||
name1 = { it.getString(R.string.reactions) },
|
||||
name1 = { it.getString(R.string.reactioned_posts) },
|
||||
bAllowPseudo = false,
|
||||
bAllowMisskey = false,
|
||||
|
||||
loading = { client ->
|
||||
if (isMisskey) {
|
||||
TootApiResult("misskey has no api to list your reactions")
|
||||
getStatusList(
|
||||
client,
|
||||
ApiPath.PATH_M544_REACTIONS,
|
||||
misskeyParams = column.makeMisskeyTimelineParameter(parser),
|
||||
listParser = misskeyCustomParserFavorites
|
||||
)
|
||||
} else {
|
||||
getStatusList(client,column.makeReactionsUrl())
|
||||
}
|
||||
},
|
||||
|
||||
refresh = { client ->
|
||||
getStatusList(client,column.makeReactionsUrl())
|
||||
if (isMisskey) {
|
||||
getStatusList(
|
||||
client,
|
||||
ApiPath.PATH_M544_REACTIONS,
|
||||
misskeyParams = column.makeMisskeyTimelineParameter(parser),
|
||||
listParser = misskeyCustomParserFavorites
|
||||
)
|
||||
} else {
|
||||
getStatusList(client, column.makeReactionsUrl())
|
||||
}
|
||||
},
|
||||
|
||||
gap = { client ->
|
||||
getStatusList(
|
||||
client,
|
||||
column.makeReactionsUrl(),
|
||||
mastodonFilterByIdRange = false
|
||||
)
|
||||
if (isMisskey) {
|
||||
getStatusList(
|
||||
client,
|
||||
ApiPath.PATH_M544_REACTIONS,
|
||||
mastodonFilterByIdRange = false,
|
||||
misskeyParams = column.makeMisskeyTimelineParameter(parser),
|
||||
listParser = misskeyCustomParserFavorites
|
||||
)
|
||||
} else {
|
||||
getStatusList(
|
||||
client,
|
||||
column.makeReactionsUrl(),
|
||||
mastodonFilterByIdRange = false
|
||||
)
|
||||
}
|
||||
},
|
||||
gapDirection = gapDirectionMastodonWorkaround,
|
||||
),
|
||||
|
|
|
@ -215,7 +215,8 @@ fun ColumnViewHolder.onPageCreate(column: Column, page_idx: Int, page_count: Int
|
|||
btnSearchClear.vg(Pref.bpShowSearchClear(activity.pref))
|
||||
cbResolve.vg(column.type == ColumnType.SEARCH)
|
||||
}
|
||||
column.type == ColumnType.REACTIONS -> {
|
||||
|
||||
column.type == ColumnType.REACTIONS && column.access_info.isMastodon -> {
|
||||
llSearch.vg(true)
|
||||
|
||||
flEmoji.vg(true)
|
||||
|
|
|
@ -1,6 +1,5 @@
|
|||
package jp.juggler.subwaytooter
|
||||
|
||||
import android.app.Activity
|
||||
import android.content.Context
|
||||
import android.content.Intent
|
||||
import android.content.pm.PackageManager
|
||||
|
@ -23,9 +22,6 @@ import androidx.drawerlayout.widget.DrawerLayout
|
|||
import jp.juggler.subwaytooter.action.Action_Account
|
||||
import jp.juggler.subwaytooter.action.Action_App
|
||||
import jp.juggler.subwaytooter.action.Action_Instance
|
||||
import jp.juggler.subwaytooter.api.TootApiCallback
|
||||
import jp.juggler.subwaytooter.api.TootApiClient
|
||||
import jp.juggler.subwaytooter.api.entity.TootInstance
|
||||
import jp.juggler.subwaytooter.api.entity.TootStatus
|
||||
import jp.juggler.subwaytooter.dialog.AccountPicker
|
||||
import jp.juggler.subwaytooter.table.SavedAccount
|
||||
|
@ -269,8 +265,13 @@ class SideMenuAdapter(
|
|||
Item(icon = R.drawable.ic_bookmark, title = R.string.bookmarks) {
|
||||
Action_Account.timeline(this, defaultInsertPosition, ColumnType.BOOKMARKS)
|
||||
},
|
||||
Item(icon = R.drawable.ic_face, title = R.string.fedibird_reactions) {
|
||||
Action_Account.getReactionableAccounts(this, allowMisskey = false) { list ->
|
||||
Item(icon = R.drawable.ic_face, title = R.string.reactioned_posts) {
|
||||
Action_Account.listAccountsCanSeeMyReactions(this) { list ->
|
||||
if (list.isEmpty()) {
|
||||
showToast(false, R.string.not_available_for_current_accounts)
|
||||
return@listAccountsCanSeeMyReactions
|
||||
}
|
||||
|
||||
val columnType = ColumnType.REACTIONS
|
||||
AccountPicker.pick(
|
||||
this,
|
||||
|
|
|
@ -13,9 +13,7 @@ import jp.juggler.subwaytooter.table.UserRelation
|
|||
import jp.juggler.subwaytooter.util.LinkHelper
|
||||
import jp.juggler.subwaytooter.util.openBrowser
|
||||
import jp.juggler.util.*
|
||||
import kotlinx.coroutines.Dispatchers
|
||||
import kotlinx.coroutines.launch
|
||||
import kotlinx.coroutines.withContext
|
||||
import kotlinx.coroutines.*
|
||||
|
||||
object Action_Account {
|
||||
|
||||
|
@ -385,28 +383,32 @@ object Action_Account {
|
|||
}.show()
|
||||
}
|
||||
|
||||
fun getReactionableAccounts(
|
||||
fun listAccountsReactionable(
|
||||
activity: ActMain,
|
||||
allowMisskey: Boolean = true,
|
||||
block: (ArrayList<SavedAccount>) -> Unit
|
||||
) {
|
||||
TootTaskRunner(activity).run(object : TootTask {
|
||||
var list: List<SavedAccount>? = null
|
||||
|
||||
suspend fun check(client:TootApiClient,a:SavedAccount)=when {
|
||||
client.isApiCancelled -> false
|
||||
a.isPseudo -> false
|
||||
a.isMisskey -> true
|
||||
else -> {
|
||||
val (ti, ri) = TootInstance.getEx(client.copy(), account = a)
|
||||
if (ti == null) {
|
||||
ri?.error?.let { log.w(it) }
|
||||
false
|
||||
} else InstanceCapability.emojiReaction(a,ti)
|
||||
}
|
||||
}
|
||||
|
||||
override suspend fun background(client: TootApiClient): TootApiResult? {
|
||||
list = SavedAccount.loadAccountList(activity).filter { a ->
|
||||
when {
|
||||
client.isApiCancelled -> false
|
||||
a.isPseudo -> false
|
||||
a.isMisskey -> allowMisskey
|
||||
else -> {
|
||||
val (ti, ri) = TootInstance.getEx(client, account = a)
|
||||
if (ti == null) {
|
||||
ri?.error?.let { log.w(it) }
|
||||
false
|
||||
} else
|
||||
ti.fedibird_capabilities?.contains("emoji_reaction") == true
|
||||
}
|
||||
}
|
||||
coroutineScope {
|
||||
list = SavedAccount.loadAccountList(activity)
|
||||
.map { async { if(check(client,it)) it else null } }
|
||||
.awaitAll()
|
||||
.filterNotNull()
|
||||
}
|
||||
return if (client.isApiCancelled) null else TootApiResult()
|
||||
}
|
||||
|
@ -417,7 +419,41 @@ object Action_Account {
|
|||
}
|
||||
})
|
||||
}
|
||||
fun listAccountsCanSeeMyReactions(
|
||||
activity: ActMain,
|
||||
block: (ArrayList<SavedAccount>) -> Unit
|
||||
) {
|
||||
TootTaskRunner(activity).run(object : TootTask {
|
||||
var list: List<SavedAccount>? = null
|
||||
|
||||
suspend fun check(client:TootApiClient,a:SavedAccount)=when {
|
||||
client.isApiCancelled -> false
|
||||
a.isPseudo -> false
|
||||
else -> {
|
||||
val (ti, ri) = TootInstance.getEx(client.copy(), account = a)
|
||||
if (ti == null) {
|
||||
ri?.error?.let { log.w(it) }
|
||||
false
|
||||
} else InstanceCapability.listMyReactions(a,ti)
|
||||
}
|
||||
}
|
||||
|
||||
override suspend fun background(client: TootApiClient): TootApiResult? {
|
||||
coroutineScope {
|
||||
list = SavedAccount.loadAccountList(activity)
|
||||
.map { async { if(check(client,it)) it else null } }
|
||||
.awaitAll()
|
||||
.filterNotNull()
|
||||
}
|
||||
return if (client.isApiCancelled) null else TootApiResult()
|
||||
}
|
||||
|
||||
override suspend fun handleResult(result: TootApiResult?) {
|
||||
result ?: return
|
||||
if (list != null) block(ArrayList(list))
|
||||
}
|
||||
})
|
||||
}
|
||||
// アカウントを選んでタイムラインカラムを追加
|
||||
fun timelineWithFilter(
|
||||
activity: ActMain,
|
||||
|
|
|
@ -1650,7 +1650,13 @@ object Action_Toot {
|
|||
)
|
||||
}
|
||||
|
||||
Action_Account.getReactionableAccounts(activity) { list ->
|
||||
Action_Account.listAccountsReactionable(activity) { list ->
|
||||
|
||||
if (list.isEmpty()) {
|
||||
activity.showToast(false, R.string.not_available_for_current_accounts)
|
||||
return@listAccountsReactionable
|
||||
}
|
||||
|
||||
AccountPicker.pick(
|
||||
activity,
|
||||
accountListArg = list,
|
||||
|
|
|
@ -53,4 +53,6 @@ object ApiPath {
|
|||
const val PATH_MISSKEY_FOLLOW_REQUESTS = "/api/following/requests/list"
|
||||
const val PATH_MISSKEY_FOLLOW_SUGGESTION = "/api/users/recommendation"
|
||||
const val PATH_MISSKEY_FAVORITES = "/api/i/favorites"
|
||||
}
|
||||
|
||||
const val PATH_M544_REACTIONS ="/api/i/reactions"
|
||||
}
|
||||
|
|
|
@ -1269,6 +1269,14 @@ class TootApiClient(
|
|||
|
||||
}
|
||||
|
||||
fun copy() =TootApiClient(
|
||||
context,
|
||||
httpClient,
|
||||
callback
|
||||
).also{dst->
|
||||
dst.account = account
|
||||
dst.apiHost = apiHost
|
||||
}
|
||||
}
|
||||
|
||||
// query: query_string after ? ( ? itself is excluded )
|
||||
|
|
|
@ -104,7 +104,6 @@ class TootTaskRunner(
|
|||
fun run(instance: Host, callback: TootTask): TootTaskRunner {
|
||||
client.apiHost = instance
|
||||
return run(callback)
|
||||
|
||||
}
|
||||
|
||||
fun progressPrefix(s: String): TootTaskRunner {
|
||||
|
|
|
@ -11,7 +11,6 @@ import jp.juggler.subwaytooter.util.LinkHelper
|
|||
import jp.juggler.subwaytooter.util.VersionString
|
||||
import jp.juggler.util.*
|
||||
import kotlinx.coroutines.Dispatchers
|
||||
import kotlinx.coroutines.GlobalScope
|
||||
import kotlinx.coroutines.channels.Channel
|
||||
import kotlinx.coroutines.launch
|
||||
import okhttp3.Request
|
||||
|
@ -28,39 +27,45 @@ enum class InstanceType {
|
|||
Pleroma
|
||||
}
|
||||
|
||||
enum class CapabilitySource {
|
||||
Fedibird,
|
||||
}
|
||||
object InstanceCapability {
|
||||
// FavouriteHashtag(CapabilitySource.Fedibird, "favourite_hashtag"),
|
||||
// FavouriteDomain(CapabilitySource.Fedibird, "favourite_domain"),
|
||||
// StatusExpire(CapabilitySource.Fedibird, "status_expire"),
|
||||
// FollowNoDelivery(CapabilitySource.Fedibird, "follow_no_delivery"),
|
||||
// FollowHashtag(CapabilitySource.Fedibird, "follow_hashtag"),
|
||||
// SubscribeAccount(CapabilitySource.Fedibird, "subscribe_account"),
|
||||
// SubscribeDomain(CapabilitySource.Fedibird, "subscribe_domain"),
|
||||
// SubscribeKeyword(CapabilitySource.Fedibird, "subscribe_keyword"),
|
||||
// TimelineNoLocal(CapabilitySource.Fedibird, "timeline_no_local"),
|
||||
// TimelineDomain(CapabilitySource.Fedibird, "timeline_domain"),
|
||||
// TimelineGroup(CapabilitySource.Fedibird, "timeline_group"),
|
||||
// TimelineGroupDirectory(CapabilitySource.Fedibird, "timeline_group_directory"),
|
||||
|
||||
enum class InstanceCapability(
|
||||
private val capabilitySource: CapabilitySource,
|
||||
private val id: String
|
||||
) {
|
||||
FavouriteHashtag(CapabilitySource.Fedibird, "favourite_hashtag"),
|
||||
FavouriteDomain(CapabilitySource.Fedibird, "favourite_domain"),
|
||||
StatusExpire(CapabilitySource.Fedibird, "status_expire"),
|
||||
FollowNoDelivery(CapabilitySource.Fedibird, "follow_no_delivery"),
|
||||
FollowHashtag(CapabilitySource.Fedibird, "follow_hashtag"),
|
||||
SubscribeAccount(CapabilitySource.Fedibird, "subscribe_account"),
|
||||
SubscribeDomain(CapabilitySource.Fedibird, "subscribe_domain"),
|
||||
SubscribeKeyword(CapabilitySource.Fedibird, "subscribe_keyword"),
|
||||
TimelineNoLocal(CapabilitySource.Fedibird, "timeline_no_local"),
|
||||
TimelineDomain(CapabilitySource.Fedibird, "timeline_domain"),
|
||||
TimelineGroup(CapabilitySource.Fedibird, "timeline_group"),
|
||||
TimelineGroupDirectory(CapabilitySource.Fedibird, "timeline_group_directory"),
|
||||
VisibilityMutual(CapabilitySource.Fedibird, "visibility_mutual"),
|
||||
VisibilityLimited(CapabilitySource.Fedibird, "visibility_limited"),
|
||||
;
|
||||
fun visibilityMutual(ti: TootInstance?) =
|
||||
ti?.fedibird_capabilities?.contains("visibility_mutual") == true
|
||||
|
||||
fun hasCapability(instance: TootInstance): Boolean {
|
||||
when (capabilitySource) {
|
||||
CapabilitySource.Fedibird -> {
|
||||
if (instance.fedibird_capabilities?.any { it == id } == true) return true
|
||||
}
|
||||
|
||||
fun visibilityLimited(ti: TootInstance?) =
|
||||
ti?.fedibird_capabilities?.contains("visibility_limited") == true
|
||||
|
||||
|
||||
fun emojiReaction(ai: SavedAccount, ti: TootInstance?) =
|
||||
when {
|
||||
ai.isPseudo -> false
|
||||
ai.isMisskey -> true
|
||||
else -> ti?.fedibird_capabilities?.contains("emoji_reaction") == true
|
||||
}
|
||||
|
||||
fun listMyReactions(ai: SavedAccount, ti: TootInstance?) =
|
||||
when {
|
||||
ai.isPseudo -> false
|
||||
ai.isMisskey ->
|
||||
// m544 extension
|
||||
ti?.misskeyEndpoints?.contains("i/reactions") == true
|
||||
else ->
|
||||
// fedibird extension
|
||||
ti?.fedibird_capabilities?.contains("emoji_reaction") == true
|
||||
}
|
||||
// XXX: もし機能がMastodon公式に取り込まれたならバージョン番号で判断できるはず
|
||||
return false
|
||||
}
|
||||
}
|
||||
|
||||
class TootInstance(parser: TootParser, src: JsonObject) {
|
||||
|
@ -121,13 +126,17 @@ class TootInstance(parser: TootParser, src: JsonObject) {
|
|||
|
||||
var feature_quote = false
|
||||
|
||||
var fedibird_capabilities: JsonArray? = null
|
||||
var fedibird_capabilities: Set<String>? = null
|
||||
|
||||
var misskeyEndpoints: Set<String>? = null
|
||||
|
||||
// XXX: urls をパースしてない。使ってないから…
|
||||
|
||||
init {
|
||||
if (parser.serviceType == ServiceType.MISSKEY) {
|
||||
|
||||
this.misskeyEndpoints = src.jsonArray("_endpoints")?.stringList()?.toSet()
|
||||
|
||||
this.uri = parser.apiHost.ascii
|
||||
this.title = parser.apiHost.pretty
|
||||
val sv = src.jsonObject("maintainer")?.string("url")
|
||||
|
@ -192,7 +201,7 @@ class TootInstance(parser: TootParser, src: JsonObject) {
|
|||
|
||||
this.invites_enabled = src.boolean("invites_enabled")
|
||||
|
||||
this.fedibird_capabilities = src.jsonArray("fedibird_capabilities")
|
||||
this.fedibird_capabilities = src.jsonArray("fedibird_capabilities")?.stringList()?.toSet()
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -222,8 +231,6 @@ class TootInstance(parser: TootParser, src: JsonObject) {
|
|||
return i >= 0
|
||||
}
|
||||
|
||||
fun hasCapability(cap: InstanceCapability) = cap.hasCapability(this)
|
||||
|
||||
companion object {
|
||||
|
||||
private val rePleroma = """\bpleroma\b""".asciiPattern(Pattern.CASE_INSENSITIVE)
|
||||
|
@ -274,7 +281,7 @@ class TootInstance(parser: TootParser, src: JsonObject) {
|
|||
if (sendRequest(result) {
|
||||
val builder = Request.Builder().url("https://${apiHost?.ascii}/api/v1/instance")
|
||||
|
||||
(forceAccessToken ?: account?.getAccessToken() )
|
||||
(forceAccessToken ?: account?.getAccessToken())
|
||||
?.notEmpty()?.let { builder.header("Authorization", "Bearer $it") }
|
||||
builder.build()
|
||||
}
|
||||
|
@ -285,6 +292,26 @@ class TootInstance(parser: TootParser, src: JsonObject) {
|
|||
return result
|
||||
}
|
||||
|
||||
private suspend fun TootApiClient.getMisskeyEndpoints(
|
||||
forceAccessToken: String? = null
|
||||
): TootApiResult? {
|
||||
val result = TootApiResult.makeWithCaption(apiHost?.pretty)
|
||||
if (result.error != null) return result
|
||||
|
||||
if (sendRequest(result) {
|
||||
jsonObject {
|
||||
(forceAccessToken ?: account?.misskeyApiToken)
|
||||
?.notEmpty()?.let { put("i", it) }
|
||||
}.toPostRequestBuilder()
|
||||
.url("https://${apiHost?.ascii}/api/endpoints")
|
||||
.build()
|
||||
}
|
||||
) {
|
||||
parseJson(result) ?: return null
|
||||
}
|
||||
return result
|
||||
}
|
||||
|
||||
// 疑似アカウントの追加時に、インスタンスの検証を行う
|
||||
private suspend fun TootApiClient.getInstanceInformationMisskey(
|
||||
forceAccessToken: String? = null
|
||||
|
@ -295,7 +322,7 @@ class TootInstance(parser: TootParser, src: JsonObject) {
|
|||
if (sendRequest(result) {
|
||||
jsonObject {
|
||||
put("dummy", 1)
|
||||
(forceAccessToken ?: account?.misskeyApiToken )
|
||||
(forceAccessToken ?: account?.misskeyApiToken)
|
||||
?.notEmpty()?.let { put("i", it) }
|
||||
}.toPostRequestBuilder()
|
||||
.url("https://${apiHost?.ascii}/api/meta")
|
||||
|
@ -309,6 +336,10 @@ class TootInstance(parser: TootParser, src: JsonObject) {
|
|||
if (m.find()) {
|
||||
put(TootApiClient.KEY_MISSKEY_VERSION, max(1, m.groupEx(1)!!.toInt()))
|
||||
}
|
||||
|
||||
// add endpoints
|
||||
val r2 = getMisskeyEndpoints(forceAccessToken)
|
||||
r2?.jsonArray?.let { result.jsonObject?.put("_endpoints", it) }
|
||||
}
|
||||
}
|
||||
return result
|
||||
|
@ -419,9 +450,9 @@ class TootInstance(parser: TootParser, src: JsonObject) {
|
|||
return queuedRequest(allowPixelfed) { cached ->
|
||||
|
||||
// may use cached item.
|
||||
if (!forceUpdate && forceAccessToken == null && cached!=null) {
|
||||
if (!forceUpdate && forceAccessToken == null && cached != null) {
|
||||
val now = SystemClock.elapsedRealtime()
|
||||
if ( now - cached.time_parse <= EXPIRE)
|
||||
if (now - cached.time_parse <= EXPIRE)
|
||||
return@queuedRequest Pair(cached, TootApiResult())
|
||||
}
|
||||
|
||||
|
|
|
@ -96,7 +96,7 @@ class TootReaction(
|
|||
|
||||
val UNKNOWN = TootReaction(name = "?")
|
||||
|
||||
fun isUnicodeEmoji(code: String): Boolean =
|
||||
private fun isUnicodeEmoji(code: String): Boolean =
|
||||
code.any { it.code >= 0x7f }
|
||||
|
||||
fun splitEmojiDomain(code: String): Pair<String?, String?> {
|
||||
|
@ -111,11 +111,7 @@ class TootReaction(
|
|||
fun canReaction(
|
||||
access_info: SavedAccount,
|
||||
ti: TootInstance? = TootInstance.getCached(access_info.apiHost)
|
||||
) = when {
|
||||
access_info.isPseudo -> false
|
||||
access_info.isMisskey -> true
|
||||
else -> ti?.fedibird_capabilities?.contains("emoji_reaction") == true
|
||||
}
|
||||
) = InstanceCapability.emojiReaction(access_info,ti)
|
||||
|
||||
fun decodeEmojiQuery(jsonText: String?): List<TootReaction> =
|
||||
jsonText.notEmpty()?.let { src ->
|
||||
|
@ -137,9 +133,6 @@ class TootReaction(
|
|||
|
||||
}
|
||||
|
||||
private val isUnicodeEmoji: Boolean
|
||||
get() = isUnicodeEmoji(name)
|
||||
|
||||
fun splitEmojiDomain() =
|
||||
splitEmojiDomain(name)
|
||||
|
||||
|
|
File diff suppressed because it is too large
Load Diff
|
@ -1079,7 +1079,7 @@
|
|||
<string name="confirm_mail_description">確認メールの再送を要求した後の手順:\n- あなたのメーラーで新着メールが届くのを確認する。\n- メール中の確認リンクを開く。\n- このダイアログを閉じてカラムをリロードする。</string>
|
||||
<string name="push_notification_filter">プッシュ通知フィルタ(Mastodon 3.4.0以降。プッシュ通知の更新が必要)</string>
|
||||
<string name="no_one">誰もいない</string>
|
||||
<string name="fedibird_reactions">リアクション (Fedibird)</string>
|
||||
<string name="reactioned_posts">リアクションした投稿</string>
|
||||
<string name="reactions">リアクション</string>
|
||||
<string name="cant_reaction_remote_custom_emoji">リモートのカスタム絵文字でリアクションできません %1$s</string>
|
||||
<string name="keep_reaction_space">リアクション表示用の空間を確保する</string>
|
||||
|
@ -1090,5 +1090,5 @@
|
|||
<string name="cant_save_duplicated_keyword">既に存在するキーワードを重複保存できません</string>
|
||||
<string name="discard_changes">変更を破棄しますか?</string>
|
||||
<string name="saved">保存しました</string>
|
||||
|
||||
<string name="not_available_for_current_accounts">この機能を利用できるアカウントがありません</string>
|
||||
</resources>
|
||||
|
|
|
@ -1093,7 +1093,7 @@
|
|||
<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>
|
||||
<string name="fedibird_reactions">Reactions (Fedibird)</string>
|
||||
<string name="reactioned_posts">Reactioned posts</string>
|
||||
<string name="reactions">Reactions</string>
|
||||
<string name="cant_reaction_remote_custom_emoji">can\'t reaction with remote custom emoji %1$s</string>
|
||||
<string name="keep_reaction_space">Keep Spacing for Reactions</string>
|
||||
|
@ -1103,4 +1103,6 @@
|
|||
<string name="cant_save_duplicated_keyword">Can\'t save duplicated keyword.</string>
|
||||
<string name="discard_changes">Discard changes?</string>
|
||||
<string name="saved">saved.</string>
|
||||
<string name="not_available_for_current_accounts">Unavailable for current accounts</string>
|
||||
|
||||
</resources>
|
||||
|
|
Loading…
Reference in New Issue