mirror of
https://github.com/element-hq/element-android
synced 2024-11-24 18:35:40 +03:00
Attachments: try to improve a bit the UI and adding options [WIP]
This commit is contained in:
parent
ae5b6bd2b9
commit
20696353b8
16 changed files with 193 additions and 39 deletions
|
@ -32,6 +32,7 @@ import android.view.animation.AnimationSet
|
|||
import android.view.animation.OvershootInterpolator
|
||||
import android.view.animation.ScaleAnimation
|
||||
import android.view.animation.TranslateAnimation
|
||||
import android.widget.FrameLayout
|
||||
import android.widget.ImageButton
|
||||
import android.widget.LinearLayout
|
||||
import android.widget.PopupWindow
|
||||
|
@ -39,9 +40,12 @@ import androidx.core.view.doOnNextLayout
|
|||
import com.amulyakhare.textdrawable.TextDrawable
|
||||
import com.amulyakhare.textdrawable.util.ColorGenerator
|
||||
import im.vector.riotx.R
|
||||
import im.vector.riotx.core.utils.DimensionConverter
|
||||
import kotlin.math.max
|
||||
|
||||
class AttachmentTypeSelectorView(context: Context, var callback: Callback?)
|
||||
class AttachmentTypeSelectorView(context: Context,
|
||||
inflater: LayoutInflater,
|
||||
var callback: Callback?)
|
||||
: PopupWindow(context) {
|
||||
|
||||
interface Callback {
|
||||
|
@ -54,21 +58,25 @@ class AttachmentTypeSelectorView(context: Context, var callback: Callback?)
|
|||
private var cameraButton: ImageButton
|
||||
private var fileButton: ImageButton
|
||||
private var stickersButton: ImageButton
|
||||
private var audioButton: ImageButton
|
||||
private var contactButton: ImageButton
|
||||
|
||||
private var anchor: View? = null
|
||||
|
||||
init {
|
||||
val inflater = context.getSystemService(Context.LAYOUT_INFLATER_SERVICE) as LayoutInflater
|
||||
val layout = inflater.inflate(R.layout.attachment_type_selector, null, true)
|
||||
val root = FrameLayout(context)
|
||||
val layout = inflater.inflate(R.layout.view_attachment_type_selector, root, true)
|
||||
galleryButton = layout.findViewById<ImageButton>(R.id.attachmentGalleryButton).configure(TYPE_GALLERY)
|
||||
cameraButton = layout.findViewById<ImageButton>(R.id.attachmentCameraButton).configure(TYPE_CAMERA)
|
||||
fileButton = layout.findViewById<ImageButton>(R.id.attachmentFileButton).configure(TYPE_FILE)
|
||||
stickersButton = layout.findViewById<ImageButton>(R.id.attachmentStickersButton).configure(TYPE_STICKER)
|
||||
audioButton = layout.findViewById<ImageButton>(R.id.attachmentAudioButton).configure(TYPE_AUDIO)
|
||||
contactButton = layout.findViewById<ImageButton>(R.id.attachmentContactButton).configure(TYPE_CONTACT)
|
||||
contentView = layout
|
||||
width = LinearLayout.LayoutParams.MATCH_PARENT
|
||||
height = LinearLayout.LayoutParams.WRAP_CONTENT
|
||||
setBackgroundDrawable(BitmapDrawable())
|
||||
animationStyle = 0
|
||||
setBackgroundDrawable(BitmapDrawable())
|
||||
inputMethodMode = INPUT_METHOD_NOT_NEEDED
|
||||
isFocusable = true
|
||||
isTouchable = true
|
||||
|
@ -87,6 +95,8 @@ class AttachmentTypeSelectorView(context: Context, var callback: Callback?)
|
|||
animateButtonIn(galleryButton, ANIMATION_DURATION / 2)
|
||||
animateButtonIn(cameraButton, ANIMATION_DURATION / 2)
|
||||
animateButtonIn(fileButton, ANIMATION_DURATION / 4)
|
||||
animateButtonIn(audioButton, ANIMATION_DURATION / 2)
|
||||
animateButtonIn(contactButton, ANIMATION_DURATION / 4)
|
||||
animateButtonIn(stickersButton, 0)
|
||||
}
|
||||
}
|
||||
|
@ -193,6 +203,8 @@ class AttachmentTypeSelectorView(context: Context, var callback: Callback?)
|
|||
const val TYPE_GALLERY = 1
|
||||
const val TYPE_FILE = 2
|
||||
const val TYPE_STICKER = 3
|
||||
const val TYPE_AUDIO = 4
|
||||
const val TYPE_CONTACT = 5
|
||||
|
||||
private const val ANIMATION_DURATION = 250
|
||||
}
|
||||
|
|
|
@ -66,6 +66,10 @@ class AttachmentsHelper private constructor(private val pickerManagerFactory: Pi
|
|||
pickerManagerFactory.createFilePicker()
|
||||
}
|
||||
|
||||
private val audioPicker by lazy {
|
||||
pickerManagerFactory.createAudioPicker()
|
||||
}
|
||||
|
||||
// Restorable
|
||||
|
||||
override fun onSaveInstanceState(outState: Bundle) {
|
||||
|
@ -97,6 +101,13 @@ class AttachmentsHelper private constructor(private val pickerManagerFactory: Pi
|
|||
imagePicker.pickImage()
|
||||
}
|
||||
|
||||
/**
|
||||
* Starts the process for handling audio picking
|
||||
*/
|
||||
fun selectAudio() {
|
||||
audioPicker.pickAudio()
|
||||
}
|
||||
|
||||
/**
|
||||
* Starts the process for handling capture image picking
|
||||
*/
|
||||
|
|
|
@ -16,6 +16,7 @@
|
|||
|
||||
package im.vector.riotx.features.attachments
|
||||
|
||||
import com.kbeanie.multipicker.api.entity.ChosenAudio
|
||||
import com.kbeanie.multipicker.api.entity.ChosenFile
|
||||
import com.kbeanie.multipicker.api.entity.ChosenImage
|
||||
import com.kbeanie.multipicker.api.entity.ChosenVideo
|
||||
|
@ -32,6 +33,18 @@ fun ChosenFile.toContentAttachmentData(): ContentAttachmentData {
|
|||
)
|
||||
}
|
||||
|
||||
fun ChosenAudio.toContentAttachmentData(): ContentAttachmentData {
|
||||
return ContentAttachmentData(
|
||||
path = originalPath,
|
||||
mimeType = mimeType,
|
||||
type = mapType(),
|
||||
size = size,
|
||||
date = createdAt.time,
|
||||
name = displayName,
|
||||
duration = duration
|
||||
)
|
||||
}
|
||||
|
||||
fun ChosenFile.mapType(): ContentAttachmentData.Type {
|
||||
return when {
|
||||
mimeType.startsWith("image/") -> ContentAttachmentData.Type.IMAGE
|
||||
|
|
|
@ -16,9 +16,12 @@
|
|||
|
||||
package im.vector.riotx.features.attachments
|
||||
|
||||
import com.kbeanie.multipicker.api.callbacks.AudioPickerCallback
|
||||
import com.kbeanie.multipicker.api.callbacks.ContactPickerCallback
|
||||
import com.kbeanie.multipicker.api.callbacks.FilePickerCallback
|
||||
import com.kbeanie.multipicker.api.callbacks.ImagePickerCallback
|
||||
import com.kbeanie.multipicker.api.callbacks.VideoPickerCallback
|
||||
import com.kbeanie.multipicker.api.entity.ChosenAudio
|
||||
import com.kbeanie.multipicker.api.entity.ChosenFile
|
||||
import com.kbeanie.multipicker.api.entity.ChosenImage
|
||||
import com.kbeanie.multipicker.api.entity.ChosenVideo
|
||||
|
@ -26,7 +29,18 @@ import com.kbeanie.multipicker.api.entity.ChosenVideo
|
|||
/**
|
||||
* This class delegates the PickerManager callbacks to an [AttachmentsHelper.Callback]
|
||||
*/
|
||||
class AttachmentsPickerCallback(private val callback: AttachmentsHelper.Callback) : ImagePickerCallback, FilePickerCallback, VideoPickerCallback {
|
||||
class AttachmentsPickerCallback(private val callback: AttachmentsHelper.Callback) : ImagePickerCallback, FilePickerCallback, VideoPickerCallback, AudioPickerCallback {
|
||||
|
||||
override fun onAudiosChosen(audios: MutableList<ChosenAudio>?) {
|
||||
if (audios.isNullOrEmpty()) {
|
||||
callback.onAttachmentsProcessFailed()
|
||||
} else {
|
||||
val attachments = audios.map {
|
||||
it.toContentAttachmentData()
|
||||
}
|
||||
callback.onAttachmentsReady(attachments)
|
||||
}
|
||||
}
|
||||
|
||||
override fun onFilesChosen(files: MutableList<ChosenFile>?) {
|
||||
if (files.isNullOrEmpty()) {
|
||||
|
|
|
@ -18,7 +18,9 @@ package im.vector.riotx.features.attachments
|
|||
|
||||
import android.app.Activity
|
||||
import androidx.fragment.app.Fragment
|
||||
import com.kbeanie.multipicker.api.AudioPicker
|
||||
import com.kbeanie.multipicker.api.CameraImagePicker
|
||||
import com.kbeanie.multipicker.api.ContactPicker
|
||||
import com.kbeanie.multipicker.api.FilePicker
|
||||
import com.kbeanie.multipicker.api.ImagePicker
|
||||
import com.kbeanie.multipicker.api.VideoPicker
|
||||
|
@ -33,6 +35,7 @@ interface PickerManagerFactory {
|
|||
|
||||
fun createFilePicker(): FilePicker
|
||||
|
||||
fun createAudioPicker(): AudioPicker
|
||||
|
||||
}
|
||||
|
||||
|
@ -67,6 +70,12 @@ class ActivityPickerManagerFactory(private val activity: Activity, callback: Att
|
|||
}
|
||||
}
|
||||
|
||||
override fun createAudioPicker(): AudioPicker {
|
||||
return AudioPicker(activity).also {
|
||||
it.allowMultiple()
|
||||
it.setAudioPickerCallback(attachmentsPickerCallback)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
class FragmentPickerManagerFactory(private val fragment: Fragment, callback: AttachmentsHelper.Callback) : PickerManagerFactory {
|
||||
|
@ -100,5 +109,12 @@ class FragmentPickerManagerFactory(private val fragment: Fragment, callback: Att
|
|||
}
|
||||
}
|
||||
|
||||
override fun createAudioPicker(): AudioPicker {
|
||||
return AudioPicker(fragment).also {
|
||||
it.allowMultiple()
|
||||
it.setAudioPickerCallback(attachmentsPickerCallback)
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
|
|
@ -622,9 +622,9 @@ class RoomDetailFragment :
|
|||
private fun setupAttachmentButton() {
|
||||
composerLayout.attachmentButton.setOnClickListener {
|
||||
if (!::attachmentTypeSelector.isInitialized) {
|
||||
attachmentTypeSelector = AttachmentTypeSelectorView(requireContext(), this)
|
||||
attachmentTypeSelector = AttachmentTypeSelectorView(vectorBaseActivity, vectorBaseActivity.layoutInflater, this)
|
||||
}
|
||||
attachmentTypeSelector.show(it)
|
||||
attachmentTypeSelector.show(composerLayout.attachmentButton)
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1114,7 +1114,10 @@ class RoomDetailFragment :
|
|||
AttachmentTypeSelectorView.TYPE_CAMERA -> attachmentsHelper.openCamera()
|
||||
AttachmentTypeSelectorView.TYPE_FILE -> attachmentsHelper.selectFile()
|
||||
AttachmentTypeSelectorView.TYPE_GALLERY -> attachmentsHelper.selectGallery()
|
||||
AttachmentTypeSelectorView.TYPE_AUDIO -> attachmentsHelper.selectAudio()
|
||||
AttachmentTypeSelectorView.TYPE_CONTACT -> vectorBaseActivity.notImplemented("Picking contacts")
|
||||
AttachmentTypeSelectorView.TYPE_STICKER -> vectorBaseActivity.notImplemented("Adding stickers")
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
|
|
Binary file not shown.
After Width: | Height: | Size: 707 B |
Binary file not shown.
After Width: | Height: | Size: 442 B |
Binary file not shown.
After Width: | Height: | Size: 928 B |
Binary file not shown.
After Width: | Height: | Size: 1.4 KiB |
Binary file not shown.
After Width: | Height: | Size: 1.9 KiB |
24
vector/src/main/res/drawable/bg_attachment_type_selector.xml
Normal file
24
vector/src/main/res/drawable/bg_attachment_type_selector.xml
Normal file
|
@ -0,0 +1,24 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<layer-list xmlns:android="http://schemas.android.com/apk/res/android">
|
||||
<item>
|
||||
<shape android:shape="rectangle">
|
||||
<solid android:color="?riotx_header_panel_border_mobile" />
|
||||
<corners android:radius="16dp" />
|
||||
</shape>
|
||||
</item>
|
||||
|
||||
<item
|
||||
android:bottom="1dp"
|
||||
android:left="1dp"
|
||||
android:right="1dp"
|
||||
android:top="1dp">
|
||||
<shape android:shape="rectangle">
|
||||
<solid android:color="?riotx_background" />
|
||||
<corners android:radius="16dp" />
|
||||
|
||||
</shape>
|
||||
|
||||
</item>
|
||||
|
||||
|
||||
</layer-list>
|
|
@ -0,0 +1,4 @@
|
|||
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
|
||||
<vector xmlns:android="http://schemas.android.com/apk/res/android" android:height="24dp" android:viewportHeight="24.0" android:viewportWidth="24.0" android:width="24dp">
|
||||
<path android:fillColor="#FFFFFF" android:pathData="M12,1c-4.97,0 -9,4.03 -9,9v7c0,1.66 1.34,3 3,3h3v-8H5v-2c0,-3.87 3.13,-7 7,-7s7,3.13 7,7v2h-4v8h3c1.66,0 3,-1.34 3,-3v-7c0,-4.97 -4.03,-9 -9,-9z"/>
|
||||
</vector>
|
|
@ -0,0 +1,4 @@
|
|||
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
|
||||
<vector xmlns:android="http://schemas.android.com/apk/res/android" android:height="24dp" android:viewportHeight="24.0" android:viewportWidth="24.0" android:width="24dp">
|
||||
<path android:fillColor="#FFFFFF" android:pathData="M16,11c1.66,0 2.99,-1.34 2.99,-3S17.66,5 16,5c-1.66,0 -3,1.34 -3,3s1.34,3 3,3zM8,11c1.66,0 2.99,-1.34 2.99,-3S9.66,5 8,5C6.34,5 5,6.34 5,8s1.34,3 3,3zM8,13c-2.33,0 -7,1.17 -7,3.5L1,19h14v-2.5c0,-2.33 -4.67,-3.5 -7,-3.5zM16,13c-0.29,0 -0.62,0.02 -0.97,0.05 1.16,0.84 1.97,1.97 1.97,3.45L17,19h6v-2.5c0,-2.33 -4.67,-3.5 -7,-3.5z"/>
|
||||
</vector>
|
|
@ -1,11 +1,15 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
|
||||
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
xmlns:tools="http://schemas.android.com/tools"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:background="@color/riotx_background_light">
|
||||
|
||||
android:background="@drawable/bg_attachment_type_selector"
|
||||
android:layout_marginStart="8dp"
|
||||
android:layout_marginEnd="8dp"
|
||||
android:orientation="vertical"
|
||||
android:paddingTop="16dp"
|
||||
android:paddingBottom="16dp">
|
||||
|
||||
<LinearLayout
|
||||
android:layout_width="match_parent"
|
||||
|
@ -13,7 +17,7 @@
|
|||
android:layout_margin="16dp"
|
||||
android:baselineAligned="false"
|
||||
android:orientation="horizontal"
|
||||
android:weightSum="4">
|
||||
android:weightSum="3">
|
||||
|
||||
<LinearLayout
|
||||
android:layout_width="match_parent"
|
||||
|
@ -24,16 +28,12 @@
|
|||
|
||||
<ImageButton
|
||||
android:id="@+id/attachmentCameraButton"
|
||||
android:layout_width="40dp"
|
||||
android:layout_height="40dp"
|
||||
android:scaleType="center"
|
||||
style="@style/AttachmentTypeSelectorButton"
|
||||
android:src="@drawable/ic_attachment_camera_white_24dp"
|
||||
tools:background="@color/colorAccent" />
|
||||
|
||||
<TextView
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginTop="8dp"
|
||||
style="@style/AttachmentTypeSelectorLabel"
|
||||
android:text="Camera" />
|
||||
|
||||
</LinearLayout>
|
||||
|
@ -48,16 +48,12 @@
|
|||
|
||||
<ImageButton
|
||||
android:id="@+id/attachmentGalleryButton"
|
||||
android:layout_width="40dp"
|
||||
android:layout_height="40dp"
|
||||
android:scaleType="center"
|
||||
style="@style/AttachmentTypeSelectorButton"
|
||||
android:src="@drawable/ic_attachment_gallery_white_24dp"
|
||||
tools:background="@color/colorAccent" />
|
||||
|
||||
<TextView
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginTop="8dp"
|
||||
style="@style/AttachmentTypeSelectorLabel"
|
||||
android:text="Gallery" />
|
||||
|
||||
</LinearLayout>
|
||||
|
@ -72,20 +68,66 @@
|
|||
|
||||
<ImageButton
|
||||
android:id="@+id/attachmentFileButton"
|
||||
android:layout_width="40dp"
|
||||
android:layout_height="40dp"
|
||||
android:scaleType="center"
|
||||
style="@style/AttachmentTypeSelectorButton"
|
||||
android:src="@drawable/ic_attachment_file_white_24dp"
|
||||
tools:background="@color/colorAccent" />
|
||||
|
||||
<TextView
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginTop="8dp"
|
||||
style="@style/AttachmentTypeSelectorLabel"
|
||||
android:text="File" />
|
||||
|
||||
</LinearLayout>
|
||||
|
||||
</LinearLayout>
|
||||
|
||||
<LinearLayout
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
android:layout_margin="16dp"
|
||||
android:baselineAligned="false"
|
||||
android:orientation="horizontal"
|
||||
android:weightSum="3">
|
||||
|
||||
<LinearLayout
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_weight="1"
|
||||
android:gravity="center"
|
||||
android:orientation="vertical">
|
||||
|
||||
<ImageButton
|
||||
android:id="@+id/attachmentAudioButton"
|
||||
style="@style/AttachmentTypeSelectorButton"
|
||||
android:src="@drawable/ic_attachment_audio_white_24dp"
|
||||
tools:background="@color/colorAccent" />
|
||||
|
||||
<TextView
|
||||
style="@style/AttachmentTypeSelectorLabel"
|
||||
android:text="Audio" />
|
||||
|
||||
</LinearLayout>
|
||||
|
||||
|
||||
<LinearLayout
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_weight="1"
|
||||
android:gravity="center"
|
||||
android:orientation="vertical">
|
||||
|
||||
<ImageButton
|
||||
android:id="@+id/attachmentContactButton"
|
||||
style="@style/AttachmentTypeSelectorButton"
|
||||
android:src="@drawable/ic_attachment_contact_white_24dp"
|
||||
tools:background="@color/colorAccent" />
|
||||
|
||||
<TextView
|
||||
style="@style/AttachmentTypeSelectorLabel"
|
||||
android:text="Contact" />
|
||||
|
||||
</LinearLayout>
|
||||
|
||||
|
||||
<LinearLayout
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
|
@ -95,20 +137,16 @@
|
|||
|
||||
<ImageButton
|
||||
android:id="@+id/attachmentStickersButton"
|
||||
android:layout_width="40dp"
|
||||
android:layout_height="40dp"
|
||||
android:scaleType="center"
|
||||
android:src="@drawable/ic_send_sticker"
|
||||
style="@style/AttachmentTypeSelectorButton"
|
||||
android:src="@drawable/ic_attachment_stickers_white_24dp"
|
||||
tools:background="@color/colorAccent" />
|
||||
|
||||
<TextView
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginTop="8dp"
|
||||
style="@style/AttachmentTypeSelectorLabel"
|
||||
android:text="Stickers" />
|
||||
|
||||
</LinearLayout>
|
||||
|
||||
|
||||
</LinearLayout>
|
||||
</FrameLayout>
|
||||
|
||||
|
||||
</LinearLayout>
|
|
@ -324,4 +324,19 @@
|
|||
<item name="android:textSize">12sp</item>
|
||||
</style>
|
||||
|
||||
|
||||
<style name="AttachmentTypeSelectorButton">
|
||||
<item name="android:layout_width">48dp</item>
|
||||
<item name="android:layout_height">48dp</item>
|
||||
<item name="android:scaleType">center</item>
|
||||
</style>
|
||||
|
||||
<style name="AttachmentTypeSelectorLabel">
|
||||
<item name="android:layout_width">wrap_content</item>
|
||||
<item name="android:layout_height">wrap_content</item>
|
||||
<item name="android:textColor">?riotx_text_primary</item>
|
||||
<item name="android:textSize">14sp</item>
|
||||
<item name="android:layout_marginTop">8dp</item>
|
||||
</style>
|
||||
|
||||
</resources>
|
Loading…
Reference in a new issue