Fix api
This commit is contained in:
parent
163ef6197b
commit
5802c52b97
|
@ -1,10 +0,0 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<project version="4">
|
||||
<component name="RunConfigurationProducerService">
|
||||
<option name="ignoredProducers">
|
||||
<set>
|
||||
<option value="com.android.tools.idea.compose.preview.runconfiguration.ComposePreviewRunConfigurationProducer" />
|
||||
</set>
|
||||
</option>
|
||||
</component>
|
||||
</project>
|
|
@ -4,13 +4,13 @@ plugins {
|
|||
}
|
||||
|
||||
android {
|
||||
compileSdkVersion 30
|
||||
compileSdkVersion 31
|
||||
buildToolsVersion "30.0.3"
|
||||
|
||||
defaultConfig {
|
||||
applicationId "fr.oupson.taotoolbox"
|
||||
minSdkVersion 21
|
||||
targetSdkVersion 30
|
||||
targetSdkVersion 31
|
||||
versionCode 1
|
||||
versionName "0.0.3"
|
||||
testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"
|
||||
|
@ -43,19 +43,17 @@ android {
|
|||
}
|
||||
|
||||
dependencies {
|
||||
|
||||
implementation "org.jetbrains.kotlin:kotlin-stdlib:$kotlin_version"
|
||||
implementation 'androidx.core:core-ktx:1.3.2'
|
||||
implementation 'androidx.appcompat:appcompat:1.2.0'
|
||||
implementation 'com.google.android.material:material:1.3.0'
|
||||
implementation 'androidx.constraintlayout:constraintlayout:2.0.4'
|
||||
implementation 'androidx.core:core-ktx:1.7.0'
|
||||
implementation 'androidx.appcompat:appcompat:1.4.0'
|
||||
implementation 'com.google.android.material:material:1.4.0'
|
||||
implementation 'androidx.constraintlayout:constraintlayout:2.1.2'
|
||||
implementation 'androidx.preference:preference-ktx:1.1.1'
|
||||
testImplementation 'junit:junit:4.13.2'
|
||||
androidTestImplementation 'androidx.test.ext:junit:1.1.2'
|
||||
androidTestImplementation 'androidx.test.espresso:espresso-core:3.3.0'
|
||||
androidTestImplementation 'androidx.test.ext:junit:1.1.3'
|
||||
androidTestImplementation 'androidx.test.espresso:espresso-core:3.4.0'
|
||||
|
||||
implementation 'org.jetbrains.kotlinx:kotlinx-coroutines-core:1.4.3'
|
||||
implementation 'org.jetbrains.kotlinx:kotlinx-coroutines-android:1.4.3'
|
||||
implementation 'org.jetbrains.kotlinx:kotlinx-coroutines-core:1.6.0'
|
||||
implementation 'org.jetbrains.kotlinx:kotlinx-coroutines-android:1.6.0'
|
||||
|
||||
implementation project(":common")
|
||||
implementation 'org.osmdroid:osmdroid-android:6.1.10'
|
||||
|
|
|
@ -2,7 +2,8 @@
|
|||
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
package="fr.oupson.taotoolbox">
|
||||
|
||||
<uses-permission android:name="android.permission.ACCESS_FINE_LOCATION"/>
|
||||
<uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION" />
|
||||
<uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" />
|
||||
<uses-permission android:name="android.permission.INTERNET" />
|
||||
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
|
||||
|
||||
|
@ -15,13 +16,17 @@
|
|||
android:roundIcon="@mipmap/ic_launcher"
|
||||
android:supportsRtl="true"
|
||||
android:theme="@style/Theme.TaoToolbox">
|
||||
<activity android:name=".activities.TaoWidgetConfigurationActivity">
|
||||
<activity
|
||||
android:name=".activities.TaoWidgetConfigurationActivity"
|
||||
android:exported="true">
|
||||
<intent-filter>
|
||||
<action android:name="android.appwidget.action.APPWIDGET_CONFIGURE" />
|
||||
</intent-filter>
|
||||
</activity>
|
||||
|
||||
<receiver android:name=".receivers.TaoWidget">
|
||||
<receiver
|
||||
android:name=".receivers.TaoWidget"
|
||||
android:exported="true">
|
||||
<intent-filter>
|
||||
<action android:name="android.appwidget.action.APPWIDGET_UPDATE" />
|
||||
</intent-filter>
|
||||
|
@ -31,7 +36,9 @@
|
|||
android:resource="@xml/widget_tao_info" />
|
||||
</receiver>
|
||||
|
||||
<activity android:name=".activities.MainActivity">
|
||||
<activity
|
||||
android:name=".activities.MainActivity"
|
||||
android:exported="true">
|
||||
<intent-filter>
|
||||
<action android:name="android.intent.action.MAIN" />
|
||||
|
||||
|
|
|
@ -12,6 +12,7 @@ import android.view.WindowManager
|
|||
import androidx.appcompat.app.AppCompatActivity
|
||||
import androidx.core.app.ActivityCompat
|
||||
import androidx.core.content.ContextCompat
|
||||
import androidx.lifecycle.lifecycleScope
|
||||
import androidx.preference.PreferenceManager
|
||||
import fr.oupson.common.api.TaoRestApi
|
||||
import fr.oupson.common.db.TaoDatabaseHelper
|
||||
|
@ -20,6 +21,7 @@ import fr.oupson.common.db.TaoDatabaseHelper.TaoDatabase.StopEntry
|
|||
import fr.oupson.taotoolbox.BuildConfig
|
||||
import fr.oupson.taotoolbox.R
|
||||
import fr.oupson.taotoolbox.databinding.ActivityMainBinding
|
||||
import fr.oupson.taotoolbox.utils.PolylineDecoder
|
||||
import fr.oupson.taotoolbox.windows.StopInfoWindow
|
||||
import kotlinx.coroutines.*
|
||||
import org.json.JSONArray
|
||||
|
@ -98,7 +100,7 @@ class MainActivity : AppCompatActivity() {
|
|||
|
||||
requestPermissionsIfNecessary()
|
||||
|
||||
GlobalScope.launch(scope) {
|
||||
lifecycleScope.launch(scope) {
|
||||
val helper = TaoDatabaseHelper(this@MainActivity).apply {
|
||||
try {
|
||||
this.checkUpdate()
|
||||
|
@ -241,12 +243,7 @@ class MainActivity : AppCompatActivity() {
|
|||
)
|
||||
}
|
||||
|
||||
val geo = route.getJSONArray("geojson") // TODO DECODE ENCODED ?
|
||||
|
||||
for (i in 0 until geo.length()) {
|
||||
val value = geo.getJSONArray(i)
|
||||
routeLine.addPoint(GeoPoint(value.getDouble(1), value.getDouble(0)))
|
||||
}
|
||||
PolylineDecoder.decodeInto(routeLine, route.getString("geojsonEncoded"), 1)
|
||||
|
||||
binding.map.overlays.add(routeLine)
|
||||
}
|
||||
|
|
|
@ -12,6 +12,7 @@ import android.view.MenuItem
|
|||
import android.view.View
|
||||
import android.widget.AutoCompleteTextView
|
||||
import androidx.appcompat.app.AppCompatActivity
|
||||
import androidx.lifecycle.lifecycleScope
|
||||
import fr.oupson.common.api.TaoRestApi
|
||||
import fr.oupson.common.db.TaoDatabaseHelper
|
||||
import fr.oupson.common.db.TaoDatabaseHelper.TaoDatabase.*
|
||||
|
@ -69,7 +70,7 @@ class TaoWidgetConfigurationActivity : AppCompatActivity() {
|
|||
val appWidgetManager: AppWidgetManager = AppWidgetManager.getInstance(this)
|
||||
val ids =
|
||||
appWidgetManager.getAppWidgetIds(ComponentName(this, TaoWidget::class.java))
|
||||
GlobalScope.launch(Dispatchers.IO) {
|
||||
lifecycleScope.launch(Dispatchers.IO) {
|
||||
for (id in ids) {
|
||||
TaoWidget.updateAppWidget(
|
||||
this@TaoWidgetConfigurationActivity,
|
||||
|
@ -88,7 +89,7 @@ class TaoWidgetConfigurationActivity : AppCompatActivity() {
|
|||
(binding.configSelectLine.editText as? AutoCompleteTextView)?.also { autoCompleteTextView ->
|
||||
autoCompleteTextView.setAdapter(lineAdapter)
|
||||
autoCompleteTextView.setOnItemClickListener { _, _, position, _ ->
|
||||
GlobalScope.launch(Dispatchers.IO) {
|
||||
lifecycleScope.launch(Dispatchers.IO) {
|
||||
linePosition = position
|
||||
directionPosition = -1
|
||||
loadDirectionList(position)
|
||||
|
@ -99,7 +100,7 @@ class TaoWidgetConfigurationActivity : AppCompatActivity() {
|
|||
(binding.configSelectDirection.editText as? AutoCompleteTextView)?.also { directionAutoComplete ->
|
||||
directionAutoComplete.setAdapter(directionAdapter)
|
||||
directionAutoComplete.setOnItemClickListener { _, _, position, _ ->
|
||||
GlobalScope.launch(Dispatchers.IO) {
|
||||
lifecycleScope.launch(Dispatchers.IO) {
|
||||
directionPosition = position
|
||||
stopPosition = -1
|
||||
|
||||
|
@ -120,7 +121,7 @@ class TaoWidgetConfigurationActivity : AppCompatActivity() {
|
|||
save()
|
||||
}
|
||||
|
||||
GlobalScope.launch(Dispatchers.IO) {
|
||||
lifecycleScope.launch(Dispatchers.IO) {
|
||||
db = TaoDatabaseHelper(this@TaoWidgetConfigurationActivity).apply {
|
||||
checkUpdate()
|
||||
withContext(Dispatchers.Main) {
|
||||
|
|
|
@ -7,18 +7,19 @@ import android.view.ViewGroup
|
|||
import android.widget.ImageView
|
||||
import android.widget.TextView
|
||||
import androidx.recyclerview.widget.RecyclerView
|
||||
import fr.oupson.taotoolbox.R
|
||||
import fr.oupson.common.api.LineColors
|
||||
import fr.oupson.common.api.Schedule
|
||||
import fr.oupson.common.api.RealtimeStopArea
|
||||
import fr.oupson.taotoolbox.R
|
||||
import kotlinx.coroutines.Dispatchers
|
||||
import kotlinx.coroutines.GlobalScope
|
||||
import kotlinx.coroutines.launch
|
||||
import kotlinx.coroutines.withContext
|
||||
|
||||
class ScheduleAdapter(
|
||||
private val scheduleList: SimplePtr<Array<Schedule>>
|
||||
// TODO ADAPT
|
||||
class RealTimeAdapter(
|
||||
private val realTimeList: SimplePtr<Array<RealtimeStopArea>>
|
||||
) :
|
||||
RecyclerView.Adapter<ScheduleAdapter.ScheduleViewHolder>() {
|
||||
RecyclerView.Adapter<RealTimeAdapter.RealTimeViewHolder>() {
|
||||
class SimplePtr<T>(private var value: T? = null) {
|
||||
fun get(): T? = value
|
||||
fun set(value: T?) {
|
||||
|
@ -26,21 +27,23 @@ class ScheduleAdapter(
|
|||
}
|
||||
}
|
||||
|
||||
class ScheduleViewHolder(
|
||||
class RealTimeViewHolder(
|
||||
private val view: View
|
||||
) : RecyclerView.ViewHolder(view) {
|
||||
private val scheduleDirectionTextView =
|
||||
view.findViewById<TextView>(R.id.item_schedule_direction_text_view)
|
||||
private val scheduleImageView = view.findViewById<ImageView>(R.id.item_schedule_line_image_view)
|
||||
private val scheduleNextTextView = view.findViewById<TextView>(R.id.item_schedule_next_text_view)
|
||||
private val scheduleImageView =
|
||||
view.findViewById<ImageView>(R.id.item_schedule_line_image_view)
|
||||
private val scheduleNextTextView =
|
||||
view.findViewById<TextView>(R.id.item_schedule_next_text_view)
|
||||
private val scheduleAfterTextView =
|
||||
view.findViewById<TextView>(R.id.item_schedule_after_text_view)
|
||||
|
||||
fun bind(schedule: Schedule) {
|
||||
fun bind(schedule: RealtimeStopArea) {
|
||||
scheduleDirectionTextView.text = view.context.getString(
|
||||
R.string.line_and_direction_name,
|
||||
schedule.lineColors.lineCode,
|
||||
schedule.lineDirectionName
|
||||
schedule.routeName
|
||||
)
|
||||
|
||||
scheduleNextTextView.text =
|
||||
|
@ -50,7 +53,6 @@ class ScheduleAdapter(
|
|||
schedule.timeRemainingAfter() ?: "∅"
|
||||
)
|
||||
|
||||
|
||||
GlobalScope.launch(Dispatchers.Default) {
|
||||
val btm = LineColors.getLineBtm(
|
||||
view.context,
|
||||
|
@ -67,16 +69,16 @@ class ScheduleAdapter(
|
|||
}
|
||||
}
|
||||
|
||||
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): ScheduleViewHolder {
|
||||
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): RealTimeViewHolder {
|
||||
val inflater = LayoutInflater.from(parent.context)
|
||||
return ScheduleViewHolder(inflater.inflate(R.layout.item_schedule, parent, false))
|
||||
return RealTimeViewHolder(inflater.inflate(R.layout.item_schedule, parent, false))
|
||||
}
|
||||
|
||||
override fun onBindViewHolder(holder: ScheduleViewHolder, position: Int) {
|
||||
val ref = scheduleList.get()
|
||||
override fun onBindViewHolder(holder: RealTimeViewHolder, position: Int) {
|
||||
val ref = realTimeList.get()
|
||||
if (ref != null)
|
||||
holder.bind(ref[position])
|
||||
}
|
||||
|
||||
override fun getItemCount(): Int = scheduleList.get()?.size ?: 0
|
||||
override fun getItemCount(): Int = realTimeList.get()?.size ?: 0
|
||||
}
|
|
@ -7,6 +7,7 @@ import android.content.Context
|
|||
import android.content.Intent
|
||||
import android.graphics.*
|
||||
import android.net.Uri
|
||||
import android.os.Build
|
||||
import android.util.Log
|
||||
import android.widget.RemoteViews
|
||||
import fr.oupson.common.api.LineColors
|
||||
|
@ -37,12 +38,18 @@ class TaoWidget : AppWidgetProvider() {
|
|||
serviceIntent.putExtra(AppWidgetManager.EXTRA_APPWIDGET_IDS, intArrayOf(appWidgetId))
|
||||
serviceIntent.data = Uri.parse(serviceIntent.toUri(Intent.URI_INTENT_SCHEME))
|
||||
|
||||
val pending = PendingIntent.getBroadcast(
|
||||
val pending =
|
||||
PendingIntent.getBroadcast(
|
||||
context,
|
||||
appWidgetId,
|
||||
serviceIntent,
|
||||
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
|
||||
PendingIntent.FLAG_UPDATE_CURRENT or PendingIntent.FLAG_IMMUTABLE
|
||||
} else {
|
||||
PendingIntent.FLAG_UPDATE_CURRENT
|
||||
}
|
||||
)
|
||||
|
||||
views.setOnClickPendingIntent(R.id.tao_widget_root, pending)
|
||||
|
||||
try {
|
||||
|
|
|
@ -0,0 +1,37 @@
|
|||
package fr.oupson.taotoolbox.utils;
|
||||
|
||||
|
||||
import org.osmdroid.util.GeoPoint;
|
||||
import org.osmdroid.views.overlay.Polyline;
|
||||
|
||||
public class PolylineDecoder {
|
||||
public static void decodeInto(Polyline line, String encodedString, int precision) {
|
||||
int index = 0;
|
||||
int len = encodedString.length();
|
||||
int lat = 0, lng = 0;
|
||||
|
||||
while (index < len) {
|
||||
int b, shift, result;
|
||||
shift = result = 0;
|
||||
do {
|
||||
b = encodedString.charAt(index++) - 63;
|
||||
result |= (b & 0x1f) << shift;
|
||||
shift += 5;
|
||||
} while (b >= 0x20);
|
||||
int dlat = ((result & 1) != 0 ? ~(result >> 1) : (result >> 1));
|
||||
lat += dlat;
|
||||
|
||||
shift = result = 0;
|
||||
do {
|
||||
b = encodedString.charAt(index++) - 63;
|
||||
result |= (b & 0x1f) << shift;
|
||||
shift += 5;
|
||||
} while (b >= 0x20);
|
||||
int dlng = ((result & 1) != 0 ? ~(result >> 1) : (result >> 1));
|
||||
lng += dlng;
|
||||
|
||||
GeoPoint p = new GeoPoint(((double) (lng * precision)) / 1.0e6, ((double) (lat * precision)) / 1.0e6, 0);
|
||||
line.addPoint(p);
|
||||
}
|
||||
}
|
||||
}
|
|
@ -3,10 +3,10 @@ package fr.oupson.taotoolbox.windows
|
|||
import android.widget.TextView
|
||||
import androidx.recyclerview.widget.LinearLayoutManager
|
||||
import androidx.recyclerview.widget.RecyclerView
|
||||
import fr.oupson.taotoolbox.R
|
||||
import fr.oupson.taotoolbox.adapters.ScheduleAdapter
|
||||
import fr.oupson.common.api.Schedule
|
||||
import fr.oupson.common.api.RealtimeStopArea
|
||||
import fr.oupson.common.api.TaoRestApi
|
||||
import fr.oupson.taotoolbox.R
|
||||
import fr.oupson.taotoolbox.adapters.RealTimeAdapter
|
||||
import kotlinx.coroutines.*
|
||||
import org.osmdroid.views.MapView
|
||||
import org.osmdroid.views.overlay.Marker
|
||||
|
@ -21,13 +21,13 @@ class StopInfoWindow(
|
|||
|
||||
private val titleTextView: TextView by lazy { view.findViewById(R.id.window_stop_info_title_text_view) }
|
||||
|
||||
private val scheduleList: ScheduleAdapter.SimplePtr<Array<Schedule>> by lazy {
|
||||
ScheduleAdapter.SimplePtr(
|
||||
private val realtimeList: RealTimeAdapter.SimplePtr<Array<RealtimeStopArea>> by lazy {
|
||||
RealTimeAdapter.SimplePtr(
|
||||
null
|
||||
)
|
||||
}
|
||||
|
||||
private val adapter: ScheduleAdapter by lazy { ScheduleAdapter(scheduleList) }
|
||||
private val adapter: RealTimeAdapter by lazy { RealTimeAdapter(realtimeList) }
|
||||
private val recyclerView: RecyclerView by lazy {
|
||||
view.findViewById<RecyclerView>(R.id.window_stop_info_schedule_recycler_view).also {
|
||||
it.adapter = adapter
|
||||
|
@ -36,7 +36,7 @@ class StopInfoWindow(
|
|||
}
|
||||
|
||||
override fun onOpen(item: Any?) {
|
||||
scheduleList.set(null)
|
||||
realtimeList.set(null)
|
||||
recyclerView.adapter?.notifyDataSetChanged()
|
||||
|
||||
if (item is Marker) {
|
||||
|
@ -44,10 +44,10 @@ class StopInfoWindow(
|
|||
titleTextView.text = item.title
|
||||
|
||||
GlobalScope.launch(windowsContext) {
|
||||
val schedule = taoRestApi.getSchedule(id)
|
||||
val realtime = taoRestApi.getRealtimeByStopArea(id)
|
||||
|
||||
withContext(Dispatchers.Main) {
|
||||
scheduleList.set(schedule)
|
||||
realtimeList.set(realtime)
|
||||
adapter.notifyDataSetChanged()
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,13 +1,13 @@
|
|||
// Top-level build file where you can add configuration options common to all sub-projects/modules.
|
||||
buildscript {
|
||||
ext.kotlin_version = "1.5.0"
|
||||
ext.ktor_version = "1.5.3"
|
||||
ext.kotlin_version = "1.6.10"
|
||||
ext.ktor_version = "1.6.3"
|
||||
repositories {
|
||||
google()
|
||||
mavenCentral()
|
||||
}
|
||||
dependencies {
|
||||
classpath 'com.android.tools.build:gradle:4.2.0'
|
||||
classpath 'com.android.tools.build:gradle:7.0.4'
|
||||
classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlin_version"
|
||||
|
||||
// NOTE: Do not place your application dependencies here; they belong
|
||||
|
|
|
@ -1,18 +1,16 @@
|
|||
plugins {
|
||||
id 'com.android.library'
|
||||
id 'kotlin-android'
|
||||
id 'org.jetbrains.kotlin.plugin.serialization' version '1.4.30'
|
||||
id 'org.jetbrains.kotlin.plugin.serialization' version '1.5.30'
|
||||
}
|
||||
|
||||
android {
|
||||
compileSdkVersion 30
|
||||
compileSdkVersion 31
|
||||
buildToolsVersion "30.0.3"
|
||||
|
||||
defaultConfig {
|
||||
minSdkVersion 21
|
||||
targetSdkVersion 30
|
||||
versionCode 1
|
||||
versionName "1.0"
|
||||
targetSdkVersion 31
|
||||
|
||||
testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"
|
||||
consumerProguardFiles "consumer-rules.pro"
|
||||
|
@ -34,14 +32,13 @@ android {
|
|||
}
|
||||
|
||||
dependencies {
|
||||
implementation "org.jetbrains.kotlin:kotlin-stdlib:$kotlin_version"
|
||||
implementation 'androidx.core:core-ktx:1.3.2'
|
||||
implementation 'androidx.appcompat:appcompat:1.2.0'
|
||||
implementation 'com.google.android.material:material:1.3.0'
|
||||
implementation 'androidx.core:core-ktx:1.7.0'
|
||||
implementation 'androidx.appcompat:appcompat:1.4.0'
|
||||
implementation 'com.google.android.material:material:1.4.0'
|
||||
testImplementation 'junit:junit:4.13.2'
|
||||
androidTestImplementation 'androidx.test.ext:junit:1.1.2'
|
||||
androidTestImplementation 'androidx.test.espresso:espresso-core:3.3.0'
|
||||
implementation "org.jetbrains.kotlinx:kotlinx-serialization-json:1.1.0"
|
||||
androidTestImplementation 'androidx.test.ext:junit:1.1.3'
|
||||
androidTestImplementation 'androidx.test.espresso:espresso-core:3.4.0'
|
||||
implementation "org.jetbrains.kotlinx:kotlinx-serialization-json:1.3.2"
|
||||
|
||||
implementation "io.ktor:ktor-client-serialization:$ktor_version"
|
||||
implementation "io.ktor:ktor-client-core:$ktor_version"
|
||||
|
|
|
@ -130,7 +130,10 @@ object DateAsStringSerializer : KSerializer<Date> {
|
|||
SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss.SSSX", Locale.getDefault()).parse(string)!!
|
||||
} else { // Z format is not supported :/
|
||||
val newDateStr = if (string.endsWith("Z")) {
|
||||
string.substring(0, string.length - 1) + "+0000" // Little trick to get time in correct time zone
|
||||
string.substring(
|
||||
0,
|
||||
string.length - 1
|
||||
) + "+0000" // Little trick to get time in correct time zone
|
||||
} else {
|
||||
throw Exception("$string is not supported") // TODO ?
|
||||
}
|
||||
|
@ -165,3 +168,64 @@ data class Schedule(
|
|||
(it.time - Date().time) / (1000 * 60)
|
||||
}
|
||||
}
|
||||
|
||||
@Serializable
|
||||
data class RealtimeStopArea(
|
||||
val lineId: String,
|
||||
val lineCode: String,
|
||||
val lineColors: LineColors,
|
||||
val routeId: String,
|
||||
val routeName: String,
|
||||
val lineIsTAD: Boolean,
|
||||
val nextPassages: Array<NextPassage>,
|
||||
val summaryStatus: String?
|
||||
) {
|
||||
fun timeRemaining(): Long? =
|
||||
nextPassages.getOrNull(0)?.let {
|
||||
(it.date!!.time - Date().time) / (1000 * 60)
|
||||
}
|
||||
|
||||
fun timeRemainingAfter(): Long? =
|
||||
nextPassages.getOrNull(1)?.let {
|
||||
(it.date!!.time - Date().time) / (1000 * 60)
|
||||
}
|
||||
|
||||
override fun equals(other: Any?): Boolean {
|
||||
if (this === other) return true
|
||||
if (javaClass != other?.javaClass) return false
|
||||
|
||||
other as RealtimeStopArea
|
||||
|
||||
if (lineId != other.lineId) return false
|
||||
if (lineCode != other.lineCode) return false
|
||||
if (lineColors != other.lineColors) return false
|
||||
if (routeId != other.routeId) return false
|
||||
if (routeName != other.routeName) return false
|
||||
if (lineIsTAD != other.lineIsTAD) return false
|
||||
if (!nextPassages.contentEquals(other.nextPassages)) return false
|
||||
if (summaryStatus != other.summaryStatus) return false
|
||||
|
||||
return true
|
||||
}
|
||||
|
||||
override fun hashCode(): Int {
|
||||
var result = lineId.hashCode()
|
||||
result = 31 * result + lineCode.hashCode()
|
||||
result = 31 * result + lineColors.hashCode()
|
||||
result = 31 * result + routeId.hashCode()
|
||||
result = 31 * result + routeName.hashCode()
|
||||
result = 31 * result + lineIsTAD.hashCode()
|
||||
result = 31 * result + nextPassages.contentHashCode()
|
||||
result = 31 * result + (summaryStatus?.hashCode() ?: 0)
|
||||
return result
|
||||
}
|
||||
}
|
||||
|
||||
@Serializable
|
||||
data class NextPassage(
|
||||
@Serializable(with = DateAsStringSerializer::class)
|
||||
val date: Date?,
|
||||
val vehicleId: String,
|
||||
val loadPrediction: String?, // TODO
|
||||
val isLiveData: Boolean
|
||||
)
|
||||
|
|
|
@ -3,6 +3,7 @@ package fr.oupson.common.api
|
|||
import io.ktor.client.*
|
||||
import io.ktor.client.engine.android.*
|
||||
import io.ktor.client.features.json.*
|
||||
import io.ktor.client.features.json.serializer.*
|
||||
import io.ktor.client.request.*
|
||||
import io.ktor.client.request.forms.*
|
||||
import io.ktor.http.*
|
||||
|
@ -12,7 +13,9 @@ import kotlin.coroutines.CoroutineContext
|
|||
|
||||
class TaoRestApi(private val httpClient: HttpClient) {
|
||||
constructor() : this(HttpClient(Android) {
|
||||
install(JsonFeature)
|
||||
install(JsonFeature) {
|
||||
serializer = KotlinxSerializer(kotlinx.serialization.json.Json { ignoreUnknownKeys = true })
|
||||
}
|
||||
engine {
|
||||
connectTimeout = 10_1000
|
||||
socketTimeout = 10_000
|
||||
|
@ -69,9 +72,24 @@ class TaoRestApi(private val httpClient: HttpClient) {
|
|||
}, true) {}
|
||||
}
|
||||
|
||||
suspend fun getRealtimeByStopArea(stopAreaId: String, limit: Int? = null, includeLoadPrediction: Boolean? = null) : Array<RealtimeStopArea> = withContext(Dispatchers.IO) {
|
||||
httpClient.submitForm("https://navigorleans.c-t.io/api/3.0/realtime/byStopArea", Parameters.build {
|
||||
append(
|
||||
"stopAreaId", stopAreaId
|
||||
)
|
||||
if (limit != null) {
|
||||
append("limit", limit.toString())
|
||||
}
|
||||
|
||||
if (includeLoadPrediction != null) {
|
||||
append("includeLoadPrediction", includeLoadPrediction.toString())
|
||||
}
|
||||
}, true) {}
|
||||
}
|
||||
|
||||
suspend fun getTaoGeoJson(
|
||||
lineId: String
|
||||
): String = withContext(requestContext) {
|
||||
httpClient.get("$baseUrl/2.0/lines/$lineId/geojson")
|
||||
httpClient.get("$baseUrl/2.0/lines/$lineId/geojson/encoded")
|
||||
}
|
||||
}
|
|
@ -3,4 +3,4 @@ distributionBase=GRADLE_USER_HOME
|
|||
distributionPath=wrapper/dists
|
||||
zipStoreBase=GRADLE_USER_HOME
|
||||
zipStorePath=wrapper/dists
|
||||
distributionUrl=https\://services.gradle.org/distributions/gradle-6.7.1-bin.zip
|
||||
distributionUrl=https\://services.gradle.org/distributions/gradle-7.0.2-bin.zip
|
||||
|
|
|
@ -33,16 +33,15 @@ android {
|
|||
}
|
||||
|
||||
dependencies {
|
||||
implementation "org.jetbrains.kotlin:kotlin-stdlib:$kotlin_version"
|
||||
implementation 'org.jetbrains.kotlinx:kotlinx-coroutines-android:1.4.3'
|
||||
implementation 'org.jetbrains.kotlinx:kotlinx-coroutines-android:1.5.0'
|
||||
implementation 'org.jetbrains.kotlinx:kotlinx-coroutines-guava:1.4.2'
|
||||
implementation 'androidx.core:core-ktx:1.3.2'
|
||||
implementation 'androidx.appcompat:appcompat:1.2.0'
|
||||
implementation 'com.google.android.material:material:1.3.0'
|
||||
implementation 'androidx.constraintlayout:constraintlayout:2.0.4'
|
||||
implementation 'androidx.core:core-ktx:1.6.0'
|
||||
implementation 'androidx.appcompat:appcompat:1.3.1'
|
||||
implementation 'com.google.android.material:material:1.4.0'
|
||||
implementation 'androidx.constraintlayout:constraintlayout:2.1.0'
|
||||
testImplementation 'junit:junit:4.13.2'
|
||||
androidTestImplementation 'androidx.test.ext:junit:1.1.2'
|
||||
androidTestImplementation 'androidx.test.espresso:espresso-core:3.3.0'
|
||||
androidTestImplementation 'androidx.test.ext:junit:1.1.3'
|
||||
androidTestImplementation 'androidx.test.espresso:espresso-core:3.4.0'
|
||||
implementation 'androidx.wear:wear:1.1.0'
|
||||
implementation "androidx.wear:wear-tiles:1.0.0-alpha01"
|
||||
debugImplementation "androidx.wear:wear-tiles-renderer:1.0.0-alpha01"
|
||||
|
|
Loading…
Reference in New Issue