mirror of
https://github.com/screentinker/screentinker.git
synced 2026-06-20 05:02:54 -06:00
Each playlist item can carry schedule blocks (active days, start/end time-of-day, optional start/end dates). An item plays when the screen's local "now" matches at least one block; an item with no blocks always plays. #74 covers time-of-day/day-of-week windows including overnight wrap; #75 covers inclusive date ranges (auto-expiry). Evaluation is on-device, so dayparting and expiry work offline. - Shared evaluator contract: shared/schedule-vectors.json (39 vectors — DST US+AU, overnight-wrap anchoring, timezone correctness, date boundaries). Canonical JS evaluator in server/lib/schedule-eval.js; Kotlin and Tizen ports kept in lockstep by drift guards (Tizen byte-diff test, Kotlin JUnit reads the shared JSON, new android-test CI job). - All three players (web, Android, Tizen) filter by schedule against their own clock, idle with a "Nothing scheduled" message + 30s re-check when everything is filtered, and fail open on any evaluator error. - Editor: per-item schedule modal + row badge in the playlist editor; client validation mirrors the server; editing marks the playlist draft. - Part B (behaviour change): device/group schedule overrides now evaluate in each device's effective timezone instead of server-local time. - Device detail shows the reported timezone + a clock-skew warning. - i18n for en/es/fr/de/pt across all new strings (namespaced itemsched.* to avoid colliding with the device-schedule calendar's schedule.*). - CHANGELOG documents the feature, the Part B change, the fail-open guarantee, and the scheduled-single-video re-render tradeoff. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
90 lines
2.9 KiB
Plaintext
90 lines
2.9 KiB
Plaintext
plugins {
|
|
id("com.android.application")
|
|
id("org.jetbrains.kotlin.android")
|
|
}
|
|
|
|
android {
|
|
namespace = "com.remotedisplay.player"
|
|
compileSdk = 34
|
|
|
|
defaultConfig {
|
|
applicationId = "com.remotedisplay.player"
|
|
minSdk = 26
|
|
targetSdk = 34
|
|
versionCode = 19
|
|
versionName = "1.8.3"
|
|
}
|
|
|
|
signingConfigs {
|
|
create("release") {
|
|
storeFile = file("../release-key.jks")
|
|
storePassword = System.getenv("KEYSTORE_PASSWORD") ?: findProperty("KEYSTORE_PASSWORD") as String? ?: ""
|
|
keyAlias = System.getenv("KEY_ALIAS") ?: findProperty("KEY_ALIAS") as String? ?: "remotedisplay"
|
|
keyPassword = System.getenv("KEY_PASSWORD") ?: findProperty("KEY_PASSWORD") as String? ?: ""
|
|
}
|
|
}
|
|
|
|
buildTypes {
|
|
debug {
|
|
signingConfig = signingConfigs.getByName("release")
|
|
}
|
|
release {
|
|
isMinifyEnabled = false
|
|
signingConfig = signingConfigs.getByName("release")
|
|
proguardFiles(getDefaultProguardFile("proguard-android-optimize.txt"), "proguard-rules.pro")
|
|
}
|
|
}
|
|
|
|
compileOptions {
|
|
sourceCompatibility = JavaVersion.VERSION_17
|
|
targetCompatibility = JavaVersion.VERSION_17
|
|
}
|
|
|
|
kotlinOptions {
|
|
jvmTarget = "17"
|
|
}
|
|
}
|
|
|
|
dependencies {
|
|
// AndroidX
|
|
implementation("androidx.core:core-ktx:1.12.0")
|
|
implementation("androidx.appcompat:appcompat:1.6.1")
|
|
implementation("com.google.android.material:material:1.11.0")
|
|
implementation("androidx.constraintlayout:constraintlayout:2.1.4")
|
|
implementation("androidx.lifecycle:lifecycle-runtime-ktx:2.7.0")
|
|
implementation("androidx.lifecycle:lifecycle-service:2.7.0")
|
|
|
|
// Encrypted SharedPreferences
|
|
implementation("androidx.security:security-crypto:1.1.0-alpha06")
|
|
|
|
// ExoPlayer / Media3
|
|
implementation("androidx.media3:media3-exoplayer:1.2.1")
|
|
implementation("androidx.media3:media3-ui:1.2.1")
|
|
|
|
// Socket.IO client
|
|
implementation("io.socket:socket.io-client:2.1.0")
|
|
|
|
// WorkManager for background downloads
|
|
implementation("androidx.work:work-runtime-ktx:2.9.0")
|
|
|
|
// Gson for JSON
|
|
implementation("com.google.code.gson:gson:2.10.1")
|
|
|
|
// OkHttp for file downloads
|
|
implementation("com.squareup.okhttp3:okhttp:4.12.0")
|
|
|
|
// Coroutines
|
|
implementation("org.jetbrains.kotlinx:kotlinx-coroutines-android:1.7.3")
|
|
|
|
// #74/#75: unit tests for the Kotlin schedule evaluator (vector drift guard)
|
|
testImplementation("junit:junit:4.13.2")
|
|
}
|
|
|
|
// #74/#75: point the evaluator drift-guard test at the SHARED vector contract
|
|
// (shared/schedule-vectors.json, the single source - no snapshot). rootProject is
|
|
// the android/ Gradle root; its parent is the repo root. Any ScheduleEval.kt edit
|
|
// that breaks a vector fails ScheduleEvalTest in CI.
|
|
tasks.withType<Test> {
|
|
systemProperty("scheduleVectors", File(rootProject.projectDir.parentFile, "shared/schedule-vectors.json").absolutePath)
|
|
}
|