Skip to content

Commit

Permalink
Merge pull request #619 from vector-im/feature/attachments
Browse files Browse the repository at this point in the history
Feature/attachments
  • Loading branch information
bmarty authored Oct 23, 2019
2 parents 7890e83 + cac5fb7 commit 70a14f6
Show file tree
Hide file tree
Showing 59 changed files with 1,609 additions and 252 deletions.
2 changes: 2 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -14,3 +14,5 @@
/tmp

ktlint
.idea/copyright/New_vector.xml
.idea/copyright/profiles_settings.xml
2 changes: 2 additions & 0 deletions CHANGES.md
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,8 @@ Improvements:
- Persist active tab between sessions (#503)
- Do not upload file too big for the homeserver (#587)
- Handle read markers (#84)
- Attachments: start using system pickers (#52)
- Attachments: start handling incoming share (#58)
- Mark all messages as read (#396)
- Add ability to report content (#515)

Expand Down
2 changes: 1 addition & 1 deletion vector/build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -316,7 +316,7 @@ dependencies {
implementation 'me.leolin:ShortcutBadger:1.1.22@aar'

// File picker
implementation 'com.github.jaiselrahman:FilePicker:1.2.2'
implementation 'com.kbeanie:multipicker:1.6@aar'

// DI
implementation "com.google.dagger:dagger:$daggerVersion"
Expand Down
17 changes: 17 additions & 0 deletions vector/src/main/AndroidManifest.xml
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@
package="im.vector.riotx">

<uses-permission android:name="android.permission.INTERNET" />
<uses-permission android:name="android.permission.READ_CONTACTS" />

<application
android:name=".VectorApplication"
Expand Down Expand Up @@ -79,6 +80,22 @@
</intent-filter>
</activity>

<activity android:name=".features.share.IncomingShareActivity">
<intent-filter>
<action android:name="android.intent.action.SEND" />
<data android:mimeType="*/*" />

<category android:name="android.intent.category.DEFAULT" />
<category android:name="android.intent.category.OPENABLE" />
</intent-filter>
<intent-filter>
<action android:name="android.intent.action.SEND_MULTIPLE" />
<data android:mimeType="*/*" />

<category android:name="android.intent.category.DEFAULT" />
<category android:name="android.intent.category.OPENABLE" />
</intent-filter>
</activity>
<!-- Services -->

<service
Expand Down
10 changes: 5 additions & 5 deletions vector/src/main/assets/open_source_licenses.html
Original file line number Diff line number Diff line change
Expand Up @@ -339,11 +339,6 @@ <h3>
<br/>
Copyright 2014 Leo Lin
</li>
<li>
<b>FilePicker</b>
<br/>
Copyright (c) 2018, Jaisel Rahman
</li>
<li>
<b>diff-match-patch</b>
<br/>
Expand All @@ -359,6 +354,11 @@ <h3>
<br/>
Copyright 2017 Gabriel Ittner.
</li>
<li>
<b>Android-multipicker-library</b>
<br/>
Copyright 2018 Kumar Bibek
</li>
</ul>
<pre>
Apache License
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
/*
* Copyright 2019 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 arrow.core.Option
import im.vector.matrix.android.api.session.Session
import im.vector.riotx.core.utils.RxStore
import javax.inject.Inject
import javax.inject.Singleton

@Singleton
class ActiveSessionObservableStore @Inject constructor() : RxStore<Option<Session>>()
Original file line number Diff line number Diff line change
Expand Up @@ -14,56 +14,59 @@
* limitations under the License.
*/

package im.vector.riotx.features.home
package im.vector.riotx

import androidx.lifecycle.Lifecycle
import androidx.lifecycle.LifecycleObserver
import androidx.lifecycle.OnLifecycleEvent
import arrow.core.Option
import com.airbnb.mvrx.ActivityViewModelContext
import com.airbnb.mvrx.MvRxState
import com.airbnb.mvrx.MvRxViewModelFactory
import com.airbnb.mvrx.ViewModelContext
import com.squareup.inject.assisted.Assisted
import com.squareup.inject.assisted.AssistedInject
import im.vector.matrix.android.api.session.Session
import im.vector.matrix.android.api.session.group.model.GroupSummary
import im.vector.matrix.android.api.session.room.model.RoomSummary
import im.vector.matrix.rx.rx
import im.vector.riotx.core.platform.VectorViewModel
import im.vector.riotx.features.home.HomeRoomListObservableStore
import im.vector.riotx.features.home.group.ALL_COMMUNITIES_GROUP_ID
import im.vector.riotx.features.home.group.SelectedGroupStore
import io.reactivex.Observable
import io.reactivex.android.schedulers.AndroidSchedulers
import io.reactivex.disposables.CompositeDisposable
import io.reactivex.functions.BiFunction
import io.reactivex.rxkotlin.addTo
import java.util.concurrent.TimeUnit
import javax.inject.Inject
import javax.inject.Singleton

data class EmptyState(val isEmpty: Boolean = true) : MvRxState

class HomeActivityViewModel @AssistedInject constructor(@Assisted initialState: EmptyState,
private val session: Session,
private val selectedGroupStore: SelectedGroupStore,
private val homeRoomListStore: HomeRoomListObservableStore
) : VectorViewModel<EmptyState>(initialState) {

@AssistedInject.Factory
interface Factory {
fun create(initialState: EmptyState): HomeActivityViewModel
}
/**
* This class handles the global app state. At the moment, it only manages room list.
* It requires to be added to ProcessLifecycleOwner.get().lifecycle
*/
@Singleton
class AppStateHandler @Inject constructor(
private val sessionObservableStore: ActiveSessionObservableStore,
private val homeRoomListStore: HomeRoomListObservableStore,
private val selectedGroupStore: SelectedGroupStore) : LifecycleObserver {

companion object : MvRxViewModelFactory<HomeActivityViewModel, EmptyState> {
private val compositeDisposable = CompositeDisposable()

@JvmStatic
override fun create(viewModelContext: ViewModelContext, state: EmptyState): HomeActivityViewModel? {
val homeActivity: HomeActivity = (viewModelContext as ActivityViewModelContext).activity()
return homeActivity.homeActivityViewModelFactory.create(state)
}
@OnLifecycleEvent(Lifecycle.Event.ON_RESUME)
fun entersForeground() {
observeRoomsAndGroup()
}

init {
observeRoomAndGroup()
@OnLifecycleEvent(Lifecycle.Event.ON_PAUSE)
fun entersBackground() {
compositeDisposable.clear()
}

private fun observeRoomAndGroup() {
private fun observeRoomsAndGroup() {
Observable
.combineLatest<List<RoomSummary>, Option<GroupSummary>, List<RoomSummary>>(
session.rx().liveRoomSummaries().throttleLast(300, TimeUnit.MILLISECONDS),
sessionObservableStore.observe()
.observeOn(AndroidSchedulers.mainThread())
.switchMap {
it.orNull()?.rx()?.liveRoomSummaries()
?: Observable.just(emptyList())
}
.throttleLast(300, TimeUnit.MILLISECONDS),
selectedGroupStore.observe(),
BiFunction { rooms, selectedGroupOption ->
val selectedGroup = selectedGroupOption.orNull()
Expand All @@ -83,14 +86,14 @@ class HomeActivityViewModel @AssistedInject constructor(@Assisted initialState:
.filter { !it.isDirect }
.filter {
selectedGroup?.groupId == ALL_COMMUNITIES_GROUP_ID
|| selectedGroup?.roomIds?.contains(it.roomId) ?: true
|| selectedGroup?.roomIds?.contains(it.roomId) ?: true
}
filteredDirectRooms + filteredGroupRooms
}
)
.subscribe {
homeRoomListStore.post(it)
}
.disposeOnClear()
.addTo(compositeDisposable)
}
}
2 changes: 2 additions & 0 deletions vector/src/main/java/im/vector/riotx/VectorApplication.kt
Original file line number Diff line number Diff line change
Expand Up @@ -74,6 +74,7 @@ class VectorApplication : Application(), HasVectorInjector, MatrixConfiguration.
@Inject lateinit var vectorPreferences: VectorPreferences
@Inject lateinit var versionProvider: VersionProvider
@Inject lateinit var notificationUtils: NotificationUtils
@Inject lateinit var appStateHandler: AppStateHandler
lateinit var vectorComponent: VectorComponent
private var fontThreadHandler: Handler? = null

Expand Down Expand Up @@ -134,6 +135,7 @@ class VectorApplication : Application(), HasVectorInjector, MatrixConfiguration.
FcmHelper.onEnterBackground(appContext, vectorPreferences, activeSessionHolder)
}
})
ProcessLifecycleOwner.get().lifecycle.addObserver(appStateHandler)
// This should be done as early as possible
initKnownEmojiHashSet(appContext)
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -16,8 +16,10 @@

package im.vector.riotx.core.di

import arrow.core.Option
import im.vector.matrix.android.api.auth.Authenticator
import im.vector.matrix.android.api.session.Session
import im.vector.riotx.ActiveSessionObservableStore
import im.vector.riotx.features.crypto.keysrequest.KeyRequestHandler
import im.vector.riotx.features.crypto.verification.IncomingVerificationRequestHandler
import java.util.concurrent.atomic.AtomicReference
Expand All @@ -26,6 +28,7 @@ import javax.inject.Singleton

@Singleton
class ActiveSessionHolder @Inject constructor(private val authenticator: Authenticator,
private val sessionObservableStore: ActiveSessionObservableStore,
private val keyRequestHandler: KeyRequestHandler,
private val incomingVerificationRequestHandler: IncomingVerificationRequestHandler
) {
Expand All @@ -34,12 +37,14 @@ class ActiveSessionHolder @Inject constructor(private val authenticator: Authent

fun setActiveSession(session: Session) {
activeSession.set(session)
sessionObservableStore.post(Option.fromNullable(session))
keyRequestHandler.start(session)
incomingVerificationRequestHandler.start(session)
}

fun clearActiveSession() {
activeSession.set(null)
sessionObservableStore.post(Option.empty())
keyRequestHandler.stop()
incomingVerificationRequestHandler.stop()
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -67,6 +67,7 @@ import im.vector.riotx.features.roomdirectory.picker.RoomDirectoryPickerFragment
import im.vector.riotx.features.roomdirectory.roompreview.RoomPreviewNoPreviewFragment
import im.vector.riotx.features.settings.*
import im.vector.riotx.features.settings.push.PushGatewaysFragment
import im.vector.riotx.features.share.IncomingShareActivity
import im.vector.riotx.features.ui.UiStateRepository

@Component(dependencies = [VectorComponent::class], modules = [AssistedInjectModule::class, ViewModelModule::class, HomeModule::class])
Expand Down Expand Up @@ -183,6 +184,8 @@ interface ScreenComponent {

fun inject(reactionButton: ReactionButton)

fun inject(incomingShareActivity: IncomingShareActivity)

@Component.Factory
interface Factory {
fun create(vectorComponent: VectorComponent,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -48,3 +48,10 @@ fun EditText.showPassword(visible: Boolean, updateCursor: Boolean = true) {
}
if (updateCursor) setSelection(text?.length ?: 0)
}

fun View.getMeasurements(): Pair<Int, Int> {
measure(View.MeasureSpec.UNSPECIFIED, View.MeasureSpec.UNSPECIFIED)
val width = measuredWidth
val height = measuredHeight
return width to height
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
/*
* Copyright 2019 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.core.utils

import android.app.Activity
import android.graphics.Rect
import android.view.View
import android.view.ViewTreeObserver

class KeyboardStateUtils(activity: Activity) : ViewTreeObserver.OnGlobalLayoutListener {

private val contentView: View = activity.findViewById<View>(android.R.id.content).also {
it.viewTreeObserver.addOnGlobalLayoutListener(this)
}
var isKeyboardShowing: Boolean = false
private set

override fun onGlobalLayout() {
val rect = Rect()
contentView.getWindowVisibleDisplayFrame(rect)
val screenHeight = contentView.rootView.height

val keypadHeight = screenHeight - rect.bottom
isKeyboardShowing = keypadHeight > screenHeight * 0.15
}
}
Loading

0 comments on commit 70a14f6

Please sign in to comment.