Fix scrolling issue in subscribe dialog; fix base URL background color; fix dark mode action bar
This commit is contained in:
parent
edb80cd45c
commit
678be49bff
7 changed files with 104 additions and 77 deletions
|
@ -13,7 +13,7 @@ android {
|
|||
targetSdkVersion 31
|
||||
|
||||
versionCode 21
|
||||
versionName "1.9.0"
|
||||
versionName "1.8.1"
|
||||
|
||||
testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"
|
||||
|
||||
|
|
|
@ -118,7 +118,7 @@ class ApiService {
|
|||
return call
|
||||
}
|
||||
|
||||
fun authTopicRead(baseUrl: String, topic: String, user: User?): Boolean {
|
||||
fun checkAuth(baseUrl: String, topic: String, user: User?): Boolean {
|
||||
if (user == null) {
|
||||
Log.d(TAG, "Checking anonymous read against ${topicUrl(baseUrl, topic)}")
|
||||
} else {
|
||||
|
@ -127,11 +127,14 @@ class ApiService {
|
|||
val url = topicUrlAuth(baseUrl, topic)
|
||||
val request = requestBuilder(url, user).build()
|
||||
client.newCall(request).execute().use { response ->
|
||||
return if (user == null) {
|
||||
response.isSuccessful || response.code == 404 // Treat 404 as success (old server; to be removed in future versions)
|
||||
} else {
|
||||
response.isSuccessful
|
||||
if (response.isSuccessful) {
|
||||
return true
|
||||
} else if (user == null && response.code == 404) {
|
||||
return true // Special case: Anonymous login to old servers return 404 since /<topic>/auth doesn't exist
|
||||
} else if (response.code == 401 || response.code == 403) { // See server/server.go
|
||||
return false
|
||||
}
|
||||
throw Exception("Unexpected server response ${response.code}")
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -7,6 +7,7 @@ import android.content.Context
|
|||
import android.os.Bundle
|
||||
import android.text.Editable
|
||||
import android.text.TextWatcher
|
||||
import android.util.TypedValue
|
||||
import android.view.View
|
||||
import android.view.WindowManager
|
||||
import android.view.inputmethod.InputMethodManager
|
||||
|
@ -88,7 +89,9 @@ class AddFragment : DialogFragment() {
|
|||
// Fields for "subscribe page"
|
||||
subscribeTopicText = view.findViewById(R.id.add_dialog_subscribe_topic_text)
|
||||
subscribeBaseUrlLayout = view.findViewById(R.id.add_dialog_subscribe_base_url_layout)
|
||||
subscribeBaseUrlLayout.background = view.background
|
||||
subscribeBaseUrlText = view.findViewById(R.id.add_dialog_subscribe_base_url_text)
|
||||
subscribeBaseUrlText.background = view.background
|
||||
subscribeInstantDeliveryBox = view.findViewById(R.id.add_dialog_subscribe_instant_delivery_box)
|
||||
subscribeInstantDeliveryCheckbox = view.findViewById(R.id.add_dialog_subscribe_instant_delivery_checkbox)
|
||||
subscribeInstantDeliveryDescription = view.findViewById(R.id.add_dialog_subscribe_instant_delivery_description)
|
||||
|
@ -100,6 +103,14 @@ class AddFragment : DialogFragment() {
|
|||
subscribeErrorTextImage = view.findViewById(R.id.add_dialog_subscribe_error_text_image)
|
||||
subscribeErrorTextImage.visibility = View.GONE
|
||||
|
||||
// Hack: Make end icon smaller, see https://stackoverflow.com/a/57098715/1440785
|
||||
val dimension = TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, 30f, resources.displayMetrics)
|
||||
val endIconImageView = subscribeBaseUrlLayout.findViewById<ImageView>(R.id.text_input_end_icon)
|
||||
endIconImageView.minimumHeight = dimension.toInt()
|
||||
endIconImageView.minimumWidth = dimension.toInt()
|
||||
subscribeBaseUrlLayout.requestLayout()
|
||||
|
||||
|
||||
// Fields for "login page"
|
||||
loginUsernameText = view.findViewById(R.id.add_dialog_login_username)
|
||||
loginPasswordText = view.findViewById(R.id.add_dialog_login_password)
|
||||
|
@ -280,14 +291,14 @@ class AddFragment : DialogFragment() {
|
|||
lifecycleScope.launch(Dispatchers.IO) {
|
||||
try {
|
||||
val user = repository.getUser(baseUrl) // May be null
|
||||
val authorized = api.authTopicRead(baseUrl, topic, user)
|
||||
val authorized = api.checkAuth(baseUrl, topic, user)
|
||||
if (authorized) {
|
||||
Log.d(TAG, "Access granted to topic ${topicUrl(baseUrl, topic)}")
|
||||
dismissDialog()
|
||||
} else {
|
||||
if (user != null) {
|
||||
Log.w(TAG, "Access not allowed to topic ${topicUrl(baseUrl, topic)}, but user already exists")
|
||||
showErrorAndReenableSubscribeView(getString(R.string.add_dialog_login_error_not_authorized))
|
||||
showErrorAndReenableSubscribeView(getString(R.string.add_dialog_login_error_not_authorized, user.username))
|
||||
} else {
|
||||
Log.w(TAG, "Access not allowed to topic ${topicUrl(baseUrl, topic)}, showing login dialog")
|
||||
val activity = activity ?: return@launch // We may have pressed "Cancel"
|
||||
|
@ -327,14 +338,14 @@ class AddFragment : DialogFragment() {
|
|||
lifecycleScope.launch(Dispatchers.IO) {
|
||||
Log.d(TAG, "Checking read access for user ${user.username} to topic ${topicUrl(baseUrl, topic)}")
|
||||
try {
|
||||
val authorized = api.authTopicRead(baseUrl, topic, user)
|
||||
val authorized = api.checkAuth(baseUrl, topic, user)
|
||||
if (authorized) {
|
||||
Log.d(TAG, "Access granted for user ${user.username} to topic ${topicUrl(baseUrl, topic)}, adding to database")
|
||||
repository.addUser(user)
|
||||
dismissDialog()
|
||||
} else {
|
||||
Log.w(TAG, "Access not allowed for user ${user.username} to topic ${topicUrl(baseUrl, topic)}")
|
||||
showErrorAndReenableLoginView(getString(R.string.add_dialog_login_error_not_authorized))
|
||||
showErrorAndReenableLoginView(getString(R.string.add_dialog_login_error_not_authorized, user.username))
|
||||
}
|
||||
} catch (e: Exception) {
|
||||
Log.w(TAG, "Connection to topic failed during login: ${e.message}", e)
|
||||
|
|
|
@ -6,13 +6,14 @@
|
|||
android:orientation="vertical"
|
||||
android:paddingLeft="16dp"
|
||||
android:paddingRight="16dp">
|
||||
|
||||
<androidx.constraintlayout.widget.ConstraintLayout
|
||||
<ScrollView
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
android:orientation="horizontal"
|
||||
android:id="@+id/add_dialog_subscribe_view"
|
||||
android:visibility="visible">
|
||||
android:id="@+id/add_dialog_subscribe_view">
|
||||
<androidx.constraintlayout.widget.ConstraintLayout
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:orientation="horizontal">
|
||||
<TextView
|
||||
android:id="@+id/add_dialog_subscribe_title_text"
|
||||
android:layout_width="0dp"
|
||||
|
@ -57,46 +58,46 @@
|
|||
app:layout_constraintEnd_toEndOf="parent"
|
||||
app:layout_constraintTop_toBottomOf="@id/add_dialog_subscribe_topic_text"
|
||||
android:layout_marginTop="-3dp"/>
|
||||
<TextView
|
||||
android:text="@string/add_dialog_use_another_server_description"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content" android:id="@+id/add_dialog_subscribe_use_another_server_description"
|
||||
android:paddingStart="4dp" android:paddingTop="0dp"
|
||||
android:visibility="gone" app:layout_constraintStart_toStartOf="parent"
|
||||
app:layout_constraintEnd_toEndOf="parent"
|
||||
app:layout_constraintTop_toBottomOf="@id/add_dialog_subscribe_use_another_server_checkbox"
|
||||
android:layout_marginTop="-5dp"/>
|
||||
<com.google.android.material.textfield.TextInputLayout
|
||||
style="@style/Widget.MaterialComponents.TextInputLayout.FilledBox.Dense.ExposedDropdownMenu"
|
||||
android:id="@+id/add_dialog_subscribe_base_url_layout"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="40dp"
|
||||
android:layout_margin="0dp"
|
||||
android:background="@android:color/transparent"
|
||||
android:padding="0dp"
|
||||
android:visibility="gone"
|
||||
app:endIconMode="custom"
|
||||
app:hintEnabled="false"
|
||||
app:boxBackgroundColor="@android:color/transparent" app:layout_constraintStart_toStartOf="parent"
|
||||
app:layout_constraintEnd_toEndOf="parent"
|
||||
app:layout_constraintTop_toBottomOf="@id/add_dialog_subscribe_use_another_server_description">
|
||||
<AutoCompleteTextView
|
||||
<TextView
|
||||
android:text="@string/add_dialog_use_another_server_description"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content" android:id="@+id/add_dialog_subscribe_use_another_server_description"
|
||||
android:paddingStart="4dp" android:paddingTop="0dp"
|
||||
android:visibility="gone" app:layout_constraintStart_toStartOf="parent"
|
||||
app:layout_constraintEnd_toEndOf="parent"
|
||||
app:layout_constraintTop_toBottomOf="@id/add_dialog_subscribe_use_another_server_checkbox"
|
||||
android:layout_marginTop="-5dp"/>
|
||||
<com.google.android.material.textfield.TextInputLayout
|
||||
style="@style/Widget.MaterialComponents.TextInputLayout.FilledBox.Dense.ExposedDropdownMenu"
|
||||
android:id="@+id/add_dialog_subscribe_base_url_layout"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:id="@+id/add_dialog_subscribe_base_url_text"
|
||||
android:hint="@string/app_base_url"
|
||||
android:maxLines="1"
|
||||
android:layout_marginTop="0dp"
|
||||
android:layout_marginBottom="0dp"
|
||||
android:inputType="textNoSuggestions"
|
||||
android:textAppearance="?android:attr/textAppearanceMedium"
|
||||
android:paddingStart="0dp"
|
||||
android:paddingEnd="0dp"
|
||||
android:paddingTop="0dp"
|
||||
android:paddingBottom="0dp"
|
||||
android:layout_marginStart="4dp"
|
||||
android:layout_marginEnd="4dp"/>
|
||||
</com.google.android.material.textfield.TextInputLayout>
|
||||
android:layout_margin="0dp"
|
||||
android:padding="0dp"
|
||||
android:visibility="gone"
|
||||
app:endIconMode="custom"
|
||||
app:hintEnabled="false"
|
||||
app:boxBackgroundColor="@null" app:layout_constraintStart_toStartOf="parent"
|
||||
app:layout_constraintEnd_toEndOf="parent"
|
||||
app:layout_constraintTop_toBottomOf="@id/add_dialog_subscribe_use_another_server_description">
|
||||
<AutoCompleteTextView
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:id="@+id/add_dialog_subscribe_base_url_text"
|
||||
android:hint="@string/app_base_url"
|
||||
android:maxLines="1"
|
||||
android:layout_marginTop="0dp"
|
||||
android:layout_marginBottom="0dp"
|
||||
android:inputType="textNoSuggestions"
|
||||
android:paddingStart="0dp"
|
||||
android:paddingEnd="0dp"
|
||||
android:paddingTop="5dp"
|
||||
android:paddingBottom="5dp"
|
||||
android:layout_marginStart="4dp"
|
||||
android:layout_marginEnd="4dp"
|
||||
android:textAppearance="?android:attr/textAppearanceMedium"
|
||||
/>
|
||||
</com.google.android.material.textfield.TextInputLayout>
|
||||
|
||||
<LinearLayout
|
||||
android:orientation="horizontal"
|
||||
|
@ -118,14 +119,14 @@
|
|||
app:layout_constraintEnd_toStartOf="@+id/main_item_date" android:paddingTop="3dp"
|
||||
android:layout_marginTop="3dp"/>
|
||||
</LinearLayout>
|
||||
<TextView
|
||||
android:text="@string/add_dialog_instant_delivery_description"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content" android:id="@+id/add_dialog_subscribe_instant_delivery_description"
|
||||
android:paddingStart="4dp" android:paddingTop="0dp"
|
||||
android:visibility="gone" app:layout_constraintStart_toStartOf="parent"
|
||||
app:layout_constraintEnd_toEndOf="parent"
|
||||
app:layout_constraintTop_toBottomOf="@id/add_dialog_subscribe_instant_delivery_box"/>
|
||||
<TextView
|
||||
android:text="@string/add_dialog_instant_delivery_description"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content" android:id="@+id/add_dialog_subscribe_instant_delivery_description"
|
||||
android:paddingStart="4dp" android:paddingTop="0dp"
|
||||
android:visibility="gone" app:layout_constraintStart_toStartOf="parent"
|
||||
app:layout_constraintEnd_toEndOf="parent"
|
||||
app:layout_constraintTop_toBottomOf="@id/add_dialog_subscribe_instant_delivery_box"/>
|
||||
<ImageView
|
||||
android:layout_width="20dp"
|
||||
android:layout_height="20dp" app:srcCompat="@drawable/ic_error_red_24dp"
|
||||
|
@ -140,13 +141,15 @@
|
|||
app:layout_constraintEnd_toEndOf="parent"
|
||||
app:layout_constraintTop_toBottomOf="@id/add_dialog_subscribe_instant_delivery_description" android:paddingEnd="4dp" android:textColor="@color/primaryDangerButtonColor" app:layout_constraintStart_toEndOf="@id/add_dialog_subscribe_error_text_image" android:layout_marginTop="5dp" tools:visibility="gone"/>
|
||||
</androidx.constraintlayout.widget.ConstraintLayout>
|
||||
<androidx.constraintlayout.widget.ConstraintLayout
|
||||
</ScrollView>
|
||||
<ScrollView
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
android:orientation="horizontal"
|
||||
android:id="@+id/add_dialog_login_view"
|
||||
android:visibility="gone"
|
||||
>
|
||||
android:id="@+id/add_dialog_login_view">
|
||||
<androidx.constraintlayout.widget.ConstraintLayout
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:orientation="horizontal">
|
||||
<TextView
|
||||
android:id="@+id/add_dialog_login_title"
|
||||
android:layout_width="0dp"
|
||||
|
@ -204,4 +207,5 @@
|
|||
app:layout_constraintBottom_toTopOf="@+id/add_dialog_login_description"
|
||||
android:indeterminate="true" android:layout_marginBottom="5dp"/>
|
||||
</androidx.constraintlayout.widget.ConstraintLayout>
|
||||
</ScrollView>
|
||||
</LinearLayout>
|
||||
|
|
|
@ -77,7 +77,7 @@
|
|||
<string name="add_dialog_title">Subscribe to topic</string>
|
||||
<string name="add_dialog_description_below">
|
||||
Topics may not be password-protected, so choose a name that\'s not easy to
|
||||
guess. Once subscribed, you can PUT/POST to receive notifications.
|
||||
guess. Once subscribed, you can PUT/POST notifications.
|
||||
</string>
|
||||
<string name="add_dialog_topic_name_hint">Topic name, e.g. phils_alerts</string>
|
||||
<string name="add_dialog_use_another_server">Use another server</string>
|
||||
|
@ -85,12 +85,11 @@
|
|||
You can subscribe to topics from your own server. This option requires a foreground service.
|
||||
</string>
|
||||
<string name="add_dialog_use_another_server_description_noinstant">
|
||||
You can subscribe to topics from your own server. Simply type in the base
|
||||
URL of your server.
|
||||
You can subscribe to topics from your own server. Type the server URL below.
|
||||
</string>
|
||||
<string name="add_dialog_instant_delivery">Instant delivery in doze mode</string>
|
||||
<string name="add_dialog_instant_delivery_description">
|
||||
Ensures that messages are immediately delivered, even if the device is inactive or in doze mode.
|
||||
Ensures that messages are immediately delivered, even if the device is inactive.
|
||||
This requires a foreground service.
|
||||
</string>
|
||||
<string name="add_dialog_button_cancel">Cancel</string>
|
||||
|
@ -102,7 +101,7 @@
|
|||
<string name="add_dialog_login_description">This topic requires you to login. Please type in a username and password.</string>
|
||||
<string name="add_dialog_login_username_hint">Username</string>
|
||||
<string name="add_dialog_login_password_hint">Password</string>
|
||||
<string name="add_dialog_login_error_not_authorized">Login failed. User not authorized.</string>
|
||||
<string name="add_dialog_login_error_not_authorized">Login failed. User %1$s not authorized.</string>
|
||||
<string name="add_dialog_login_new_user">New user</string>
|
||||
|
||||
<!-- Detail activity -->
|
||||
|
|
|
@ -3,16 +3,10 @@
|
|||
<style name="AppTheme" parent="Theme.MaterialComponents.DayNight.DarkActionBar">
|
||||
<item name="colorPrimary">@color/primaryColor</item>
|
||||
<item name="colorAccent">@color/primaryLightColor</item>
|
||||
<item name="actionBarStyle">@style/Custom.ActionBar</item>
|
||||
<item name="android:statusBarColor">@color/primaryColor</item>
|
||||
<item name="actionModeBackground">@color/primaryDarkColor</item>
|
||||
</style>
|
||||
|
||||
<!-- Action bar color identical in dark mode, see https://stackoverflow.com/a/58368668/1440785 -->
|
||||
<style name="Custom.ActionBar" parent="Widget.MaterialComponents.Light.ActionBar.Solid">
|
||||
<item name="background">@color/primaryColor</item>
|
||||
</style>
|
||||
|
||||
<!-- Rounded corners in images, see https://stackoverflow.com/a/61960983/1440785 -->
|
||||
<style name="roundedCornersImageView" parent="">
|
||||
<item name="cornerFamily">rounded</item>
|
||||
|
|
|
@ -1,2 +1,18 @@
|
|||
Features:
|
||||
* Support auth / access control (#19, thanks to @cmeis, @gedw99, @karmanyaahm,
|
||||
@Mek101, @gc-ss, @julianfoad, @nmoseman, Jakob, PeterCxy, Techlosopher)
|
||||
* Export/upload log now allows censored/uncensored logs (no ticket)
|
||||
* Removed wake lock (except for notification dispatching, no ticket)
|
||||
* Swipe to remove notifications (#117)
|
||||
|
||||
Bug fixes:
|
||||
* Fix download issues on SDK 29 "Movement not allowed" (#116, thanks Jakob)
|
||||
* Fix for Android 12 crashes (#124, thanks @eskilop)
|
||||
* Fix WebSocket retry logic bug with multiple servers (no ticket)
|
||||
* Fix race in refresh logic leading to duplicate connections (no ticket)
|
||||
* Fix scrolling issue in subscribe to topic dialog (#131, thanks @arminus)
|
||||
* Fix base URL text field color in dark mode, and size with large fonts (no ticket)
|
||||
* Fix action bar color in dark mode (make black, no ticket)
|
||||
|
||||
Notes:
|
||||
* Foundational work for per-subscription settings
|
||||
|
|
Loading…
Reference in a new issue