Fix scrolling issue in subscribe dialog; fix base URL background color; fix dark mode action bar

This commit is contained in:
Philipp Heckel 2022-02-06 15:51:30 -05:00
parent edb80cd45c
commit 678be49bff
7 changed files with 104 additions and 77 deletions

View file

@ -13,7 +13,7 @@ android {
targetSdkVersion 31
versionCode 21
versionName "1.9.0"
versionName "1.8.1"
testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"

View file

@ -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}")
}
}

View file

@ -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)

View file

@ -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>

View file

@ -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 -->

View file

@ -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>

View file

@ -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