Add X-Timezone header to all API requests
Send the device's IANA timezone identifier (e.g., "America/Los_Angeles") with every API request to enable timezone-aware overdue task detection. Platform implementations: - Android/JVM: TimeZone.getDefault().id - iOS: NSTimeZone.localTimeZone.name - JS/WASM: Intl.DateTimeFormat().resolvedOptions().timeZone 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
This commit is contained in:
@@ -8,6 +8,7 @@ import io.ktor.client.plugins.logging.*
|
|||||||
import io.ktor.serialization.kotlinx.json.*
|
import io.ktor.serialization.kotlinx.json.*
|
||||||
import kotlinx.serialization.json.Json
|
import kotlinx.serialization.json.Json
|
||||||
import java.util.Locale
|
import java.util.Locale
|
||||||
|
import java.util.TimeZone
|
||||||
|
|
||||||
actual fun getLocalhostAddress(): String = "10.0.2.2"
|
actual fun getLocalhostAddress(): String = "10.0.2.2"
|
||||||
|
|
||||||
@@ -15,6 +16,10 @@ actual fun getDeviceLanguage(): String {
|
|||||||
return Locale.getDefault().language
|
return Locale.getDefault().language
|
||||||
}
|
}
|
||||||
|
|
||||||
|
actual fun getDeviceTimezone(): String {
|
||||||
|
return TimeZone.getDefault().id
|
||||||
|
}
|
||||||
|
|
||||||
actual fun createHttpClient(): HttpClient {
|
actual fun createHttpClient(): HttpClient {
|
||||||
return HttpClient(OkHttp) {
|
return HttpClient(OkHttp) {
|
||||||
install(ContentNegotiation) {
|
install(ContentNegotiation) {
|
||||||
@@ -32,6 +37,7 @@ actual fun createHttpClient(): HttpClient {
|
|||||||
|
|
||||||
install(DefaultRequest) {
|
install(DefaultRequest) {
|
||||||
headers.append("Accept-Language", getDeviceLanguage())
|
headers.append("Accept-Language", getDeviceLanguage())
|
||||||
|
headers.append("X-Timezone", getDeviceTimezone())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -16,6 +16,13 @@ expect fun createHttpClient(): HttpClient
|
|||||||
*/
|
*/
|
||||||
expect fun getDeviceLanguage(): String
|
expect fun getDeviceLanguage(): String
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get the device's timezone identifier (e.g., "America/Los_Angeles", "Europe/London").
|
||||||
|
* This is used to set the X-Timezone header for API requests
|
||||||
|
* so the server can calculate overdue tasks correctly based on the user's local time.
|
||||||
|
*/
|
||||||
|
expect fun getDeviceTimezone(): String
|
||||||
|
|
||||||
object ApiClient {
|
object ApiClient {
|
||||||
val httpClient = createHttpClient()
|
val httpClient = createHttpClient()
|
||||||
|
|
||||||
|
|||||||
@@ -8,6 +8,7 @@ import io.ktor.client.plugins.logging.*
|
|||||||
import io.ktor.serialization.kotlinx.json.*
|
import io.ktor.serialization.kotlinx.json.*
|
||||||
import kotlinx.serialization.json.Json
|
import kotlinx.serialization.json.Json
|
||||||
import platform.Foundation.NSLocale
|
import platform.Foundation.NSLocale
|
||||||
|
import platform.Foundation.NSTimeZone
|
||||||
import platform.Foundation.preferredLanguages
|
import platform.Foundation.preferredLanguages
|
||||||
|
|
||||||
actual fun getLocalhostAddress(): String = "127.0.0.1"
|
actual fun getLocalhostAddress(): String = "127.0.0.1"
|
||||||
@@ -19,6 +20,10 @@ actual fun getDeviceLanguage(): String {
|
|||||||
return firstLanguage?.split("-")?.firstOrNull() ?: "en"
|
return firstLanguage?.split("-")?.firstOrNull() ?: "en"
|
||||||
}
|
}
|
||||||
|
|
||||||
|
actual fun getDeviceTimezone(): String {
|
||||||
|
return NSTimeZone.localTimeZone.name
|
||||||
|
}
|
||||||
|
|
||||||
actual fun createHttpClient(): HttpClient {
|
actual fun createHttpClient(): HttpClient {
|
||||||
return HttpClient(Darwin) {
|
return HttpClient(Darwin) {
|
||||||
install(ContentNegotiation) {
|
install(ContentNegotiation) {
|
||||||
@@ -36,6 +41,7 @@ actual fun createHttpClient(): HttpClient {
|
|||||||
|
|
||||||
install(DefaultRequest) {
|
install(DefaultRequest) {
|
||||||
headers.append("Accept-Language", getDeviceLanguage())
|
headers.append("Accept-Language", getDeviceLanguage())
|
||||||
|
headers.append("X-Timezone", getDeviceTimezone())
|
||||||
}
|
}
|
||||||
|
|
||||||
engine {
|
engine {
|
||||||
|
|||||||
@@ -15,6 +15,11 @@ actual fun getDeviceLanguage(): String {
|
|||||||
return window.navigator.language.split("-").firstOrNull() ?: "en"
|
return window.navigator.language.split("-").firstOrNull() ?: "en"
|
||||||
}
|
}
|
||||||
|
|
||||||
|
actual fun getDeviceTimezone(): String {
|
||||||
|
// Use Intl API to get IANA timezone name (e.g., "America/Los_Angeles")
|
||||||
|
return js("Intl.DateTimeFormat().resolvedOptions().timeZone") as String
|
||||||
|
}
|
||||||
|
|
||||||
actual fun createHttpClient(): HttpClient {
|
actual fun createHttpClient(): HttpClient {
|
||||||
return HttpClient(Js) {
|
return HttpClient(Js) {
|
||||||
install(ContentNegotiation) {
|
install(ContentNegotiation) {
|
||||||
@@ -32,6 +37,7 @@ actual fun createHttpClient(): HttpClient {
|
|||||||
|
|
||||||
install(DefaultRequest) {
|
install(DefaultRequest) {
|
||||||
headers.append("Accept-Language", getDeviceLanguage())
|
headers.append("Accept-Language", getDeviceLanguage())
|
||||||
|
headers.append("X-Timezone", getDeviceTimezone())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -8,6 +8,7 @@ import io.ktor.client.plugins.logging.*
|
|||||||
import io.ktor.serialization.kotlinx.json.*
|
import io.ktor.serialization.kotlinx.json.*
|
||||||
import kotlinx.serialization.json.Json
|
import kotlinx.serialization.json.Json
|
||||||
import java.util.Locale
|
import java.util.Locale
|
||||||
|
import java.util.TimeZone
|
||||||
|
|
||||||
actual fun getLocalhostAddress(): String = "127.0.0.1"
|
actual fun getLocalhostAddress(): String = "127.0.0.1"
|
||||||
|
|
||||||
@@ -15,6 +16,10 @@ actual fun getDeviceLanguage(): String {
|
|||||||
return Locale.getDefault().language
|
return Locale.getDefault().language
|
||||||
}
|
}
|
||||||
|
|
||||||
|
actual fun getDeviceTimezone(): String {
|
||||||
|
return TimeZone.getDefault().id
|
||||||
|
}
|
||||||
|
|
||||||
actual fun createHttpClient(): HttpClient {
|
actual fun createHttpClient(): HttpClient {
|
||||||
return HttpClient(CIO) {
|
return HttpClient(CIO) {
|
||||||
install(ContentNegotiation) {
|
install(ContentNegotiation) {
|
||||||
@@ -32,6 +37,7 @@ actual fun createHttpClient(): HttpClient {
|
|||||||
|
|
||||||
install(DefaultRequest) {
|
install(DefaultRequest) {
|
||||||
headers.append("Accept-Language", getDeviceLanguage())
|
headers.append("Accept-Language", getDeviceLanguage())
|
||||||
|
headers.append("X-Timezone", getDeviceTimezone())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -15,6 +15,11 @@ actual fun getDeviceLanguage(): String {
|
|||||||
return window.navigator.language.split("-").firstOrNull() ?: "en"
|
return window.navigator.language.split("-").firstOrNull() ?: "en"
|
||||||
}
|
}
|
||||||
|
|
||||||
|
actual fun getDeviceTimezone(): String {
|
||||||
|
// Use Intl API to get IANA timezone name (e.g., "America/Los_Angeles")
|
||||||
|
return js("Intl.DateTimeFormat().resolvedOptions().timeZone") as String
|
||||||
|
}
|
||||||
|
|
||||||
actual fun createHttpClient(): HttpClient {
|
actual fun createHttpClient(): HttpClient {
|
||||||
return HttpClient(Js) {
|
return HttpClient(Js) {
|
||||||
install(ContentNegotiation) {
|
install(ContentNegotiation) {
|
||||||
@@ -32,6 +37,7 @@ actual fun createHttpClient(): HttpClient {
|
|||||||
|
|
||||||
install(DefaultRequest) {
|
install(DefaultRequest) {
|
||||||
headers.append("Accept-Language", getDeviceLanguage())
|
headers.append("Accept-Language", getDeviceLanguage())
|
||||||
|
headers.append("X-Timezone", getDeviceTimezone())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user