Merge branch 'develop' into feature/stabilization

This commit is contained in:
ganfra 2020-01-08 22:28:08 +01:00
commit 8c4d8763a2
12 changed files with 164 additions and 41 deletions

View File

@ -12,14 +12,18 @@ Improvements 🙌:
- Improve devices list screen - Improve devices list screen
- Add settings for rageshake sensibility - Add settings for rageshake sensibility
- Fix autocompletion issues and add support for rooms, groups, and emoji (#780) - Fix autocompletion issues and add support for rooms, groups, and emoji (#780)
- Show skip to bottom FAB while scrolling down (#752)
Other changes: Other changes:
- Change the way RiotX identifies a session to allow the SDK to support several sessions with the same user (#800) - Change the way RiotX identifies a session to allow the SDK to support several sessions with the same user (#800)
- Exclude play-services-oss-licenses library from F-Droid build (#814)
Bugfix 🐛: Bugfix 🐛:
- Fix crash when opening room creation screen from the room filtering screen - Fix crash when opening room creation screen from the room filtering screen
- Fix avatar image disappearing (#777) - Fix avatar image disappearing (#777)
- Fix read marker banner when permalink - Fix read marker banner when permalink
- Fix joining upgraded rooms (#697)
- Fix matrix.org room directory not being browsable (#807)
- Hide non working settings (#751) - Hide non working settings (#751)
Translations 🗣: Translations 🗣:

View File

@ -212,11 +212,12 @@ internal interface RoomAPI {
/** /**
* Join the given room. * Join the given room.
* *
* @param roomId the room id * @param roomIdOrAlias the room id or alias
* @param server_name the servers to attempt to join the room through
* @param params the request body * @param params the request body
*/ */
@POST(NetworkConstants.URI_API_PREFIX_PATH_R0 + "rooms/{roomId}/join") @POST(NetworkConstants.URI_API_PREFIX_PATH_R0 + "join/{roomIdOrAlias}")
fun join(@Path("roomId") roomId: String, fun join(@Path("roomIdOrAlias") roomIdOrAlias: String,
@Query("server_name") viaServers: List<String>, @Query("server_name") viaServers: List<String>,
@Body params: Map<String, String?>): Call<Unit> @Body params: Map<String, String?>): Call<Unit>

View File

@ -186,6 +186,7 @@ android {
gplay { gplay {
dimension "store" dimension "store"
resValue "bool", "isGplay", "true"
buildConfigField "boolean", "ALLOW_FCM_USE", "true" buildConfigField "boolean", "ALLOW_FCM_USE", "true"
buildConfigField "String", "SHORT_FLAVOR_DESCRIPTION", "\"G\"" buildConfigField "String", "SHORT_FLAVOR_DESCRIPTION", "\"G\""
buildConfigField "String", "FLAVOR_DESCRIPTION", "\"GooglePlay\"" buildConfigField "String", "FLAVOR_DESCRIPTION", "\"GooglePlay\""
@ -194,6 +195,7 @@ android {
fdroid { fdroid {
dimension "store" dimension "store"
resValue "bool", "isGplay", "false"
buildConfigField "boolean", "ALLOW_FCM_USE", "false" buildConfigField "boolean", "ALLOW_FCM_USE", "false"
buildConfigField "String", "SHORT_FLAVOR_DESCRIPTION", "\"F\"" buildConfigField "String", "SHORT_FLAVOR_DESCRIPTION", "\"F\""
buildConfigField "String", "FLAVOR_DESCRIPTION", "\"FDroid\"" buildConfigField "String", "FLAVOR_DESCRIPTION", "\"FDroid\""
@ -249,9 +251,6 @@ dependencies {
implementation "com.squareup.moshi:moshi-adapters:$moshi_version" implementation "com.squareup.moshi:moshi-adapters:$moshi_version"
kapt "com.squareup.moshi:moshi-kotlin-codegen:$moshi_version" kapt "com.squareup.moshi:moshi-kotlin-codegen:$moshi_version"
// OSS License
implementation 'com.google.android.gms:play-services-oss-licenses:17.0.0'
// Log // Log
implementation 'com.jakewharton.timber:timber:4.7.1' implementation 'com.jakewharton.timber:timber:4.7.1'
@ -343,6 +342,9 @@ dependencies {
exclude group: 'com.google.firebase', module: 'firebase-measurement-connector' exclude group: 'com.google.firebase', module: 'firebase-measurement-connector'
} }
// OSS License, gplay flavor only
gplayImplementation 'com.google.android.gms:play-services-oss-licenses:17.0.0'
implementation "androidx.emoji:emoji-appcompat:1.0.0" implementation "androidx.emoji:emoji-appcompat:1.0.0"
// TESTS // TESTS

View File

@ -0,0 +1,22 @@
/*
* Copyright 2020 New Vector Ltd
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package im.vector.riotx
import android.content.Context
// No op
fun openOssLicensesMenuActivity(@Suppress("UNUSED_PARAMETER") context: Context) = Unit

View File

@ -0,0 +1,23 @@
/*
* Copyright 2020 New Vector Ltd
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package im.vector.riotx
import android.content.Context
import android.content.Intent
import com.google.android.gms.oss.licenses.OssLicensesMenuActivity
fun openOssLicensesMenuActivity(context: Context) = context.startActivity(Intent(context, OssLicensesMenuActivity::class.java))

View File

@ -19,16 +19,14 @@ package im.vector.riotx.core.utils
import android.os.Handler import android.os.Handler
internal class Debouncer(private val handler: Handler) { class Debouncer(private val handler: Handler) {
private val runnables = HashMap<String, Runnable>() private val runnables = HashMap<String, Runnable>()
fun debounce(identifier: String, millis: Long, r: Runnable): Boolean { fun debounce(identifier: String, millis: Long, r: Runnable): Boolean {
if (runnables.containsKey(identifier)) { // debounce
// debounce cancel(identifier)
val old = runnables[identifier]
handler.removeCallbacks(old)
}
insertRunnable(identifier, r, millis) insertRunnable(identifier, r, millis)
return true return true
} }
@ -37,6 +35,14 @@ internal class Debouncer(private val handler: Handler) {
handler.removeCallbacksAndMessages(null) handler.removeCallbacksAndMessages(null)
} }
fun cancel(identifier: String) {
if (runnables.containsKey(identifier)) {
val old = runnables[identifier]
handler.removeCallbacks(old)
runnables.remove(identifier)
}
}
private fun insertRunnable(identifier: String, r: Runnable, millis: Long) { private fun insertRunnable(identifier: String, r: Runnable, millis: Long) {
val chained = Runnable { val chained = Runnable {
handler.post(r) handler.post(r)

View File

@ -0,0 +1,77 @@
/*
* Copyright 2020 New Vector Ltd
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package im.vector.riotx.features.home.room.detail
import androidx.recyclerview.widget.LinearLayoutManager
import androidx.recyclerview.widget.RecyclerView
import com.google.android.material.floatingactionbutton.FloatingActionButton
import im.vector.riotx.core.utils.Debouncer
import timber.log.Timber
/**
* Show or hide the jumpToBottomView, depending on the scrolling and if the timeline is displaying the more recent event
* - When user scrolls up (i.e. going to the past): hide
* - When user scrolls down: show if not displaying last event
* - When user stops scrolling: show if not displaying last event
*/
class JumpToBottomViewVisibilityManager(
private val jumpToBottomView: FloatingActionButton,
private val debouncer: Debouncer,
recyclerView: RecyclerView,
private val layoutManager: LinearLayoutManager) {
init {
recyclerView.addOnScrollListener(object : RecyclerView.OnScrollListener() {
override fun onScrolled(recyclerView: RecyclerView, dx: Int, dy: Int) {
debouncer.cancel("jump_to_bottom_visibility")
val scrollingToPast = dy < 0
if (scrollingToPast) {
jumpToBottomView.hide()
} else {
maybeShowJumpToBottomViewVisibility()
}
}
override fun onScrollStateChanged(recyclerView: RecyclerView, newState: Int) {
when (newState) {
RecyclerView.SCROLL_STATE_IDLE -> {
maybeShowJumpToBottomViewVisibilityWithDelay()
}
RecyclerView.SCROLL_STATE_DRAGGING,
RecyclerView.SCROLL_STATE_SETTLING -> Unit
}
}
})
}
fun maybeShowJumpToBottomViewVisibilityWithDelay() {
debouncer.debounce("jump_to_bottom_visibility", 250, Runnable {
maybeShowJumpToBottomViewVisibility()
})
}
private fun maybeShowJumpToBottomViewVisibility() {
Timber.v("First visible: ${layoutManager.findFirstCompletelyVisibleItemPosition()}")
if (layoutManager.findFirstVisibleItemPosition() != 0) {
jumpToBottomView.show()
} else {
jumpToBottomView.hide()
}
}
}

View File

@ -177,6 +177,7 @@ class RoomDetailFragment @Inject constructor(
private lateinit var sharedActionViewModel: MessageSharedActionViewModel private lateinit var sharedActionViewModel: MessageSharedActionViewModel
private lateinit var layoutManager: LinearLayoutManager private lateinit var layoutManager: LinearLayoutManager
private lateinit var jumpToBottomViewVisibilityManager: JumpToBottomViewVisibilityManager
private var modelBuildListener: OnModelBuildFinishedListener? = null private var modelBuildListener: OnModelBuildFinishedListener? = null
private lateinit var attachmentsHelper: AttachmentsHelper private lateinit var attachmentsHelper: AttachmentsHelper
@ -306,6 +307,13 @@ class RoomDetailFragment @Inject constructor(
layoutManager.scrollToPosition(0) layoutManager.scrollToPosition(0)
} }
} }
jumpToBottomViewVisibilityManager = JumpToBottomViewVisibilityManager(
jumpToBottomView,
debouncer,
recyclerView,
layoutManager
)
} }
private fun setupJumpToReadMarkerView() { private fun setupJumpToReadMarkerView() {
@ -472,25 +480,11 @@ class RoomDetailFragment @Inject constructor(
it.dispatchTo(scrollOnNewMessageCallback) it.dispatchTo(scrollOnNewMessageCallback)
it.dispatchTo(scrollOnHighlightedEventCallback) it.dispatchTo(scrollOnHighlightedEventCallback)
updateJumpToReadMarkerViewVisibility() updateJumpToReadMarkerViewVisibility()
updateJumpToBottomViewVisibility() jumpToBottomViewVisibilityManager.maybeShowJumpToBottomViewVisibilityWithDelay()
} }
timelineEventController.addModelBuildListener(modelBuildListener) timelineEventController.addModelBuildListener(modelBuildListener)
recyclerView.adapter = timelineEventController.adapter recyclerView.adapter = timelineEventController.adapter
recyclerView.addOnScrollListener(object : RecyclerView.OnScrollListener() {
override fun onScrollStateChanged(recyclerView: RecyclerView, newState: Int) {
when (newState) {
RecyclerView.SCROLL_STATE_IDLE -> {
updateJumpToBottomViewVisibility()
}
RecyclerView.SCROLL_STATE_DRAGGING,
RecyclerView.SCROLL_STATE_SETTLING -> {
jumpToBottomView.hide()
}
}
}
})
if (vectorPreferences.swipeToReplyIsEnabled()) { if (vectorPreferences.swipeToReplyIsEnabled()) {
val quickReplyHandler = object : RoomMessageTouchHelperCallback.QuickReplayHandler { val quickReplyHandler = object : RoomMessageTouchHelperCallback.QuickReplayHandler {
override fun performQuickReplyOnHolder(model: EpoxyModel<*>) { override fun performQuickReplyOnHolder(model: EpoxyModel<*>) {
@ -543,17 +537,6 @@ class RoomDetailFragment @Inject constructor(
} }
} }
private fun updateJumpToBottomViewVisibility() {
debouncer.debounce("jump_to_bottom_visibility", 250, Runnable {
Timber.v("First visible: ${layoutManager.findFirstCompletelyVisibleItemPosition()}")
if (layoutManager.findFirstVisibleItemPosition() != 0) {
jumpToBottomView.show()
} else {
jumpToBottomView.hide()
}
})
}
private fun setupComposer() { private fun setupComposer() {
autoCompleter.setup(composerLayout.composerEditText) autoCompleter.setup(composerLayout.composerEditText)
composerLayout.callback = object : TextComposerView.Callback { composerLayout.callback = object : TextComposerView.Callback {

View File

@ -48,6 +48,7 @@ class RoomDirectoryListCreator @Inject constructor(private val stringArrayProvid
if (it != userHsName) { if (it != userHsName) {
// Use the server name as a default display name // Use the server name as a default display name
result.add(RoomDirectoryData( result.add(RoomDirectoryData(
homeServer = it,
displayName = it, displayName = it,
includeAllNetworks = true includeAllNetworks = true
)) ))

View File

@ -20,13 +20,13 @@ import android.content.Intent
import android.net.Uri import android.net.Uri
import android.provider.Settings import android.provider.Settings
import androidx.preference.Preference import androidx.preference.Preference
import com.google.android.gms.oss.licenses.OssLicensesMenuActivity
import im.vector.matrix.android.api.Matrix import im.vector.matrix.android.api.Matrix
import im.vector.riotx.R import im.vector.riotx.R
import im.vector.riotx.core.preference.VectorPreference import im.vector.riotx.core.preference.VectorPreference
import im.vector.riotx.core.utils.copyToClipboard import im.vector.riotx.core.utils.copyToClipboard
import im.vector.riotx.core.utils.displayInWebView import im.vector.riotx.core.utils.displayInWebView
import im.vector.riotx.features.version.VersionProvider import im.vector.riotx.features.version.VersionProvider
import im.vector.riotx.openOssLicensesMenuActivity
import javax.inject.Inject import javax.inject.Inject
class VectorSettingsHelpAboutFragment @Inject constructor( class VectorSettingsHelpAboutFragment @Inject constructor(
@ -107,10 +107,11 @@ class VectorSettingsHelpAboutFragment @Inject constructor(
false false
} }
// Note: preference is not visible on F-Droid build
findPreference<VectorPreference>(VectorPreferences.SETTINGS_OTHER_THIRD_PARTY_NOTICES_PREFERENCE_KEY)!! findPreference<VectorPreference>(VectorPreferences.SETTINGS_OTHER_THIRD_PARTY_NOTICES_PREFERENCE_KEY)!!
.onPreferenceClickListener = Preference.OnPreferenceClickListener { .onPreferenceClickListener = Preference.OnPreferenceClickListener {
// See https://developers.google.com/android/guides/opensource // See https://developers.google.com/android/guides/opensource
startActivity(Intent(requireActivity(), OssLicensesMenuActivity::class.java)) openOssLicensesMenuActivity(requireActivity())
false false
} }
} }

View File

@ -32,6 +32,7 @@
android:title="@string/settings_rageshake"> android:title="@string/settings_rageshake">
<im.vector.riotx.core.preference.VectorSwitchPreference <im.vector.riotx.core.preference.VectorSwitchPreference
android:defaultValue="true"
android:key="SETTINGS_USE_RAGE_SHAKE_KEY" android:key="SETTINGS_USE_RAGE_SHAKE_KEY"
android:title="@string/send_bug_report_rage_shake" /> android:title="@string/send_bug_report_rage_shake" />

View File

@ -1,5 +1,6 @@
<?xml version="1.0" encoding="utf-8"?> <?xml version="1.0" encoding="utf-8"?>
<androidx.preference.PreferenceScreen xmlns:android="http://schemas.android.com/apk/res/android" <androidx.preference.PreferenceScreen xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"> xmlns:tools="http://schemas.android.com/tools">
<im.vector.riotx.core.preference.VectorPreference <im.vector.riotx.core.preference.VectorPreference
@ -40,6 +41,7 @@
<im.vector.riotx.core.preference.VectorPreference <im.vector.riotx.core.preference.VectorPreference
android:key="SETTINGS_OTHER_THIRD_PARTY_NOTICES_PREFERENCE_KEY" android:key="SETTINGS_OTHER_THIRD_PARTY_NOTICES_PREFERENCE_KEY"
android:title="@string/settings_other_third_party_notices" /> android:title="@string/settings_other_third_party_notices"
app:isPreferenceVisible="@bool/isGplay" />
</androidx.preference.PreferenceScreen> </androidx.preference.PreferenceScreen>