Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
21 commits
Select commit Hold shift + click to select a range
3fc84d0
Improve relative time formatting in the notification activity.
Isira-Seneviratne Mar 20, 2023
5e72b19
Fix test issue.
Isira-Seneviratne Apr 22, 2023
0ed177d
Fix variable name.
Isira-Seneviratne Apr 24, 2023
1fb7c40
Merge branch 'main' into Notification_time_ago
Isira-Seneviratne Sep 24, 2023
4f1f76e
Add Instant serializer
Isira-Seneviratne Sep 24, 2023
7f5ac4d
Use LocalDate.ofInstant()
Isira-Seneviratne Sep 24, 2023
605c4e7
Merge branch 'main' into Notification_time_ago
Isira-Seneviratne Oct 18, 2023
55b6026
Merge branch 'main' into Notification_time_ago
Isira-Seneviratne Jan 20, 2024
6bc61ef
Merge branch 'main' into Notification_time_ago
Isira-Seneviratne Feb 5, 2024
e2f68a2
Merge branch 'refs/heads/main' into Notification_time_ago
Isira-Seneviratne Oct 23, 2024
c0f7ca4
Switch to Kotlinx Datetime
Isira-Seneviratne Oct 24, 2024
a80045b
Merge branch 'main' into Notification_time_ago
Isira-Seneviratne Nov 17, 2024
dfbeaed
Merge branch 'main' into Notification_time_ago
Isira-Seneviratne Nov 21, 2024
0b96068
Merge branch 'main' into Notification_time_ago
Isira-Seneviratne Dec 4, 2024
405ee95
Merge branch 'main' into Notification_time_ago
Isira-Seneviratne Feb 21, 2025
cbe4993
Merge branch 'main' into Notification_time_ago
Isira-Seneviratne Jul 6, 2025
b7400e3
Merge branch 'main' into Notification_time_ago
Isira-Seneviratne Jul 18, 2025
8970440
Merge branch 'main' into Notification_time_ago
Isira-Seneviratne Jul 23, 2025
88e9838
Fix import
Isira-Seneviratne Jul 23, 2025
07c86cb
Use Instant.DISTANT_PAST
Isira-Seneviratne Jul 23, 2025
3910680
Remove unused methods
Isira-Seneviratne Jul 23, 2025
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,6 @@ import android.graphics.Typeface
import android.graphics.drawable.Drawable
import android.net.Uri
import android.os.Bundle
import android.text.format.DateUtils
import android.view.Menu
import android.view.MenuItem
import android.view.View
Expand Down Expand Up @@ -50,6 +49,7 @@ import org.wikipedia.page.LinkMovementMethodExt
import org.wikipedia.richtext.RichTextUtil
import org.wikipedia.settings.NotificationSettingsActivity
import org.wikipedia.settings.Prefs
import org.wikipedia.util.DateUtil
import org.wikipedia.util.DeviceUtil
import org.wikipedia.util.DimenUtil
import org.wikipedia.util.FeedbackUtil
Expand All @@ -64,6 +64,8 @@ import org.wikipedia.views.NotificationActionsOverflowView
import org.wikipedia.views.SearchAndFilterActionProvider
import org.wikipedia.views.SwipeableItemTouchHelperCallback
import org.wikipedia.views.WikiCardView
import kotlin.time.ExperimentalTime
import kotlin.time.toJavaInstant

class NotificationActivity : BaseActivity() {
private lateinit var binding: ActivityNotificationsBinding
Expand Down Expand Up @@ -390,7 +392,8 @@ class NotificationActivity : BaseActivity() {
}
}

binding.notificationTime.text = DateUtils.getRelativeTimeSpanString(n.date().time, System.currentTimeMillis(), 0L)
@OptIn(ExperimentalTime::class)
binding.notificationTime.text = DateUtil.formatRelativeTime(n.instant().toJavaInstant())
binding.notificationTime.setTextColor(if (n.isUnread) primaryColor else inactiveColor)
binding.notificationOverflowMenu.imageTintList = if (n.isUnread) primaryColor else inactiveColor

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@ import org.wikipedia.util.Resource
import org.wikipedia.util.StringUtil
import java.util.Date
import java.util.Random
import kotlin.time.ExperimentalTime

class NotificationViewModel : ViewModel() {

Expand Down Expand Up @@ -47,6 +48,7 @@ class NotificationViewModel : ViewModel() {
_uiState.value = Resource.Success(pair)
}

@OptIn(ExperimentalTime::class)
private fun processList(list: List<Notification>): List<NotificationListItemContainer> {
if (currentContinueStr.isNullOrEmpty()) {
notificationList.clear()
Expand All @@ -57,7 +59,7 @@ class NotificationViewModel : ViewModel() {
}
}
// Sort them by descending date...
notificationList.sortByDescending { it.date() }
notificationList.sortByDescending { it.instant() }

// Filtered the tab selection
val tabSelectedList = notificationList
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -14,15 +14,19 @@ import org.wikipedia.dataclient.WikiSite
import org.wikipedia.dataclient.mwapi.MwException
import org.wikipedia.settings.Prefs
import org.wikipedia.util.log.L
import kotlin.time.ExperimentalTime
import kotlin.time.Instant

class PollNotificationWorker(
private val appContext: Context,
params: WorkerParameters
) : CoroutineWorker(appContext, params) {
@OptIn(ExperimentalTime::class)
override suspend fun doWork(): Result {
return try {
val response = ServiceFactory.get(WikipediaApp.instance.wikiSite).lastUnreadNotification()
val lastNotificationTime = response.query?.notifications?.list?.maxOfOrNull { it.utcIso8601 }.orEmpty()
val lastNotificationTime = response.query?.notifications?.list?.maxOfOrNull { it.instant() }
?: Instant.DISTANT_PAST
if (lastNotificationTime > Prefs.remoteNotificationsSeenTime) {
Prefs.remoteNotificationsSeenTime = lastNotificationTime
retrieveNotifications()
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -11,9 +11,10 @@ import org.wikipedia.Constants
import org.wikipedia.dataclient.WikiSite
import org.wikipedia.json.JsonUtil
import org.wikipedia.page.Namespace
import org.wikipedia.util.DateUtil
import org.wikipedia.util.UriUtil
import java.util.*
import kotlin.time.Clock
import kotlin.time.ExperimentalTime
import kotlin.time.Instant

@Serializable
@Entity(primaryKeys = ["id", "wiki"])
Expand All @@ -28,9 +29,6 @@ class Notification(var id: Long = 0,
var timestamp: Timestamp? = null,
@SerialName("*") var contents: Contents? = null) {

val utcIso8601: String
get() = timestamp?.utciso8601.orEmpty()

val isFromWikidata: Boolean
get() = wiki == Constants.WIKIDATA_DB_NAME

Expand All @@ -40,8 +38,9 @@ class Notification(var id: Long = 0,
return id + wiki.hashCode()
}

fun date(): Date {
return timestamp?.date() ?: Date()
@OptIn(ExperimentalTime::class)
fun instant(): Instant {
return timestamp?.instant ?: Clock.System.now()
}

override fun toString(): String {
Expand Down Expand Up @@ -69,14 +68,8 @@ class Notification(var id: Long = 0,
}

@Serializable
class Timestamp {

val utciso8601: String? = null

fun date(): Date {
return DateUtil.iso8601DateParse(utciso8601!!)
}
}
@OptIn(ExperimentalTime::class)
class Timestamp(@SerialName("utciso8601") val instant: Instant)

@Serializable
class Link {
Expand Down
12 changes: 9 additions & 3 deletions app/src/main/java/org/wikipedia/settings/Prefs.kt
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,8 @@ import org.wikipedia.util.ReleaseUtil.isDevRelease
import org.wikipedia.util.StringUtil
import org.wikipedia.watchlist.WatchlistFilterTypes
import java.util.Date
import kotlin.time.ExperimentalTime
import kotlin.time.Instant

/** Shared preferences utility for convenient POJO access. */
object Prefs {
Expand Down Expand Up @@ -373,9 +375,13 @@ object Prefs {
get() = PrefsIoUtil.getBoolean(R.string.preference_key_reading_lists_first_time_sync, true)
set(value) = PrefsIoUtil.setBoolean(R.string.preference_key_reading_lists_first_time_sync, value)

var remoteNotificationsSeenTime
get() = PrefsIoUtil.getString(R.string.preference_key_remote_notifications_seen_time, "").orEmpty()
set(seenTime) = PrefsIoUtil.setString(R.string.preference_key_remote_notifications_seen_time, seenTime)
@OptIn(ExperimentalTime::class)
var remoteNotificationsSeenTime: Instant
get() {
val timestamp = PrefsIoUtil.getString(R.string.preference_key_remote_notifications_seen_time, "")!!
return Instant.parseOrNull(timestamp) ?: Instant.DISTANT_PAST
}
set(seenTime) = PrefsIoUtil.setString(R.string.preference_key_remote_notifications_seen_time, seenTime.toString())

var showHistoryOfflineArticlesToast
get() = PrefsIoUtil.getBoolean(R.string.preference_key_history_offline_articles_toast, true)
Expand Down
21 changes: 7 additions & 14 deletions app/src/main/java/org/wikipedia/util/DateUtil.kt
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ import android.content.Context
import android.icu.text.RelativeDateTimeFormatter
import android.os.Build
import android.text.format.DateFormat
import android.text.format.DateUtils
import org.wikipedia.R
import org.wikipedia.WikipediaApp
import org.wikipedia.extensions.getResources
Expand All @@ -15,9 +16,9 @@ import java.time.LocalDate
import java.time.LocalDateTime
import java.time.ZoneId
import java.time.ZoneOffset
import java.time.ZonedDateTime
import java.time.format.DateTimeFormatter
import java.time.format.FormatStyle
import java.time.temporal.ChronoUnit
import java.time.temporal.TemporalAccessor
import java.util.Calendar
import java.util.Date
Expand Down Expand Up @@ -189,18 +190,10 @@ object DateUtil {
}
}

fun startOfYearInMillis(year: Int, zoneId: ZoneId = ZoneId.systemDefault()): Long {
val localDate = LocalDate.of(year, 1, 1)
return localDate.atStartOfDay(zoneId).toInstant().toEpochMilli()
}

fun endOfYearInMillis(year: Int, zoneId: ZoneId = ZoneId.systemDefault()): Long {
val localDate = LocalDate.of(year, 12, 31)
return localDate.atTime(0, 0, 0).atZone(zoneId).toInstant().toEpochMilli()
}

fun epochMilliToYear(epochMilli: Long, zoneId: ZoneId = ZoneId.systemDefault()): Int {
val zonedDateTime = ZonedDateTime.ofInstant(Instant.ofEpochMilli(epochMilli), zoneId)
return zonedDateTime.year
fun formatRelativeTime(instant: Instant): CharSequence {
val localDate = LocalDate.ofInstant(instant, ZoneId.systemDefault())
val weeks = localDate.until(LocalDate.now(), ChronoUnit.WEEKS)
val minResolution = if (weeks in 1..10) DateUtils.WEEK_IN_MILLIS else 0L
return DateUtils.getRelativeTimeSpanString(instant.toEpochMilli(), System.currentTimeMillis(), minResolution)
}
}
3 changes: 0 additions & 3 deletions gradle/libs.versions.toml
Original file line number Diff line number Diff line change
Expand Up @@ -50,7 +50,6 @@ composeBom = "2025.07.00"
composeActivity = "1.10.1"
composeViewModel = "2.9.2"


[libraries]
android-sdk = { module = "org.maplibre.gl:android-sdk", version.ref = "androidSdk" }
android-plugin-annotation-v9 = { module = "org.maplibre.gl:android-plugin-annotation-v9", version.ref = "androidPluginAnnotationV9" }
Expand Down Expand Up @@ -88,8 +87,6 @@ hamcrest = { module = "org.hamcrest:hamcrest", version.ref = "hamcrest" }
installreferrer = { module = "com.android.installreferrer:installreferrer", version.ref = "installreferrer" }
jsoup = { module = "org.jsoup:jsoup", version.ref = "jsoup" }
junit = { module = "junit:junit", version.ref = "junit" }
kotlin-gradle-plugin = { module = "org.jetbrains.kotlin:kotlin-gradle-plugin", version.ref = "kotlinStdlibJdk8" }
kotlin-serialization = { module = "org.jetbrains.kotlin:kotlin-serialization", version.ref = "kotlinStdlibJdk8" }
kotlin-stdlib-jdk8 = { module = "org.jetbrains.kotlin:kotlin-stdlib-jdk8", version.ref = "kotlinStdlibJdk8" }
kotlinx-coroutines-android = { module = "org.jetbrains.kotlinx:kotlinx-coroutines-android", version.ref = "kotlinCoroutinesVersion" }
kotlinx-coroutines-core = { module = "org.jetbrains.kotlinx:kotlinx-coroutines-core", version.ref = "kotlinCoroutinesVersion" }
Expand Down
Loading