More flexible Relative time format string

This commit is contained in:
tateisu 2018-12-27 02:08:01 +09:00
parent d263262ad8
commit 856fbd6470
7 changed files with 130 additions and 120 deletions

View File

@ -2,6 +2,7 @@ package jp.juggler.subwaytooter.api.entity
import android.annotation.SuppressLint
import android.content.Context
import android.support.annotation.StringRes
import android.text.Spannable
import android.text.SpannableString
import jp.juggler.subwaytooter.App1
@ -21,6 +22,7 @@ import java.text.SimpleDateFormat
import java.util.*
import java.util.regex.Pattern
import kotlin.collections.ArrayList
import kotlin.math.abs
@Suppress("MemberVisibilityCanPrivate")
class TootStatus(parser : TootParser, src : JSONObject) : TimelineItem() {
@ -89,7 +91,7 @@ class TootStatus(parser : TootParser, src : JSONObject) : TimelineItem() {
// Pleromaは「空文字列CWなし」「空じゃない文字列CWあり」の2種類
// Misskeyは「CWなし」「空欄CW」「CWあり」の3通り。空欄CWはパース時に書き換えてしまう
// Misskeyで投稿が削除された時に変更されるため、val変数にできない
var spoiler_text : String =""
var spoiler_text : String = ""
var decoded_spoiler_text : Spannable
// Body of the status; this will contain HTML (remote HTML already sanitized)
@ -281,7 +283,7 @@ class TootStatus(parser : TootParser, src : JSONObject) : TimelineItem() {
if(options.highlight_sound != null && this.highlight_sound == null) {
this.highlight_sound = options.highlight_sound
}
// Markdownのデコード結果からmentionsを読むのだった
this.mentions =
(decoded_content as? MisskeyMarkdownDecoder.SpannableStringBuilderEx)?.mentions
@ -292,12 +294,12 @@ class TootStatus(parser : TootParser, src : JSONObject) : TimelineItem() {
) ?: EMPTY_SPANNABLE
val sv = src.parseString("cw")?.cleanCW()
this.spoiler_text = when{
this.spoiler_text = when {
sv == null -> "" // CWなし
sv.isBlank() -> parser.context.getString(R.string.blank_cw)
else-> sv
else -> sv
}
options = DecodeOptions(
parser.context,
parser.linkHelper,
@ -368,7 +370,7 @@ class TootStatus(parser : TootParser, src : JSONObject) : TimelineItem() {
ServiceType.MASTODON -> {
this.host_access = parser.linkHelper.host
this.id = EntityId.mayDefault(src.parseLong("id") )
this.id = EntityId.mayDefault(src.parseLong("id"))
this.uri = src.parseString("uri") ?: error("missing uri")
this.reblogged = src.optBoolean("reblogged")
@ -394,7 +396,7 @@ class TootStatus(parser : TootParser, src : JSONObject) : TimelineItem() {
// 投稿元タンスでのIDを調べる。失敗するかもしれない
this.uri = src.parseString("uri") ?: error("missing uri")
this.id = findStatusIdFromUri(uri, url) ?: EntityId.defaultLong
this.time_created_at = TootStatus.parseTime(this.created_at)
this.media_attachments =
parseListOrNull(
@ -412,10 +414,11 @@ class TootStatus(parser : TootParser, src : JSONObject) : TimelineItem() {
this.host_access = null
// MSPのデータはLTLから呼んだものなので、常に投稿元タンスでのidが得られる
this.id = EntityId.mayDefault(src.parseLong("id") )
this.id = EntityId.mayDefault(src.parseLong("id"))
// MSPだとuriは提供されない。LTL限定なのでURL的なものを作れるはず
this.uri = "https://${parser.linkHelper.host}/users/${who.username}/statuses/$id"
this.uri =
"https://${parser.linkHelper.host}/users/${who.username}/statuses/$id"
this.time_created_at = parseTimeMSP(created_at)
this.media_attachments =
TootAttachmentMSP.parseList(src.optJSONArray("media_attachments"))
@ -463,13 +466,13 @@ class TootStatus(parser : TootParser, src : JSONObject) : TimelineItem() {
this.highlight_sound = options.highlight_sound
}
val sv = (src.parseString("spoiler_text")?:"").cleanCW()
this.spoiler_text = when{
sv.isEmpty() ->"" // CWなし
sv.isBlank() ->parser.context.getString(R.string.blank_cw)
else->sv
val sv = (src.parseString("spoiler_text") ?: "").cleanCW()
this.spoiler_text = when {
sv.isEmpty() -> "" // CWなし
sv.isBlank() -> parser.context.getString(R.string.blank_cw)
else -> sv
}
options = DecodeOptions(
parser.context,
emojiMapCustom = custom_emojis,
@ -499,7 +502,6 @@ class TootStatus(parser : TootParser, src : JSONObject) : TimelineItem() {
}
}
///////////////////////////////////////////////////
// ユーティリティ
@ -600,7 +602,7 @@ class TootStatus(parser : TootParser, src : JSONObject) : TimelineItem() {
|| enquete != null -> true
else -> false
}
// return true if updated
fun increaseReaction(reaction : String?, byMe : Boolean, caller : String) : Boolean {
reaction ?: return false
@ -682,9 +684,11 @@ class TootStatus(parser : TootParser, src : JSONObject) : TimelineItem() {
// 公開ステータスページのURL Misskey
@Suppress("HasPlatformType")
val reStatusPageMisskey = Pattern.compile("""\Ahttps://([^/]+)/notes/([0-9a-f]{24})\b""", Pattern.CASE_INSENSITIVE)
val reStatusPageMisskey = Pattern.compile(
"""\Ahttps://([^/]+)/notes/([0-9a-f]{24})\b""",
Pattern.CASE_INSENSITIVE
)
fun parseListTootsearch(
parser : TootParser,
root : JSONObject
@ -780,48 +784,52 @@ class TootStatus(parser : TootParser, src : JSONObject) : TimelineItem() {
if(bAllowRelative && Pref.bpRelativeTimestamp(App1.pref)) {
val now = System.currentTimeMillis()
var delta = now - t
val sign = context.getString(if(delta > 0) R.string.ago else R.string.later)
delta = if(delta >= 0) delta else - delta
@StringRes val phraseId = if(delta >= 0)
R.string.relative_time_phrase_past
else
R.string.relative_time_phrase_future
delta = abs(delta)
fun f(v : Long, unit1 : Int, units : Int) : String {
val vi = v.toInt()
return context.getString(
phraseId,
vi,
context.getString(if(vi <= 1) unit1 else units)
)
}
when {
delta < 1000L -> return context.getString(R.string.time_within_second)
delta < 60000L -> {
val v = (delta / 1000L).toInt()
return context.getString(
if(v > 1) R.string.relative_time_second_2 else R.string.relative_time_second_1,
v,
sign
)
}
delta < 60000L -> return f(
delta / 1000L,
R.string.relative_time_unit_second1,
R.string.relative_time_unit_seconds
)
delta < 3600000L -> {
val v = (delta / 60000L).toInt()
return context.getString(
if(v > 1) R.string.relative_time_minute_2 else R.string.relative_time_minute_1,
v,
sign
)
}
delta < 3600000L -> return f(
delta / 60000L,
R.string.relative_time_unit_minute1,
R.string.relative_time_unit_minutes
)
delta < 86400000L -> {
val v = (delta / 3600000L).toInt()
return context.getString(
if(v > 1) R.string.relative_time_hour_2 else R.string.relative_time_hour_1,
v,
sign
)
}
delta < 86400000L -> return f(
delta / 3600000L,
R.string.relative_time_unit_hour1,
R.string.relative_time_unit_hours
)
delta < 40 * 86400000L -> {
val v = (delta / 86400000L).toInt()
return context.getString(
if(v > 1) R.string.relative_time_day_2 else R.string.relative_time_day_1,
v,
sign
)
}
delta < 40 * 86400000L -> return f(
delta / 86400000L,
R.string.relative_time_unit_day1,
R.string.relative_time_unit_days
)
else -> {
// fall back to absolute time
}
}
}
@ -874,11 +882,10 @@ class TootStatus(parser : TootParser, src : JSONObject) : TimelineItem() {
return if(host != null && host.isNotEmpty() && host != "?") host else null
}
private fun readMisskeyNoteId(url : String) : EntityId? {
// https://misskey.xyz/notes/5b802367744b650030a13640
val m = reStatusPageMisskey.matcher(url)
return if(!m.find()) null else EntityIdString(m.group(2))
return if(! m.find()) null else EntityIdString(m.group(2))
}
fun validStatusId(src : EntityId?) : EntityId? {
@ -889,12 +896,10 @@ class TootStatus(parser : TootParser, src : JSONObject) : TimelineItem() {
}
}
private fun String.cleanCW() =
CharacterGroup.reWhitespace.matcher(this).replaceAll(" ").sanitizeBDI()
/* 空欄かどうかがCW判定条件に影響するので、trimしてはいけない */
// 投稿元タンスでのステータスIDを調べる
fun findStatusIdFromUri(
uri : String?,

View File

@ -244,17 +244,8 @@
<string name="input_access_token">تحديد رمز النفاذ (للمستخدمين المتقدمين)</string>
<string name="title">العنوان</string>
<string name="instance_information">معلومات عن مثيل الخادوم</string>
<string name="later">لاحقًا</string>
<string name="time_within_second">الآن</string>
<string name="relative_time_second_1">%1$d ثانية %2$s</string>
<string name="relative_time_second_2">%1$d ثواني %2$s</string>
<string name="relative_time_minute_1">%1$d دقيقة %2$s</string>
<string name="relative_time_minute_2">%1$d دقائق %2$s</string>
<string name="relative_time_hour_1">%1$d ساعة %2$s</string>
<string name="relative_time_hour_2">%1$d ساعات %2$s</string>
<string name="relative_time_day_1">%1$d يوم %2$s</string>
<string name="relative_time_day_2">%1$d أيام %2$s</string>
<string name="time_within_second">الآن</string>
<string name="make_enquete">إنشاء استطلاع للرأي</string>
<string name="profile_pin">تدبيس على الملف الشخصي</string>
<string name="profile_unpin">إلغاء التدبيس مِن الملف الشخصي</string>
@ -396,7 +387,7 @@
<string name="ui_theme">سمة واجهة المستخدم (مطلوب أعادة تشغيل التطبيق)</string>
<string name="simple_list">قائمة بسيطة (مطلوب أعادة تشغيل التطبيق)</string>
<string name="unfavourite_succeeded">تم حذفه من المفضلة</string>
<string name="file_size_too_big">"حجم هذا الملف أكبر من الحد الأقصى المسموح به %1$dMB."</string>
<string name="file_size_too_big">حجم هذا الملف أكبر من الحد الأقصى المسموح به %1$dMB.</string>
<string name="visibility_local_home">الرئيسية (محلي)</string>
<string name="visibility_local_followers">للمتابِعين فقط (محلي)</string>
<string name="visibility_local_unlisted">غير مدرج (محلي)</string>

View File

@ -303,7 +303,6 @@
<string name="version">Fersiwn</string>
<string name="instance_information_of">Gwybodaeth achos \"%1$s\"</string>
<string name="instance_information">Gwybodaeth achos</string>
<string name="later">wedyn</string>
<string name="enquete_voted">Wedi pleidleisio!</string>
<string name="enquete_vote_failed">Pleidlais wedi methu. %1$s</string>
<string name="choice1">dewis 1</string>
@ -418,15 +417,18 @@
<string name="acct_sample">(sampl)enwdefnyddiwr@achos</string>
<string name="change_header">Newid delwedd pennawd</string>
<string name="missing_mail_app">Ap E-bost ar goll.</string>
<string name="ago">yn ôl</string>
<string name="relative_time_second_1">%1$d eiliad %2$s</string>
<string name="relative_time_second_2">%1$d eiliadau %2$s</string>
<string name="relative_time_minute_1">%1$d munud %2$s</string>
<string name="relative_time_minute_2">%1$d munudau %2$s</string>
<string name="relative_time_hour_1">%1$d awr %2$s</string>
<string name="relative_time_hour_2">%1$d oriau %2$s</string>
<string name="relative_time_day_1">%1$d dydd %2$s</string>
<string name="relative_time_day_2">%1$d dyddiau %2$s</string>
<string name="relative_time_unit_second1">eiliad</string>
<string name="relative_time_unit_seconds">eiliadau</string>
<string name="relative_time_unit_minute1">munud</string>
<string name="relative_time_unit_minutes">munudau</string>
<string name="relative_time_unit_hour1">awr</string>
<string name="relative_time_unit_hours">oriau</string>
<string name="relative_time_unit_day1">dydd</string>
<string name="relative_time_unit_days">dyddiau</string>
<string name="relative_time_phrase_past">%1$d %2$s yn ôl</string>
<string name="relative_time_phrase_future">%1$d %2$s wedyn</string>
<string name="skin_tone_light">lliw croen golau</string>
<string name="skin_tone_medium_light">lliw croen cymhedrol o olau</string>
<string name="skin_tone_medium">lliw croen cymhedrol</string>

View File

@ -447,17 +447,19 @@
<string name="instance_information">Informations sur l\'instance</string>
<string name="missing_mail_app">App de courriel manquante.</string>
<string name="relative_timestamp">Afficher les horodatages relatifs</string>
<string name="ago">ago</string>
<string name="later">plus tard</string>
<string name="time_within_second">à l\'instant</string>
<string name="relative_time_second_1">%1$d seconde %2$s</string>
<string name="relative_time_second_2">%1$d secondes %2$s</string>
<string name="relative_time_minute_1">%1$d minute %2$s</string>
<string name="relative_time_minute_2">%1$d minutes %2$s</string>
<string name="relative_time_hour_1">%1$d heure %2$s</string>
<string name="relative_time_hour_2">%1$d heures %2$s</string>
<string name="relative_time_day_1">%1$d day %2$s</string>
<string name="relative_time_day_2">%1$d jours %2$s</string>
<string name="relative_time_unit_second1">seconde</string>
<string name="relative_time_unit_seconds">secondes</string>
<string name="relative_time_unit_minute1">minute</string>
<string name="relative_time_unit_minutes">minutes</string>
<string name="relative_time_unit_hour1">heure</string>
<string name="relative_time_unit_hours">heures</string>
<string name="relative_time_unit_day1">day</string>
<string name="relative_time_unit_days">jours</string>
<string name="relative_time_phrase_past">%1$d %2$s ago</string>
<string name="relative_time_phrase_future">%1$d %2$s plus tard</string>
<string name="notification_sound_before_oreo">Son de notification (avant Android 8.0)</string>
<string name="notification_style_after_oreo">Style de notification (Android 8.0 ou version ultérieure)</string>
<string name="notification_for">Notification for %1$s</string>

View File

@ -34,7 +34,6 @@
<string name="actions_for_notification">通知へのアクション</string>
<string name="actions_for_status">トゥートへのアクション</string>
<string name="actions_for_user">ユーザへのアクション</string>
<string name="ago"></string>
<string name="allow_column_duplication">カラムの重複を許容する</string>
<string name="allow_non_space_before_emoji_code">絵文字コードの手前に空白以外の文字があっても変換する (投稿と表示の両方に影響します。表示の反映にはアプリ再起動とカラムのリロードが必要です。投稿時に変換された絵文字を元のコードに戻すことはできません。)</string>
<string name="already_boosted">既にブースト済みです</string>
@ -370,7 +369,6 @@
<string name="language_code">ja</string>
<string name="languages">言語</string>
<string name="last_selection">最後に選択した</string>
<string name="later"></string>
<string name="launcher_icon_by">ランチャーアイコンはフタバさんがデザインしました</string>
<string name="led">LED</string>
<string name="length_warning">\"%1$s\"が長すぎます(%2$d/%3$d文字).\n標準的なタンスではエラーとなりますが、一部のタンスでは通るかも。\nよろしいですか?</string>
@ -562,14 +560,17 @@
<string name="regex_filter">正規表現フィルタ(上級者向け)</string>
<string name="regex_filter_matches_empty_string">正規表現フィルタは空文字列にマッチしてしまいます</string>
<string name="register_app_to_server">%1$sにこのアプリを登録しています…</string>
<string name="relative_time_day_1">%1$d日%2$s</string>
<string name="relative_time_day_2">%1$d日%2$s</string>
<string name="relative_time_hour_1">%1$d時間%2$s</string>
<string name="relative_time_hour_2">%1$d時間%2$s</string>
<string name="relative_time_minute_1">%1$d分%2$s</string>
<string name="relative_time_minute_2">%1$d分%2$s</string>
<string name="relative_time_second_1">%1$d秒%2$s</string>
<string name="relative_time_second_2">%1$d秒%2$s</string>
<string name="relative_time_unit_second1"></string>
<string name="relative_time_unit_seconds"></string>
<string name="relative_time_unit_minute1"></string>
<string name="relative_time_unit_minutes"></string>
<string name="relative_time_unit_hour1">時間</string>
<string name="relative_time_unit_hours">時間</string>
<string name="relative_time_unit_day1"></string>
<string name="relative_time_unit_days"></string>
<string name="relative_time_phrase_past">%1$d %2$s前</string>
<string name="relative_time_phrase_future">%1$d %2$s後</string>
<string name="relative_timestamp">相対時刻を表示</string>
<string name="reload">再読み込み</string>
<string name="remote_profile_warning">リモートユーザのプロフィールは情報が不十分な可能性があります。より正確な情報をWebページで確認することができます。</string>

View File

@ -367,18 +367,19 @@
<string name="instance_information">Instansinfo</string>
<string name="missing_mail_app">Manglende e-postprogram.</string>
<string name="relative_timestamp">Vis relative tidsstempel</string>
<string name="ago">siden</string>
<string name="later">senere</string>
<string name="time_within_second">akkurat nå</string>
<string name="relative_time_second_1">%1$d sekund %2$s</string>
<string name="relative_time_second_2">%1$d sekunder %2$s</string>
<string name="relative_time_minute_1">%1$d minutt %2$s</string>
<string name="relative_time_minute_2">%1$d minutter %2$s</string>
<string name="relative_time_hour_1">%1$d time %2$s</string>
<string name="relative_time_hour_2">%1$d timer %2$s</string>
<string name="relative_time_day_1">%1$d dag %2$s</string>
<string name="relative_time_day_2">%1$d dager %2$s</string>
<string name="relative_time_unit_second1">sekund</string>
<string name="relative_time_unit_seconds">sekunder</string>
<string name="relative_time_unit_minute1">minutt</string>
<string name="relative_time_unit_minutes">minutter</string>
<string name="relative_time_unit_hour1">time</string>
<string name="relative_time_unit_hours">timer</string>
<string name="relative_time_unit_day1">dag</string>
<string name="relative_time_unit_days">dager</string>
<string name="relative_time_phrase_past">%1$d %2$s siden</string>
<string name="relative_time_phrase_future">%1$d %2$s senere</string>
<string name="notification_channel_description">Disse innstillingen brukes for merknad for %1$s</string>
<string name="notification_sound_before_oreo">Merknadslyd (før Android 8.0)</string>
<string name="notification_style_after_oreo">Merknadsstil (Android 8.0 eller senere)</string>

View File

@ -455,18 +455,26 @@
<string name="instance_information">Instance information</string>
<string name="missing_mail_app">Missing e-mail app.</string>
<string name="relative_timestamp">Show relative timestamps</string>
<string name="ago">ago</string>
<string name="later">later</string>
<string name="time_within_second">just now</string>
<string name="relative_time_unit_second1">second</string>
<string name="relative_time_unit_seconds">seconds</string>
<string name="relative_time_unit_minute1">minute</string>
<string name="relative_time_unit_minutes">minutes</string>
<string name="relative_time_unit_hour1">hour</string>
<string name="relative_time_unit_hours">hours</string>
<string name="relative_time_unit_day1">day</string>
<string name="relative_time_unit_days">days</string>
<string name="relative_time_phrase_past">%1$d %2$s</string>
<string name="relative_time_phrase_future">%1$d %2$s future</string>
<string name="relative_time_second_1">%1$d second %2$s</string>
<string name="relative_time_second_2">%1$d seconds %2$s</string>
<string name="relative_time_minute_1">%1$d minute %2$s</string>
<string name="relative_time_minute_2">%1$d minutes %2$s</string>
<string name="relative_time_hour_1">%1$d hour %2$s</string>
<string name="relative_time_hour_2">%1$d hours %2$s</string>
<string name="relative_time_day_1">%1$d day %2$s</string>
<string name="relative_time_day_2">%1$d days %2$s</string>
<!--<string name="relative_time_second_1">%1$d second %2$s</string>-->
<!--<string name="relative_time_second_2">%1$d seconds %2$s</string>-->
<!--<string name="relative_time_minute_1">%1$d minute %2$s</string>-->
<!--<string name="relative_time_minute_2">%1$d minutes %2$s</string>-->
<!--<string name="relative_time_hour_1">%1$d hour %2$s</string>-->
<!--<string name="relative_time_hour_2">%1$d hours %2$s</string>-->
<!--<string name="relative_time_day_1">%1$d day %2$s</string>-->
<!--<string name="relative_time_day_2">%1$d days %2$s</string>-->
<string name="notification_channel_description">This setting is used to adjust notification for %1$s</string>
<string name="notification_sound_before_oreo">Notification sound (pre Android 8.0)</string>
<string name="notification_style_after_oreo">Notification style (Android 8.0+)</string>