38 Commits 85b568971d ... 5ffcc3afdf

Autor SHA1 Mensaje Fecha
  Adam Evyčędo 85b568971d merge develop into master for version 3.10.0-alpha.1 hace 5 meses
  Adam Evyčędo 9ce882a2d0 release version 3.10.0-alpha.1 (39) hace 5 meses
  Adam Evyčędo e02c5a418c show only unique results around location hace 5 meses
  Adam Evyčędo 0b843d4a7f bring Transitous departures back hace 5 meses
  Adam Evyčędo 50069357e5 merge develop into master for version 3.10.0-alpha hace 5 meses
  Adam Evyčędo 2bf759f77f release version 3.10.0-alpha (38) hace 5 meses
  Adam Evyčędo 0164e10f7b revert gradle plugin version hace 5 meses
  Adam Evyčędo 83a2798738 catch new exceptions when requesting departures hace 5 meses
  Adam Evyčędo 57f8c5d914 fix saving favourites hace 5 meses
  Adam Evyčędo 09c9c20f90 Merge branch 'translations' into develop hace 5 meses
  Adam Evyčędo 4353c3e330 add info on TRAFFIC servers hace 5 meses
  Adam Evyčędo 5c75226508 show more info on exceptions in results and feeds hace 5 meses
  Adam Evyčędo 2d9af5bd46 fix warnings hace 5 meses
  Adam Evyčędo ab92cef626 fix upgrade path hace 5 meses
  Adam Evyčędo 3f942ddf24 add online geocoding based on Transitous hace 5 meses
  Adam Evyčędo 330323dea8 move cached and saved info to repository hace 5 meses
  Adam Evyčędo 4305e1529b Merge remote-tracking branch 'weblate/translations' into translations hace 6 meses
  abdelbasset jabrane 651acb189e Translated using Weblate (Arabic) hace 6 meses
  Adam Evyčędo 6065391398 make Place interface of Stop, POI, Position hace 6 meses
  Adam Evyčędo 1927a85f62 query POIs and addresses hace 6 meses
  Adam Evyčędo f9f0601433 Merge remote-tracking branch 'weblate/translations' into translations hace 6 meses
  abdelbasset jabrane 3f0f795eea Added translation using Weblate (Arabic) hace 6 meses
  Adam Evyčędo 95473a9f29 Merge branch 'translations' into develop hace 6 meses
  Adam Evyčędo 507ef194be handle client changes hace 6 meses
  Adam Evyčędo 56ffc5cab0 get avatar and fix refresh tokens hace 6 meses
  Adam Evyčędo 7107945c6a show account hace 6 meses
  Adam Evyčędo 8b0576d411 make account fragments hace 6 meses
  Adam Evyčędo 83ffb83df5 adapt feeds selection to new login hace 6 meses
  Adam Evyčędo 2dbca3de5b add dynamic client hace 6 meses
  Adam Evyčędo 424da66cd6 add new onboarding flow hace 6 meses
  Adam Evyčędo e468790c5c Merge remote-tracking branch 'weblate/translations' into translations hace 6 meses
  Nathan 246b1581f1 Translated using Weblate (French) hace 6 meses
  Adam Evyčędo 2ef80faacc Merge remote-tracking branch 'weblate/translations' into translations hace 7 meses
  Jonah Brüchert ff3b502ad2 Translated using Weblate (German) hace 7 meses
  Adam Evyčędo bbd76f12f6 Merge branch 'develop' into translations hace 7 meses
  Priit Jõerüüt 0d2bb1ed9d Translated using Weblate (Estonian) hace 8 meses
  Priit Jõerüüt c72eddfbfe Translated using Weblate (Estonian) hace 8 meses
  Priit Jõerüüt 1b6b5f86bb Translated using Weblate (Estonian) hace 8 meses

+ 0 - 23
CHANGELOG.adoc

@@ -14,29 +14,6 @@ and this project adheres to https://semver.org/spec/v2.0.0.html[Semantic Version
 * Travel planning
 * Offline timetable
 
-== [3.10.0-alpha.1] – 2025-06-10
-
-== Fixed
-
-* Showing departures from Transitous (regression)
-* Showing unique results from locating (regression)
-
-== [3.10.0-alpha] – 2025-06-07
-
-=== Added
-
-* Geocoding online based on Transitous
-* OIDC login and signup (hidden behind a runtime flag)
-
-=== Changed
-
-* Split data stores and repositories for feeds and results
-* Changed onboarding screen to only server
-
-=== Removed
-
-* Token
-
 == [3.9.0] – 2025-03-20
 
 === Added

+ 2 - 1
README.adoc

@@ -4,7 +4,7 @@
 
 = Bimba
 Adam Evyčędo <me@apiote.xyz>
-v3.10.0-alpha.1 2025-06-10
+v3.9.0 2025-03-20
 :toc:
 
 Bimba is a FLOSS public transport passenger companion; a timetable in your pocket.
@@ -69,3 +69,4 @@ along with this program.  If not, see <https://www.gnu.org/licenses/>.
 === Thanks to…
 
 * https://github.com/tebriz159 for new logo
+* https://material.io/icons[Material Icons], © Google Apache 2.0

+ 16 - 23
app/build.gradle.kts

@@ -20,19 +20,18 @@ plugins {
 android {
 	namespace = "xyz.apiote.bimba.czwek"
 	// NOTE apksigner with `--alignment-preserved` https://gitlab.com/fdroid/fdroiddata/-/issues/3299#note_1989808414
-	compileSdk = 36
-	buildToolsVersion = "36.0.0"
+	compileSdk = 35
+	buildToolsVersion = "35.0.1"
 
 	defaultConfig {
 		applicationId = "xyz.apiote.bimba.czwek"
 		minSdk = 21
-		targetSdk = 36
-		versionCode = 39
-		versionName = "3.10.0-alpha.1"
+		targetSdk = 35
+		versionCode = 37
+		versionName = "3.9.0"
 
 		testInstrumentationRunner = "androidx.test.runner.AndroidJUnitRunner"
-		resourceConfigurations += listOf("ar", "en", "de", "en-rGB", "en-rUS", "et", "fr", "it", "pl", "ru", "ta")
-		manifestPlaceholders["appAuthRedirectScheme"] = "bimba"
+		resourceConfigurations += listOf("en", "de", "en-rGB", "en-rUS", "et", "fr", "it", "pl", "ru", "ta")
 	}
 
 	buildTypes {
@@ -96,41 +95,35 @@ tasks.withType<ExtractDeepLinksTask> {
 }
 
 dependencies {
-	implementation("androidx.core:core-ktx:1.16.0")
+	implementation("androidx.core:core-ktx:1.15.0")
 	implementation("androidx.appcompat:appcompat:1.7.0")
-	// TODO move to stable
-	implementation("com.google.android.material:material:1.13.0-alpha13")
+	implementation("com.google.android.material:material:1.12.0")
 	implementation("androidx.constraintlayout:constraintlayout:2.2.1")
-	implementation("androidx.lifecycle:lifecycle-livedata-ktx:2.9.0")
-	implementation("androidx.lifecycle:lifecycle-viewmodel-ktx:2.9.0")
-	implementation("androidx.navigation:navigation-fragment-ktx:2.9.0")
-	implementation("androidx.navigation:navigation-ui-ktx:2.9.0")
+	implementation("androidx.lifecycle:lifecycle-livedata-ktx:2.8.7")
+	implementation("androidx.lifecycle:lifecycle-viewmodel-ktx:2.8.7")
+	implementation("androidx.navigation:navigation-fragment-ktx:2.8.8")
+	implementation("androidx.navigation:navigation-ui-ktx:2.8.8")
 	implementation("androidx.legacy:legacy-support-v4:1.0.0")
 	implementation("androidx.core:core-splashscreen:1.0.1")
 	implementation("com.google.openlocationcode:openlocationcode:1.0.4")
 	implementation("org.osmdroid:osmdroid-android:6.1.20")
 	implementation("org.yaml:snakeyaml:2.4")
-	implementation("com.charleskorn.kaml:kaml:0.77.0")
 	implementation("androidx.activity:activity-ktx:1.10.1")
 	implementation("com.otaliastudios:zoomlayout:1.9.0")
 	implementation("dev.bandb.graphview:graphview:0.8.1")
-	implementation("org.jetbrains.kotlinx:kotlinx-serialization-core:1.8.1")
+	implementation("org.jetbrains.kotlinx:kotlinx-serialization-core:1.8.0")
 	implementation("com.github.jershell:kbson:0.5.0")
 	implementation("androidx.preference:preference-ktx:1.2.1")
-	implementation("androidx.work:work-runtime-ktx:2.10.1")
+	implementation("androidx.work:work-runtime-ktx:2.10.0")
 	implementation("com.github.doyaaaaaken:kotlin-csv-jvm:1.10.0")
-	implementation("commons-io:commons-io:2.19.0")
-	implementation("com.google.guava:guava:33.4.8-android")
+	implementation("commons-io:commons-io:2.18.0")
+	implementation("com.google.guava:guava:33.4.0-android")
 	implementation(project(":fruchtfleisch"))
 	implementation("ch.acra:acra-http:5.12.0")
 	implementation("ch.acra:acra-notification:5.12.0")
 	implementation("com.squareup.okhttp3:okhttp:4.12.0")
 	implementation("com.squareup.moshi:moshi-kotlin:1.15.2")
 	implementation("androidx.activity:activity:1.10.1")
-	implementation("net.openid:appauth:0.11.1")
-	implementation("com.auth0.android:jwtdecode:2.0.2")
-	implementation("androidx.fragment:fragment-ktx:1.8.7")
-	implementation("org.minidns:minidns-hla:1.1.1")
 
 	coreLibraryDesugaring("com.android.tools:desugar_jdk_libs:2.1.5")
 

+ 9 - 4
app/src/main/AndroidManifest.xml

@@ -27,9 +27,6 @@ SPDX-License-Identifier: GPL-3.0-or-later
 		android:theme="@style/Theme.Bimba.Style"
 		tool:targetApi="33">
 		<activity
-			android:name=".account.AccountActivity"
-			android:exported="false" />
-		<activity
 			android:name=".journeys.JourneysActivity"
 			android:exported="false" />
 		<activity
@@ -44,6 +41,14 @@ SPDX-License-Identifier: GPL-3.0-or-later
 			android:exported="false"
 			android:theme="@style/Theme.Bimba.Style.NoActionBar" />
 		<activity
+			android:name=".settings.ServerChooserActivity"
+			android:exported="false">
+			<meta-data
+				android:name="android.app.lib_name"
+				android:value="" />
+		</activity>
+		<activity android:name=".onboarding.OnboardingActivity" />
+		<activity
 			android:name=".settings.feeds.FeedChooserActivity"
 			android:exported="false" />
 		<activity
@@ -83,7 +88,7 @@ SPDX-License-Identifier: GPL-3.0-or-later
 			</intent-filter>
 		</activity>
 		<activity
-			android:name=".search.ui.results.ResultsActivity"
+			android:name=".search.ResultsActivity"
 			android:exported="false"
 			android:label="@string/title_activity_results" />
 		<activity

+ 7 - 7
app/src/main/java/xyz/apiote/bimba/czwek/AboutActivity.kt

@@ -6,11 +6,11 @@ package xyz.apiote.bimba.czwek
 
 import android.content.ActivityNotFoundException
 import android.content.Intent
+import android.net.Uri
 import android.os.Bundle
 import android.widget.Toast
 import androidx.activity.enableEdgeToEdge
 import androidx.appcompat.app.AppCompatActivity
-import androidx.core.net.toUri
 import androidx.core.view.ViewCompat
 import androidx.core.view.WindowInsetsCompat
 import androidx.core.view.updatePadding
@@ -37,17 +37,17 @@ class AboutActivity : AppCompatActivity() {
 		}
 
 		binding.mastodon.setOnClickListener {
-			startActivity(Intent(Intent.ACTION_VIEW, "https://floss.social/@bimba".toUri()))
+			startActivity(Intent(Intent.ACTION_VIEW, Uri.parse("https://floss.social/@bimba")))
 		}
 		binding.website.setOnClickListener {
-			startActivity(Intent(Intent.ACTION_VIEW, "https://bimba.app".toUri()))
+			startActivity(Intent(Intent.ACTION_VIEW, Uri.parse("https://bimba.app")))
 		}
 		binding.code.setOnClickListener {
-			startActivity(Intent(Intent.ACTION_VIEW, "https://git.apiote.xyz/Bimba.git".toUri()))
+			startActivity(Intent(Intent.ACTION_VIEW, Uri.parse("https://git.apiote.xyz/Bimba.git")))
 		}
 		binding.email.setOnClickListener {
 			val intent = Intent(Intent.ACTION_SENDTO).apply {
-				setData("mailto:questions@bimba.app".toUri())
+				setData(Uri.parse("mailto:questions@bimba.app"))
 			}
 			try {
 				startActivity(intent)
@@ -59,12 +59,12 @@ class AboutActivity : AppCompatActivity() {
 			startActivity(
 				Intent(
 					Intent.ACTION_VIEW,
-					"https://hosted.weblate.org/projects/bimba/".toUri()
+					Uri.parse("https://hosted.weblate.org/projects/bimba/")
 				)
 			)
 		}
 		binding.matrix.setOnClickListener {
-			startActivity(Intent(Intent.ACTION_VIEW, "https://matrix.to/#/#marblearch:apiote.xyz".toUri()))
+			startActivity(Intent(Intent.ACTION_VIEW, Uri.parse("https://matrix.to/#/#marblearch:apiote.xyz")))
 		}
 	}
 }

+ 3 - 3
app/src/main/java/xyz/apiote/bimba/czwek/Bimba.kt

@@ -51,11 +51,11 @@ class Bimba : android.app.Application() {
 				channelDescription = getString(R.string.acra_notification_channel_description)
 				channelImportance = NotificationManagerCompat.IMPORTANCE_DEFAULT
 				sendButtonText = getString(R.string.send)
-				resSendButtonIcon = R.drawable.send  // TODO black?
+				resSendButtonIcon = R.drawable.send
 				discardButtonText = getString(R.string.discard)
-				resDiscardButtonIcon = R.drawable.discard // TODO colorOnSurface?
+				resDiscardButtonIcon = R.drawable.discard
 				sendWithCommentButtonText = getString(R.string.send_with_comment)
-				resSendWithCommentButtonIcon = R.drawable.comment // TODO colorOnSurface?
+				resSendWithCommentButtonIcon = R.drawable.comment
 				commentPrompt = getString(R.string.acra_notification_comment)
 			}
 		}

+ 0 - 118
app/src/main/java/xyz/apiote/bimba/czwek/account/AccountActivity.kt

@@ -1,118 +0,0 @@
-// SPDX-FileCopyrightText: Adam Evyčędo
-//
-// SPDX-License-Identifier: GPL-3.0-or-later
-
-package xyz.apiote.bimba.czwek.account
-
-import android.content.Intent
-import android.os.Bundle
-import androidx.activity.enableEdgeToEdge
-import androidx.activity.result.contract.ActivityResultContracts
-import androidx.appcompat.app.AppCompatActivity
-import androidx.appcompat.content.res.AppCompatResources
-import androidx.fragment.app.Fragment
-import com.google.android.material.dialog.MaterialAlertDialogBuilder
-import net.openid.appauth.AuthorizationException
-import net.openid.appauth.AuthorizationResponse
-import xyz.apiote.bimba.czwek.R
-import xyz.apiote.bimba.czwek.account.fragments.AccountFragment
-import xyz.apiote.bimba.czwek.account.fragments.LoginFragment
-import xyz.apiote.bimba.czwek.data.sources.Server
-import xyz.apiote.bimba.czwek.onboarding.FirstRunActivity
-import xyz.apiote.bimba.czwek.repo.User
-import xyz.apiote.bimba.czwek.settings.feeds.FeedChooserActivity
-
-
-class AccountActivity : AppCompatActivity() {
-	companion object {
-		const val IN_FEEDS_TRANSACTION = "inFeedsTransaction"
-	}
-
-	var currentFragment: Fragment? = null
-
-	private val authLauncher =
-		registerForActivityResult(ActivityResultContracts.StartActivityForResult()) {
-			when (currentFragment) {
-				is LoginFragment -> {
-					val resp = AuthorizationResponse.fromIntent(it.data!!)
-					val ex = AuthorizationException.fromIntent(it.data)
-					(currentFragment as LoginFragment).onAuthorization(resp, ex)
-				}
-
-				is AccountFragment -> {
-					currentFragment = LoginFragment.newInstance()
-					supportFragmentManager.beginTransaction()
-						.replace(R.id.container, currentFragment!!)
-						.commitNow()
-
-				}
-			}
-		}
-
-
-	override fun onCreate(savedInstanceState: Bundle?) {
-		enableEdgeToEdge()
-		super.onCreate(savedInstanceState)
-		setContentView(R.layout.activity_account)
-		if (savedInstanceState == null) {
-			currentFragment = if (User.load(this).isAuthenticated()) {
-				AccountFragment.newInstance()
-			} else {
-				LoginFragment.newInstance()
-			}
-			supportFragmentManager.beginTransaction()
-				.replace(R.id.container, currentFragment!!)
-				.commitNow()
-		}
-	}
-
-	fun moveOn(user: User, server: Server) {
-		var move = true
-
-		if (server.traffic!!.servers.all { it.seatsRequired.indexOf(user.seat.toString()) == -1 }) {
-			MaterialAlertDialogBuilder(this).setIcon(
-				AppCompatResources.getDrawable(
-					this,
-					R.drawable.error_gps
-				)
-			)
-				.setTitle(getString(R.string.forbidden))
-				.setMessage(getString(R.string.forbidden_server_message))
-				.setPositiveButton(R.string.ok) { _, _ -> }
-				.setNegativeButton(R.string.cancel) { _, _ -> move = false }
-				.show()
-		}
-
-		if (move) {
-			if (FirstRunActivity.getFirstRun(this)) {
-				startActivity(Intent(this, FeedChooserActivity::class.java))
-			} else {
-				if (user.isAuthenticated()) {
-					currentFragment = AccountFragment.newInstance()
-					supportFragmentManager.beginTransaction()
-						.replace(R.id.container, currentFragment!!)
-						.commitNow()
-				} else {
-					finish()
-				}
-			}
-		}
-	}
-
-	fun launchLogout(intent: Intent) {
-		authLauncher.launch(intent)
-	}
-
-	fun launchLogin(authIntent: Intent) {
-		authLauncher.launch(authIntent)
-	}
-
-	override fun onResume() {
-		super.onResume()
-
-		// TODO flashes on back from dashboard; should be e.g. start-activity-for-result
-		if (!FirstRunActivity.getFirstRun(this)) {
-			finish()
-		}
-	}
-}

+ 0 - 54
app/src/main/java/xyz/apiote/bimba/czwek/account/Client.kt

@@ -1,54 +0,0 @@
-// SPDX-FileCopyrightText: Adam Evyčędo
-//
-// SPDX-License-Identifier: GPL-3.0-or-later
-
-package xyz.apiote.bimba.czwek.account
-
-import android.content.Context
-import android.content.Context.MODE_PRIVATE
-import androidx.core.content.edit
-
-
-data class Client(val id: String, val secret: String, val authEndpoint: String) {
-	companion object {
-		const val PREFERENCES_NAME = "oidc_client"
-		const val KEY_ID = "id"
-		const val KEY_SECRET = "secret"
-		const val KEY_ENDPOINT = "auth_endpoint"
-		const val KEY_VERSION = "version"
-		const val VERSION = 0
-
-		fun load(context: Context): Client? {
-			val preferences = context.getSharedPreferences(PREFERENCES_NAME, MODE_PRIVATE)
-			val secret = preferences.getString(KEY_SECRET, null)
-			val id = preferences.getString(KEY_ID, null)
-			val authEndpoint = preferences.getString(KEY_ENDPOINT, null)
-			val version = preferences.getInt(KEY_VERSION, -1)
-			if (version != VERSION) {
-				reset(context)
-				// TODO don't logout forcibly
-				return null
-			}
-			return if (secret != null && id != null && authEndpoint != null) {
-				Client(id, secret, authEndpoint)
-			} else {
-				null
-			}
-		}
-
-		fun reset(context: Context) {
-			context.getSharedPreferences(PREFERENCES_NAME, MODE_PRIVATE).edit {
-				clear()
-			}
-		}
-	}
-
-	fun save(context: Context) {
-		context.getSharedPreferences(PREFERENCES_NAME, MODE_PRIVATE).edit {
-			putString(KEY_ID, id)
-			putString(KEY_SECRET, secret)
-			putString(KEY_ENDPOINT, authEndpoint)
-			putInt(KEY_VERSION, VERSION)
-		}
-	}
-}

+ 0 - 105
app/src/main/java/xyz/apiote/bimba/czwek/account/fragments/AccountFragment.kt

@@ -1,105 +0,0 @@
-// SPDX-FileCopyrightText: Adam Evyčędo
-//
-// SPDX-License-Identifier: GPL-3.0-or-later
-
-package xyz.apiote.bimba.czwek.account.fragments
-
-import android.content.Context
-import android.content.Intent
-import android.os.Bundle
-import android.view.LayoutInflater
-import android.view.View
-import android.view.ViewGroup
-import android.widget.Button
-import android.widget.ImageView
-import android.widget.TextView
-import androidx.core.content.res.ResourcesCompat
-import androidx.core.net.toUri
-import androidx.fragment.app.Fragment
-import androidx.fragment.app.viewModels
-import com.google.android.material.appbar.CollapsingToolbarLayout
-import kotlinx.coroutines.MainScope
-import kotlinx.coroutines.launch
-import xyz.apiote.bimba.czwek.R
-import xyz.apiote.bimba.czwek.account.AccountActivity
-import xyz.apiote.bimba.czwek.data.sources.Server
-import xyz.apiote.bimba.czwek.repo.User
-
-class AccountFragment : Fragment() {
-
-	companion object {
-		fun newInstance() = AccountFragment()
-		val LOGOUT_CALLBACK = "bimba://logout".toUri()
-	}
-
-	@Suppress("unused")
-	private val viewModel: AccountViewModel by viewModels()
-	private lateinit var user: User
-	private lateinit var _context: Context
-
-	override fun onCreate(savedInstanceState: Bundle?) {
-		super.onCreate(savedInstanceState)
-
-		_context = requireContext()
-
-		user = User.load(_context)
-	}
-
-	override fun onResume() {
-		super.onResume()
-		user = User.load(_context)
-		view?.let { setupProfile(it) }
-	}
-
-	override fun onCreateView(
-		inflater: LayoutInflater, container: ViewGroup?,
-		savedInstanceState: Bundle?
-	): View {
-		val root = inflater.inflate(R.layout.fragment_account, container, false)
-
-		setupProfile(root)
-
-		root.findViewById<Button>(R.id.edit_profile_button).setOnClickListener {
-			startActivity(
-				Intent(
-					Intent.ACTION_VIEW,
-					Server.get(_context).traffic!!.accountEndpoint.toUri()
-				)
-			)
-		}
-
-		root.findViewById<Button>(R.id.logout_button).setOnClickListener {
-			val intent = user.logout(_context)
-			(activity as AccountActivity).launchLogout(intent)
-		}
-
-		return root
-	}
-
-	private fun setupProfile(root: View) {
-		root.findViewById<CollapsingToolbarLayout>(R.id.collapsing_layout).apply {
-			title = _context.getString(R.string.greeting, user.getDisplayName(_context))
-			val tf = ResourcesCompat.getFont(_context, R.font.yellowcircle8)
-			setCollapsedTitleTypeface(tf)
-			setExpandedTitleTypeface(tf)
-		}
-
-
-		MainScope().launch {
-			root.findViewById<ImageView>(R.id.avatar).setImageDrawable(user.getAvatar(_context))
-		}
-		root.findViewById<TextView>(R.id.email).text = user.emailAddress
-		root.findViewById<TextView>(R.id.matrix).text = user.matrixID
-		root.findViewById<TextView>(R.id.seat).text = user.seat.toString()
-		root.findViewById<ImageView>(R.id.email_verified).visibility = if (user.emailVerified) {
-			View.VISIBLE
-		} else {
-			View.GONE
-		}
-		root.findViewById<ImageView>(R.id.matrix_verified).visibility = if (user.matrixVerified) {
-			View.VISIBLE
-		} else {
-			View.GONE
-		}
-	}
-}

+ 0 - 0
app/src/main/java/xyz/apiote/bimba/czwek/account/fragments/AccountViewModel.kt


Algunos archivos no se mostraron porque demasiados archivos cambiaron en este cambio