diff --git a/app/src/main/java/com/hippo/ehviewer/util/ReadableTime.kt b/app/src/main/java/com/hippo/ehviewer/util/ReadableTime.kt index 11775b144..2edd7d0fc 100644 --- a/app/src/main/java/com/hippo/ehviewer/util/ReadableTime.kt +++ b/app/src/main/java/com/hippo/ehviewer/util/ReadableTime.kt @@ -13,123 +13,116 @@ * See the License for the specific language governing permissions and * limitations under the License. */ +package com.hippo.ehviewer.util -package com.hippo.ehviewer.util; +import android.content.Context +import android.content.res.Resources +import com.hippo.ehviewer.R +import java.time.Instant +import java.time.ZoneId +import java.time.ZoneOffset +import java.time.format.DateTimeFormatter +import java.util.Locale -import android.content.Context; -import android.content.res.Resources; - -import com.hippo.ehviewer.R; - -import java.time.Instant; -import java.time.OffsetDateTime; -import java.time.ZoneId; -import java.time.ZoneOffset; -import java.time.format.DateTimeFormatter; -import java.util.Locale; - -public final class ReadableTime { - - public static final long SECOND_MILLIS = 1000; - public static final long MINUTE_MILLIS = 60 * SECOND_MILLIS; - public static final long HOUR_MILLIS = 60 * MINUTE_MILLIS; - public static final long DAY_MILLIS = 24 * HOUR_MILLIS; - public static final long WEEK_MILLIS = 7 * DAY_MILLIS; - public static final long YEAR_MILLIS = 365 * DAY_MILLIS; - public static final long[] MULTIPLES = { - YEAR_MILLIS, - DAY_MILLIS, - HOUR_MILLIS, - MINUTE_MILLIS, - SECOND_MILLIS - }; - public static final int SIZE = 5; - public static final int[] UNITS = { - R.plurals.year, - R.plurals.day, - R.plurals.hour, - R.plurals.minute, - R.plurals.second - }; - private static final Object sCalendarLock = new Object(); - private static final DateTimeFormatter DATE_FORMAT_WITHOUT_YEAR = DateTimeFormatter.ofPattern("MMM d"); - private static final DateTimeFormatter DATE_FORMAT_WITH_YEAR = DateTimeFormatter.ofPattern("MMM d, yyyy"); - private static final DateTimeFormatter DATE_FORMAT_WITHOUT_YEAR_ZH = DateTimeFormatter.ofPattern("M月d日"); - private static final DateTimeFormatter DATE_FORMAT_WITH_YEAR_ZH = DateTimeFormatter.ofPattern("yyyy年M月d日"); - private static final DateTimeFormatter FILENAMABLE_DATE_FORMAT = DateTimeFormatter.ofPattern("yyyy-MM-dd-HH-mm-ss-SSS"); - private static final Object sDateFormatLock = new Object(); - private static Resources sResources; - - public static void initialize(Context context) { - sResources = context.getApplicationContext().getResources(); +object ReadableTime { + private const val SECOND_MILLIS: Long = 1000 + private const val MINUTE_MILLIS = 60 * SECOND_MILLIS + private const val HOUR_MILLIS = 60 * MINUTE_MILLIS + private const val DAY_MILLIS = 24 * HOUR_MILLIS + private const val WEEK_MILLIS = 7 * DAY_MILLIS + private const val YEAR_MILLIS = 365 * DAY_MILLIS + private val MULTIPLES = longArrayOf( + YEAR_MILLIS, + DAY_MILLIS, + HOUR_MILLIS, + MINUTE_MILLIS, + SECOND_MILLIS, + ) + private const val SIZE = 5 + private val UNITS = intArrayOf( + R.plurals.year, + R.plurals.day, + R.plurals.hour, + R.plurals.minute, + R.plurals.second, + ) + private val sCalendarLock = Any() + private val DATE_FORMAT_WITHOUT_YEAR = DateTimeFormatter.ofPattern("MMM d") + private val DATE_FORMAT_WITH_YEAR = DateTimeFormatter.ofPattern("MMM d, yyyy") + private val DATE_FORMAT_WITHOUT_YEAR_ZH = DateTimeFormatter.ofPattern("M月d日") + private val DATE_FORMAT_WITH_YEAR_ZH = DateTimeFormatter.ofPattern("yyyy年M月d日") + private val FILENAMABLE_DATE_FORMAT = DateTimeFormatter.ofPattern("yyyy-MM-dd-HH-mm-ss-SSS") + private val sDateFormatLock = Any() + private var sResources: Resources? = null + fun initialize(context: Context) { + sResources = context.applicationContext.resources } - public static String getTimeAgo(long time) { - Resources resources = sResources; - - long now = System.currentTimeMillis(); - if (time > now + (2 * MINUTE_MILLIS) || time <= 0) { - return resources.getString(R.string.from_the_future); + fun getTimeAgo(time: Long): String { + val resources = sResources + val now = System.currentTimeMillis() + if (time > now + 2 * MINUTE_MILLIS || time <= 0) { + return resources!!.getString(R.string.from_the_future) } - - final long diff = now - time; + val diff = now - time if (diff < MINUTE_MILLIS) { - return resources.getString(R.string.just_now); + return resources!!.getString(R.string.just_now) } else if (diff < 2 * MINUTE_MILLIS) { - return resources.getQuantityString(R.plurals.some_minutes_ago, 1, 1); + return resources!!.getQuantityString(R.plurals.some_minutes_ago, 1, 1) } else if (diff < 50 * MINUTE_MILLIS) { - int minutes = (int) (diff / MINUTE_MILLIS); - return resources.getQuantityString(R.plurals.some_minutes_ago, minutes, minutes); + val minutes = (diff / MINUTE_MILLIS).toInt() + return resources!!.getQuantityString(R.plurals.some_minutes_ago, minutes, minutes) } else if (diff < 90 * MINUTE_MILLIS) { - return resources.getQuantityString(R.plurals.some_hours_ago, 1, 1); + return resources!!.getQuantityString(R.plurals.some_hours_ago, 1, 1) } else if (diff < 24 * HOUR_MILLIS) { - int hours = (int) (diff / HOUR_MILLIS); - return resources.getQuantityString(R.plurals.some_hours_ago, hours, hours); + val hours = (diff / HOUR_MILLIS).toInt() + return resources!!.getQuantityString(R.plurals.some_hours_ago, hours, hours) } else if (diff < 48 * HOUR_MILLIS) { - return resources.getString(R.string.yesterday); + return resources!!.getString(R.string.yesterday) } else if (diff < WEEK_MILLIS) { - int days = (int) (diff / DAY_MILLIS); - return resources.getString(R.string.some_days_ago, days); + val days = (diff / DAY_MILLIS).toInt() + return resources!!.getString(R.string.some_days_ago, days) } else { - synchronized (sCalendarLock) { - OffsetDateTime nowDate = Instant.ofEpochMilli(now).atOffset(ZoneOffset.UTC); - OffsetDateTime timeDate = Instant.ofEpochMilli(time).atOffset(ZoneOffset.UTC); - int nowYear = nowDate.getYear(); - int timeYear = timeDate.getYear(); - boolean isZh = Locale.getDefault().getLanguage().equals("zh"); - - if (nowYear == timeYear) { - return (isZh ? DATE_FORMAT_WITHOUT_YEAR_ZH : DATE_FORMAT_WITHOUT_YEAR) - .format(timeDate.toInstant().atOffset(ZoneOffset.UTC)); + synchronized(sCalendarLock) { + val nowDate = Instant.ofEpochMilli(now).atOffset(ZoneOffset.UTC) + val timeDate = Instant.ofEpochMilli(time).atOffset(ZoneOffset.UTC) + val nowYear = nowDate.year + val timeYear = timeDate.year + val isZh = Locale.getDefault().language == "zh" + return if (nowYear == timeYear) { + (if (isZh) DATE_FORMAT_WITHOUT_YEAR_ZH else DATE_FORMAT_WITHOUT_YEAR) + .format(timeDate.toInstant().atOffset(ZoneOffset.UTC)) } else { - return (isZh ? DATE_FORMAT_WITH_YEAR_ZH : DATE_FORMAT_WITH_YEAR) - .format(timeDate.toInstant().atOffset(ZoneOffset.UTC)); + (if (isZh) DATE_FORMAT_WITH_YEAR_ZH else DATE_FORMAT_WITH_YEAR) + .format(timeDate.toInstant().atOffset(ZoneOffset.UTC)) } } } } - public static String getShortTimeInterval(long time) { - StringBuilder sb = new StringBuilder(); - Resources resources = sResources; - - for (int i = 0; i < SIZE; i++) { - long multiple = MULTIPLES[i]; - long quotient = time / multiple; + fun getShortTimeInterval(time: Long): String { + val sb = StringBuilder() + val resources = sResources + for (i in 0 until SIZE) { + val multiple = MULTIPLES[i] + val quotient = time / multiple if (time > multiple * 1.5 || i == SIZE - 1) { sb.append(quotient) - .append(" ") - .append(resources.getQuantityString(UNITS[i], (int) quotient)); - break; + .append(" ") + .append(resources!!.getQuantityString(UNITS[i], quotient.toInt())) + break } } - - return sb.toString(); + return sb.toString() } - public static String getFilenamableTime(long time) { - synchronized (sDateFormatLock) { - return FILENAMABLE_DATE_FORMAT.format(Instant.ofEpochMilli(time).atZone(ZoneId.systemDefault())); + fun getFilenamableTime(time: Long): String { + synchronized(sDateFormatLock) { + return FILENAMABLE_DATE_FORMAT.format( + Instant.ofEpochMilli(time).atZone( + ZoneId.systemDefault(), + ), + ) } } } diff --git a/app/src/main/java/com/hippo/ehviewer/util/TextUrl.kt b/app/src/main/java/com/hippo/ehviewer/util/TextUrl.kt index 0ae13a1ee..10dc79ef3 100644 --- a/app/src/main/java/com/hippo/ehviewer/util/TextUrl.kt +++ b/app/src/main/java/com/hippo/ehviewer/util/TextUrl.kt @@ -13,47 +13,39 @@ * See the License for the specific language governing permissions and * limitations under the License. */ +package com.hippo.ehviewer.util -package com.hippo.ehviewer.util; +import android.text.Spannable +import android.text.SpannableString +import android.text.style.URLSpan +import java.util.regex.Pattern -import android.text.Spannable; -import android.text.SpannableString; -import android.text.style.URLSpan; +object TextUrl { + private val URL_PATTERN = + Pattern.compile("(http|https)://[a-z0-9A-Z%-]+(\\.[a-z0-9A-Z%-]+)+(:\\d{1,5})?(/[a-zA-Z0-9-_~:#@!&',;=%/*.?+$\\[\\]()]+)?/?") -import java.util.regex.Matcher; -import java.util.regex.Pattern; - -public final class TextUrl { - - private static final Pattern URL_PATTERN = Pattern.compile("(http|https)://[a-z0-9A-Z%-]+(\\.[a-z0-9A-Z%-]+)+(:\\d{1,5})?(/[a-zA-Z0-9-_~:#@!&',;=%/*.?+$\\[\\]()]+)?/?"); - - public static CharSequence handleTextUrl(CharSequence content) { - Matcher m = URL_PATTERN.matcher(content); - - Spannable spannable = null; + fun handleTextUrl(content: CharSequence): CharSequence { + val m = URL_PATTERN.matcher(content) + var spannable: Spannable? = null while (m.find()) { // Ensure spannable if (spannable == null) { - if (content instanceof Spannable) { - spannable = (Spannable) content; + spannable = if (content is Spannable) { + content } else { - spannable = new SpannableString(content); + SpannableString(content) } } - - int start = m.start(); - int end = m.end(); - - URLSpan[] links = spannable.getSpans(start, end, URLSpan.class); - if (links.length > 0) { + val start = m.start() + val end = m.end() + val links = spannable.getSpans(start, end, URLSpan::class.java) + if (links.isNotEmpty()) { // There has been URLSpan already, leave it alone - continue; + continue } - - URLSpan urlSpan = new URLSpan(m.group(0)); - spannable.setSpan(urlSpan, start, end, Spannable.SPAN_EXCLUSIVE_EXCLUSIVE); + val urlSpan = URLSpan(m.group(0)) + spannable.setSpan(urlSpan, start, end, Spannable.SPAN_EXCLUSIVE_EXCLUSIVE) } - - return spannable == null ? content : spannable; + return spannable ?: content } }