Skip to content

Commit

Permalink
Fix scrolling issue in subscribe dialog; fix base URL background colo…
Browse files Browse the repository at this point in the history
…r; fix dark mode action bar
  • Loading branch information
Philipp Heckel committed Feb 6, 2022
1 parent edb80cd commit 678be49
Show file tree
Hide file tree
Showing 7 changed files with 104 additions and 77 deletions.
2 changes: 1 addition & 1 deletion app/build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ android {
targetSdkVersion 31

versionCode 21
versionName "1.9.0"
versionName "1.8.1"

testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"

Expand Down
13 changes: 8 additions & 5 deletions app/src/main/java/io/heckel/ntfy/msg/ApiService.kt
Original file line number Diff line number Diff line change
Expand Up @@ -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 {
Expand All @@ -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}")
}
}

Expand Down
19 changes: 15 additions & 4 deletions app/src/main/java/io/heckel/ntfy/ui/AddFragment.kt
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down Expand Up @@ -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)
Expand All @@ -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)
Expand Down Expand Up @@ -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"
Expand Down Expand Up @@ -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)
Expand Down
116 changes: 60 additions & 56 deletions app/src/main/res/layout/fragment_add_dialog.xml
Original file line number Diff line number Diff line change
Expand Up @@ -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"
Expand Down Expand Up @@ -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"
Expand All @@ -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"
Expand All @@ -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"
Expand Down Expand Up @@ -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>
9 changes: 4 additions & 5 deletions app/src/main/res/values/strings.xml
Original file line number Diff line number Diff line change
Expand Up @@ -77,20 +77,19 @@
<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>
<string name="add_dialog_use_another_server_description">
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>
Expand All @@ -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 -->
Expand Down
6 changes: 0 additions & 6 deletions app/src/main/res/values/styles.xml
Original file line number Diff line number Diff line change
Expand Up @@ -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>
Expand Down
16 changes: 16 additions & 0 deletions fastlane/metadata/android/en-US/changelog/21.txt
Original file line number Diff line number Diff line change
@@ -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

0 comments on commit 678be49

Please sign in to comment.