Show files shared by chat message in app if possible
This commit is contained in:
parent
5b529e8e3a
commit
b818bf0155
26 changed files with 965 additions and 21 deletions
|
@ -23,6 +23,8 @@ import android.annotation.SuppressLint
|
||||||
import android.content.pm.ActivityInfo
|
import android.content.pm.ActivityInfo
|
||||||
import android.content.res.Configuration
|
import android.content.res.Configuration
|
||||||
import android.os.Bundle
|
import android.os.Bundle
|
||||||
|
import android.util.DisplayMetrics
|
||||||
|
import android.view.Display
|
||||||
import android.view.Surface
|
import android.view.Surface
|
||||||
import androidx.appcompat.app.AppCompatActivity
|
import androidx.appcompat.app.AppCompatActivity
|
||||||
import androidx.appcompat.app.AppCompatDelegate
|
import androidx.appcompat.app.AppCompatDelegate
|
||||||
|
@ -73,6 +75,8 @@ abstract class GenericActivity : AppCompatActivity() {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
updateScreenSize()
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun onResume() {
|
override fun onResume() {
|
||||||
|
@ -102,4 +106,14 @@ abstract class GenericActivity : AppCompatActivity() {
|
||||||
fun isTablet(): Boolean {
|
fun isTablet(): Boolean {
|
||||||
return resources.getBoolean(R.bool.isTablet)
|
return resources.getBoolean(R.bool.isTablet)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private fun updateScreenSize() {
|
||||||
|
val metrics = DisplayMetrics()
|
||||||
|
val display: Display = windowManager.defaultDisplay
|
||||||
|
display.getRealMetrics(metrics)
|
||||||
|
val screenWidth = metrics.widthPixels.toFloat()
|
||||||
|
val screenHeight = metrics.heightPixels.toFloat()
|
||||||
|
coreContext.screenWidth = screenWidth
|
||||||
|
coreContext.screenHeight = screenHeight
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -348,6 +348,42 @@ internal fun DetailChatRoomFragment.navigateToEphemeralInfo() {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
internal fun DetailChatRoomFragment.navigateToTextFileViewer(secure: Boolean) {
|
||||||
|
val bundle = bundleOf("Secure" to secure)
|
||||||
|
findMasterNavController().navigate(
|
||||||
|
R.id.action_global_textViewerFragment,
|
||||||
|
bundle,
|
||||||
|
getRightToLeftAnimationNavOptions()
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
internal fun DetailChatRoomFragment.navigateToPdfFileViewer(secure: Boolean) {
|
||||||
|
val bundle = bundleOf("Secure" to secure)
|
||||||
|
findMasterNavController().navigate(
|
||||||
|
R.id.action_global_pdfViewerFragment,
|
||||||
|
bundle,
|
||||||
|
getRightToLeftAnimationNavOptions()
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
internal fun DetailChatRoomFragment.navigateToImageFileViewer(secure: Boolean) {
|
||||||
|
val bundle = bundleOf("Secure" to secure)
|
||||||
|
findMasterNavController().navigate(
|
||||||
|
R.id.action_global_imageViewerFragment,
|
||||||
|
bundle,
|
||||||
|
getRightToLeftAnimationNavOptions()
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
internal fun DetailChatRoomFragment.navigateToVideoFileViewer(secure: Boolean) {
|
||||||
|
val bundle = bundleOf("Secure" to secure)
|
||||||
|
findMasterNavController().navigate(
|
||||||
|
R.id.action_global_videoViewerFragment,
|
||||||
|
bundle,
|
||||||
|
getRightToLeftAnimationNavOptions()
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
internal fun ChatRoomCreationFragment.navigateToGroupInfo() {
|
internal fun ChatRoomCreationFragment.navigateToGroupInfo() {
|
||||||
if (findNavController().currentDestination?.id == R.id.chatRoomCreationFragment) {
|
if (findNavController().currentDestination?.id == R.id.chatRoomCreationFragment) {
|
||||||
findNavController().navigate(
|
findNavController().navigate(
|
||||||
|
|
|
@ -24,8 +24,6 @@ import android.animation.ValueAnimator
|
||||||
import android.annotation.TargetApi
|
import android.annotation.TargetApi
|
||||||
import android.content.pm.PackageManager
|
import android.content.pm.PackageManager
|
||||||
import android.os.Bundle
|
import android.os.Bundle
|
||||||
import android.util.DisplayMetrics
|
|
||||||
import android.view.Display
|
|
||||||
import androidx.databinding.DataBindingUtil
|
import androidx.databinding.DataBindingUtil
|
||||||
import androidx.lifecycle.ViewModelProvider
|
import androidx.lifecycle.ViewModelProvider
|
||||||
import com.google.android.flexbox.FlexboxLayout
|
import com.google.android.flexbox.FlexboxLayout
|
||||||
|
@ -179,10 +177,7 @@ class OutgoingCallActivity : ProximitySensorActivity() {
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun initNumpadLayout() {
|
private fun initNumpadLayout() {
|
||||||
val metrics = DisplayMetrics()
|
val screenWidth = coreContext.screenWidth
|
||||||
val display: Display = windowManager.defaultDisplay
|
|
||||||
display.getRealMetrics(metrics)
|
|
||||||
val screenWidth = metrics.widthPixels.toFloat()
|
|
||||||
numpadAnimator = ValueAnimator.ofFloat(screenWidth, 0f).apply {
|
numpadAnimator = ValueAnimator.ofFloat(screenWidth, 0f).apply {
|
||||||
addUpdateListener {
|
addUpdateListener {
|
||||||
val value = it.animatedValue as Float
|
val value = it.animatedValue as Float
|
||||||
|
|
|
@ -27,8 +27,6 @@ import android.content.Intent
|
||||||
import android.content.pm.PackageManager.PERMISSION_GRANTED
|
import android.content.pm.PackageManager.PERMISSION_GRANTED
|
||||||
import android.os.Bundle
|
import android.os.Bundle
|
||||||
import android.os.SystemClock
|
import android.os.SystemClock
|
||||||
import android.util.DisplayMetrics
|
|
||||||
import android.view.Display
|
|
||||||
import androidx.lifecycle.ViewModelProvider
|
import androidx.lifecycle.ViewModelProvider
|
||||||
import com.google.android.flexbox.FlexboxLayout
|
import com.google.android.flexbox.FlexboxLayout
|
||||||
import org.linphone.LinphoneApplication.Companion.coreContext
|
import org.linphone.LinphoneApplication.Companion.coreContext
|
||||||
|
@ -242,10 +240,7 @@ class ControlsFragment : GenericFragment<CallControlsFragmentBinding>() {
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun initNumpadLayout() {
|
private fun initNumpadLayout() {
|
||||||
val metrics = DisplayMetrics()
|
val screenWidth = coreContext.screenWidth
|
||||||
val display: Display = requireActivity().windowManager.defaultDisplay
|
|
||||||
display.getRealMetrics(metrics)
|
|
||||||
val screenWidth = metrics.widthPixels.toFloat()
|
|
||||||
numpadAnimator = ValueAnimator.ofFloat(screenWidth, 0f).apply {
|
numpadAnimator = ValueAnimator.ofFloat(screenWidth, 0f).apply {
|
||||||
addUpdateListener {
|
addUpdateListener {
|
||||||
val value = it.animatedValue as Float
|
val value = it.animatedValue as Float
|
||||||
|
|
|
@ -70,6 +70,7 @@ class MainActivity : GenericActivity(), SnackBarActivity, NavController.OnDestin
|
||||||
}
|
}
|
||||||
|
|
||||||
private lateinit var tabsFragment: FragmentContainerView
|
private lateinit var tabsFragment: FragmentContainerView
|
||||||
|
private lateinit var statusFragment: FragmentContainerView
|
||||||
|
|
||||||
override fun onCreate(savedInstanceState: Bundle?) {
|
override fun onCreate(savedInstanceState: Bundle?) {
|
||||||
super.onCreate(savedInstanceState)
|
super.onCreate(savedInstanceState)
|
||||||
|
@ -110,6 +111,7 @@ class MainActivity : GenericActivity(), SnackBarActivity, NavController.OnDestin
|
||||||
}
|
}
|
||||||
|
|
||||||
tabsFragment = findViewById(R.id.tabs_fragment)
|
tabsFragment = findViewById(R.id.tabs_fragment)
|
||||||
|
statusFragment = findViewById(R.id.status_fragment)
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun onNewIntent(intent: Intent?) {
|
override fun onNewIntent(intent: Intent?) {
|
||||||
|
@ -154,6 +156,9 @@ class MainActivity : GenericActivity(), SnackBarActivity, NavController.OnDestin
|
||||||
arguments: Bundle?
|
arguments: Bundle?
|
||||||
) {
|
) {
|
||||||
currentFocus?.hideKeyboard()
|
currentFocus?.hideKeyboard()
|
||||||
|
if (statusFragment.visibility == View.GONE) {
|
||||||
|
statusFragment.visibility = View.VISIBLE
|
||||||
|
}
|
||||||
|
|
||||||
val motionLayout: MotionLayout = binding.content as MotionLayout
|
val motionLayout: MotionLayout = binding.content as MotionLayout
|
||||||
if (corePreferences.enableAnimations) {
|
if (corePreferences.enableAnimations) {
|
||||||
|
@ -171,6 +176,10 @@ class MainActivity : GenericActivity(), SnackBarActivity, NavController.OnDestin
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fun hideStatusFragment() {
|
||||||
|
statusFragment.visibility = View.GONE
|
||||||
|
}
|
||||||
|
|
||||||
private fun View.hideKeyboard() {
|
private fun View.hideKeyboard() {
|
||||||
val imm = context.getSystemService(Activity.INPUT_METHOD_SERVICE) as InputMethodManager
|
val imm = context.getSystemService(Activity.INPUT_METHOD_SERVICE) as InputMethodManager
|
||||||
imm.hideSoftInputFromWindow(windowToken, 0)
|
imm.hideSoftInputFromWindow(windowToken, 0)
|
||||||
|
|
|
@ -41,6 +41,7 @@ import androidx.lifecycle.lifecycleScope
|
||||||
import androidx.navigation.fragment.findNavController
|
import androidx.navigation.fragment.findNavController
|
||||||
import androidx.recyclerview.widget.LinearLayoutManager
|
import androidx.recyclerview.widget.LinearLayoutManager
|
||||||
import androidx.recyclerview.widget.RecyclerView
|
import androidx.recyclerview.widget.RecyclerView
|
||||||
|
import java.io.File
|
||||||
import kotlinx.coroutines.launch
|
import kotlinx.coroutines.launch
|
||||||
import org.linphone.LinphoneApplication.Companion.coreContext
|
import org.linphone.LinphoneApplication.Companion.coreContext
|
||||||
import org.linphone.LinphoneApplication.Companion.corePreferences
|
import org.linphone.LinphoneApplication.Companion.corePreferences
|
||||||
|
@ -225,7 +226,19 @@ class DetailChatRoomFragment : MasterFragment<ChatRoomDetailFragmentBinding, Cha
|
||||||
|
|
||||||
adapter.openContentEvent.observe(viewLifecycleOwner, {
|
adapter.openContentEvent.observe(viewLifecycleOwner, {
|
||||||
it.consume { path ->
|
it.consume { path ->
|
||||||
openFile(path)
|
if (!File(path).exists()) {
|
||||||
|
(requireActivity() as MainActivity).showSnackBar(R.string.chat_room_file_not_found)
|
||||||
|
} else {
|
||||||
|
Log.i("[Chat Message] Opening file: $path")
|
||||||
|
sharedViewModel.fileToOpen.value = path
|
||||||
|
when {
|
||||||
|
FileUtils.isExtensionImage(path) -> navigateToImageFileViewer(viewModel.chatRoom.currentParams.encryptionEnabled())
|
||||||
|
FileUtils.isExtensionVideo(path) -> navigateToVideoFileViewer(viewModel.chatRoom.currentParams.encryptionEnabled())
|
||||||
|
FileUtils.isExtensionPdf(path) -> navigateToPdfFileViewer(viewModel.chatRoom.currentParams.encryptionEnabled())
|
||||||
|
FileUtils.isPlainTextFile(path) -> navigateToTextFileViewer(viewModel.chatRoom.currentParams.encryptionEnabled())
|
||||||
|
else -> openFile(path)
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
|
||||||
|
@ -581,14 +594,7 @@ class DetailChatRoomFragment : MasterFragment<ChatRoomDetailFragmentBinding, Cha
|
||||||
|
|
||||||
dialogViewModel.showOkButton({
|
dialogViewModel.showOkButton({
|
||||||
dialog.dismiss()
|
dialog.dismiss()
|
||||||
intent.setDataAndType(contentUri, "text/plain")
|
navigateToTextFileViewer(viewModel.chatRoom.currentParams.encryptionEnabled())
|
||||||
try {
|
|
||||||
startActivity(intent)
|
|
||||||
} catch (anfe: ActivityNotFoundException) {
|
|
||||||
Log.e("[Chat Message] Couldn't find an activity to handle text/plain MIME type")
|
|
||||||
val activity = requireActivity() as MainActivity
|
|
||||||
activity.showSnackBar(R.string.chat_room_cant_open_file_no_app_found)
|
|
||||||
}
|
|
||||||
})
|
})
|
||||||
|
|
||||||
dialog.show()
|
dialog.show()
|
||||||
|
|
|
@ -0,0 +1,116 @@
|
||||||
|
/*
|
||||||
|
* Copyright (c) 2010-2021 Belledonne Communications SARL.
|
||||||
|
*
|
||||||
|
* This file is part of linphone-android
|
||||||
|
* (see https://www.linphone.org).
|
||||||
|
*
|
||||||
|
* This program is free software: you can redistribute it and/or modify
|
||||||
|
* it under the terms of the GNU General Public License as published by
|
||||||
|
* the Free Software Foundation, either version 3 of the License, or
|
||||||
|
* (at your option) any later version.
|
||||||
|
*
|
||||||
|
* This program is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
* GNU General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License
|
||||||
|
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
package org.linphone.activities.main.files.fragments
|
||||||
|
|
||||||
|
import android.annotation.SuppressLint
|
||||||
|
import android.os.Bundle
|
||||||
|
import android.view.GestureDetector
|
||||||
|
import android.view.MotionEvent
|
||||||
|
import android.view.ScaleGestureDetector
|
||||||
|
import androidx.lifecycle.ViewModelProvider
|
||||||
|
import org.linphone.R
|
||||||
|
import org.linphone.activities.main.files.viewmodels.ImageFileViewModel
|
||||||
|
import org.linphone.activities.main.files.viewmodels.ImageFileViewModelFactory
|
||||||
|
import org.linphone.activities.main.fragments.SecureFragment
|
||||||
|
import org.linphone.activities.main.viewmodels.SharedMainViewModel
|
||||||
|
import org.linphone.databinding.ImageViewerFragmentBinding
|
||||||
|
|
||||||
|
class ImageViewerFragment : SecureFragment<ImageViewerFragmentBinding>() {
|
||||||
|
private lateinit var viewModel: ImageFileViewModel
|
||||||
|
private lateinit var sharedViewModel: SharedMainViewModel
|
||||||
|
|
||||||
|
private lateinit var gestureDetector: GestureDetector
|
||||||
|
private lateinit var scaleGestureDetector: ScaleGestureDetector
|
||||||
|
private var scaleFactor = 1.0f
|
||||||
|
|
||||||
|
override fun getLayoutId(): Int = R.layout.image_viewer_fragment
|
||||||
|
|
||||||
|
@SuppressLint("ClickableViewAccessibility")
|
||||||
|
override fun onActivityCreated(savedInstanceState: Bundle?) {
|
||||||
|
super.onActivityCreated(savedInstanceState)
|
||||||
|
|
||||||
|
binding.lifecycleOwner = this
|
||||||
|
|
||||||
|
sharedViewModel = requireActivity().run {
|
||||||
|
ViewModelProvider(this).get(SharedMainViewModel::class.java)
|
||||||
|
}
|
||||||
|
|
||||||
|
val filePath = sharedViewModel.fileToOpen.value
|
||||||
|
filePath ?: return
|
||||||
|
|
||||||
|
viewModel = ViewModelProvider(
|
||||||
|
this,
|
||||||
|
ImageFileViewModelFactory(filePath)
|
||||||
|
)[ImageFileViewModel::class.java]
|
||||||
|
binding.viewModel = viewModel
|
||||||
|
|
||||||
|
isSecure = arguments?.getBoolean("Secure") ?: false
|
||||||
|
|
||||||
|
gestureDetector = GestureDetector(requireContext(), object :
|
||||||
|
GestureDetector.SimpleOnGestureListener() {
|
||||||
|
override fun onDoubleTap(e: MotionEvent?): Boolean {
|
||||||
|
scaleFactor = if (scaleFactor == 1.0f) 2.0f else 1.0f
|
||||||
|
binding.imageView.scaleX = scaleFactor
|
||||||
|
binding.imageView.scaleY = scaleFactor
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun onScroll(
|
||||||
|
e1: MotionEvent?,
|
||||||
|
e2: MotionEvent?,
|
||||||
|
distanceX: Float,
|
||||||
|
distanceY: Float
|
||||||
|
): Boolean {
|
||||||
|
if (scaleFactor <= 1.0f) return false
|
||||||
|
|
||||||
|
val scrollX = binding.imageView.scrollX + distanceX.toInt()
|
||||||
|
binding.imageView.scrollX = scrollX
|
||||||
|
|
||||||
|
val scrollY = binding.imageView.scrollY + distanceY.toInt()
|
||||||
|
binding.imageView.scrollY = scrollY
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
|
scaleGestureDetector = ScaleGestureDetector(requireContext(), object :
|
||||||
|
ScaleGestureDetector.SimpleOnScaleGestureListener() {
|
||||||
|
override fun onScale(detector: ScaleGestureDetector): Boolean {
|
||||||
|
scaleFactor *= detector.scaleFactor
|
||||||
|
scaleFactor = scaleFactor.coerceIn(0.1f, 5.0f)
|
||||||
|
binding.imageView.scaleX = scaleFactor
|
||||||
|
binding.imageView.scaleY = scaleFactor
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
|
binding.imageView.setOnTouchListener { _, event ->
|
||||||
|
val previousScaleFactor = scaleFactor
|
||||||
|
scaleGestureDetector.onTouchEvent(event)
|
||||||
|
|
||||||
|
if (previousScaleFactor != scaleFactor) {
|
||||||
|
// Prevent touch event from going further
|
||||||
|
return@setOnTouchListener true
|
||||||
|
}
|
||||||
|
|
||||||
|
gestureDetector.onTouchEvent(event)
|
||||||
|
return@setOnTouchListener true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,57 @@
|
||||||
|
/*
|
||||||
|
* Copyright (c) 2010-2021 Belledonne Communications SARL.
|
||||||
|
*
|
||||||
|
* This file is part of linphone-android
|
||||||
|
* (see https://www.linphone.org).
|
||||||
|
*
|
||||||
|
* This program is free software: you can redistribute it and/or modify
|
||||||
|
* it under the terms of the GNU General Public License as published by
|
||||||
|
* the Free Software Foundation, either version 3 of the License, or
|
||||||
|
* (at your option) any later version.
|
||||||
|
*
|
||||||
|
* This program is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
* GNU General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License
|
||||||
|
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
package org.linphone.activities.main.files.fragments
|
||||||
|
|
||||||
|
import android.os.Bundle
|
||||||
|
import androidx.lifecycle.ViewModelProvider
|
||||||
|
import org.linphone.R
|
||||||
|
import org.linphone.activities.main.files.viewmodels.PdfFileViewModel
|
||||||
|
import org.linphone.activities.main.files.viewmodels.PdfFileViewModelFactory
|
||||||
|
import org.linphone.activities.main.fragments.SecureFragment
|
||||||
|
import org.linphone.activities.main.viewmodels.SharedMainViewModel
|
||||||
|
import org.linphone.databinding.PdfViewerFragmentBinding
|
||||||
|
|
||||||
|
class PdfViewerFragment : SecureFragment<PdfViewerFragmentBinding>() {
|
||||||
|
private lateinit var viewModel: PdfFileViewModel
|
||||||
|
private lateinit var sharedViewModel: SharedMainViewModel
|
||||||
|
|
||||||
|
override fun getLayoutId(): Int = R.layout.pdf_viewer_fragment
|
||||||
|
|
||||||
|
override fun onActivityCreated(savedInstanceState: Bundle?) {
|
||||||
|
super.onActivityCreated(savedInstanceState)
|
||||||
|
|
||||||
|
binding.lifecycleOwner = this
|
||||||
|
|
||||||
|
sharedViewModel = requireActivity().run {
|
||||||
|
ViewModelProvider(this).get(SharedMainViewModel::class.java)
|
||||||
|
}
|
||||||
|
|
||||||
|
val filePath = sharedViewModel.fileToOpen.value
|
||||||
|
filePath ?: return
|
||||||
|
|
||||||
|
viewModel = ViewModelProvider(
|
||||||
|
this,
|
||||||
|
PdfFileViewModelFactory(filePath)
|
||||||
|
)[PdfFileViewModel::class.java]
|
||||||
|
binding.viewModel = viewModel
|
||||||
|
|
||||||
|
isSecure = arguments?.getBoolean("Secure") ?: false
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,57 @@
|
||||||
|
/*
|
||||||
|
* Copyright (c) 2010-2021 Belledonne Communications SARL.
|
||||||
|
*
|
||||||
|
* This file is part of linphone-android
|
||||||
|
* (see https://www.linphone.org).
|
||||||
|
*
|
||||||
|
* This program is free software: you can redistribute it and/or modify
|
||||||
|
* it under the terms of the GNU General Public License as published by
|
||||||
|
* the Free Software Foundation, either version 3 of the License, or
|
||||||
|
* (at your option) any later version.
|
||||||
|
*
|
||||||
|
* This program is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
* GNU General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License
|
||||||
|
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
package org.linphone.activities.main.files.fragments
|
||||||
|
|
||||||
|
import android.os.Bundle
|
||||||
|
import androidx.lifecycle.ViewModelProvider
|
||||||
|
import org.linphone.R
|
||||||
|
import org.linphone.activities.main.files.viewmodels.TextFileViewModel
|
||||||
|
import org.linphone.activities.main.files.viewmodels.TextFileViewModelFactory
|
||||||
|
import org.linphone.activities.main.fragments.SecureFragment
|
||||||
|
import org.linphone.activities.main.viewmodels.SharedMainViewModel
|
||||||
|
import org.linphone.databinding.TextViewerFragmentBinding
|
||||||
|
|
||||||
|
class TextViewerFragment : SecureFragment<TextViewerFragmentBinding>() {
|
||||||
|
private lateinit var viewModel: TextFileViewModel
|
||||||
|
private lateinit var sharedViewModel: SharedMainViewModel
|
||||||
|
|
||||||
|
override fun getLayoutId(): Int = R.layout.text_viewer_fragment
|
||||||
|
|
||||||
|
override fun onActivityCreated(savedInstanceState: Bundle?) {
|
||||||
|
super.onActivityCreated(savedInstanceState)
|
||||||
|
|
||||||
|
binding.lifecycleOwner = this
|
||||||
|
|
||||||
|
sharedViewModel = requireActivity().run {
|
||||||
|
ViewModelProvider(this).get(SharedMainViewModel::class.java)
|
||||||
|
}
|
||||||
|
|
||||||
|
val filePath = sharedViewModel.fileToOpen.value
|
||||||
|
filePath ?: return
|
||||||
|
|
||||||
|
viewModel = ViewModelProvider(
|
||||||
|
this,
|
||||||
|
TextFileViewModelFactory(filePath)
|
||||||
|
)[TextFileViewModel::class.java]
|
||||||
|
binding.viewModel = viewModel
|
||||||
|
|
||||||
|
isSecure = arguments?.getBoolean("Secure") ?: false
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,40 @@
|
||||||
|
/*
|
||||||
|
* Copyright (c) 2010-2021 Belledonne Communications SARL.
|
||||||
|
*
|
||||||
|
* This file is part of linphone-android
|
||||||
|
* (see https://www.linphone.org).
|
||||||
|
*
|
||||||
|
* This program is free software: you can redistribute it and/or modify
|
||||||
|
* it under the terms of the GNU General Public License as published by
|
||||||
|
* the Free Software Foundation, either version 3 of the License, or
|
||||||
|
* (at your option) any later version.
|
||||||
|
*
|
||||||
|
* This program is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
* GNU General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License
|
||||||
|
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
package org.linphone.activities.main.files.fragments
|
||||||
|
|
||||||
|
import android.os.Bundle
|
||||||
|
import androidx.navigation.fragment.findNavController
|
||||||
|
import org.linphone.R
|
||||||
|
import org.linphone.activities.GenericFragment
|
||||||
|
import org.linphone.databinding.FileViewerTopBarFragmentBinding
|
||||||
|
|
||||||
|
class TopBarFragment : GenericFragment<FileViewerTopBarFragmentBinding>() {
|
||||||
|
override fun getLayoutId(): Int = R.layout.file_viewer_top_bar_fragment
|
||||||
|
|
||||||
|
override fun onActivityCreated(savedInstanceState: Bundle?) {
|
||||||
|
super.onActivityCreated(savedInstanceState)
|
||||||
|
|
||||||
|
binding.lifecycleOwner = this
|
||||||
|
|
||||||
|
binding.setBackClickListener {
|
||||||
|
findNavController().popBackStack()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,65 @@
|
||||||
|
/*
|
||||||
|
* Copyright (c) 2010-2021 Belledonne Communications SARL.
|
||||||
|
*
|
||||||
|
* This file is part of linphone-android
|
||||||
|
* (see https://www.linphone.org).
|
||||||
|
*
|
||||||
|
* This program is free software: you can redistribute it and/or modify
|
||||||
|
* it under the terms of the GNU General Public License as published by
|
||||||
|
* the Free Software Foundation, either version 3 of the License, or
|
||||||
|
* (at your option) any later version.
|
||||||
|
*
|
||||||
|
* This program is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
* GNU General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License
|
||||||
|
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
package org.linphone.activities.main.files.fragments
|
||||||
|
|
||||||
|
import android.os.Bundle
|
||||||
|
import android.widget.MediaController
|
||||||
|
import androidx.lifecycle.ViewModelProvider
|
||||||
|
import org.linphone.R
|
||||||
|
import org.linphone.activities.main.files.viewmodels.VideoFileViewModel
|
||||||
|
import org.linphone.activities.main.files.viewmodels.VideoFileViewModelFactory
|
||||||
|
import org.linphone.activities.main.fragments.SecureFragment
|
||||||
|
import org.linphone.activities.main.viewmodels.SharedMainViewModel
|
||||||
|
import org.linphone.databinding.VideoViewerFragmentBinding
|
||||||
|
|
||||||
|
class VideoViewerFragment : SecureFragment<VideoViewerFragmentBinding>() {
|
||||||
|
private lateinit var viewModel: VideoFileViewModel
|
||||||
|
private lateinit var sharedViewModel: SharedMainViewModel
|
||||||
|
|
||||||
|
override fun getLayoutId(): Int = R.layout.video_viewer_fragment
|
||||||
|
|
||||||
|
override fun onActivityCreated(savedInstanceState: Bundle?) {
|
||||||
|
super.onActivityCreated(savedInstanceState)
|
||||||
|
|
||||||
|
binding.lifecycleOwner = this
|
||||||
|
|
||||||
|
sharedViewModel = requireActivity().run {
|
||||||
|
ViewModelProvider(this).get(SharedMainViewModel::class.java)
|
||||||
|
}
|
||||||
|
|
||||||
|
val filePath = sharedViewModel.fileToOpen.value
|
||||||
|
filePath ?: return
|
||||||
|
|
||||||
|
viewModel = ViewModelProvider(
|
||||||
|
this,
|
||||||
|
VideoFileViewModelFactory(filePath)
|
||||||
|
)[VideoFileViewModel::class.java]
|
||||||
|
binding.viewModel = viewModel
|
||||||
|
|
||||||
|
initVideoControls()
|
||||||
|
|
||||||
|
isSecure = arguments?.getBoolean("Secure") ?: false
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun initVideoControls() {
|
||||||
|
val mediaController = MediaController(requireContext())
|
||||||
|
viewModel.initMediaController(mediaController, binding.videoView)
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,34 @@
|
||||||
|
/*
|
||||||
|
* Copyright (c) 2010-2021 Belledonne Communications SARL.
|
||||||
|
*
|
||||||
|
* This file is part of linphone-android
|
||||||
|
* (see https://www.linphone.org).
|
||||||
|
*
|
||||||
|
* This program is free software: you can redistribute it and/or modify
|
||||||
|
* it under the terms of the GNU General Public License as published by
|
||||||
|
* the Free Software Foundation, either version 3 of the License, or
|
||||||
|
* (at your option) any later version.
|
||||||
|
*
|
||||||
|
* This program is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
* GNU General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License
|
||||||
|
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
package org.linphone.activities.main.files.viewmodels
|
||||||
|
|
||||||
|
import androidx.lifecycle.ViewModel
|
||||||
|
import androidx.lifecycle.ViewModelProvider
|
||||||
|
|
||||||
|
class ImageFileViewModelFactory(private val filePath: String) :
|
||||||
|
ViewModelProvider.NewInstanceFactory() {
|
||||||
|
|
||||||
|
@Suppress("UNCHECKED_CAST")
|
||||||
|
override fun <T : ViewModel?> create(modelClass: Class<T>): T {
|
||||||
|
return ImageFileViewModel(filePath) as T
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
class ImageFileViewModel(val filePath: String) : ViewModel()
|
|
@ -0,0 +1,108 @@
|
||||||
|
/*
|
||||||
|
* Copyright (c) 2010-2021 Belledonne Communications SARL.
|
||||||
|
*
|
||||||
|
* This file is part of linphone-android
|
||||||
|
* (see https://www.linphone.org).
|
||||||
|
*
|
||||||
|
* This program is free software: you can redistribute it and/or modify
|
||||||
|
* it under the terms of the GNU General Public License as published by
|
||||||
|
* the Free Software Foundation, either version 3 of the License, or
|
||||||
|
* (at your option) any later version.
|
||||||
|
*
|
||||||
|
* This program is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
* GNU General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License
|
||||||
|
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
package org.linphone.activities.main.files.viewmodels
|
||||||
|
|
||||||
|
import android.graphics.Bitmap
|
||||||
|
import android.graphics.pdf.PdfRenderer
|
||||||
|
import android.os.ParcelFileDescriptor
|
||||||
|
import androidx.lifecycle.MutableLiveData
|
||||||
|
import androidx.lifecycle.ViewModel
|
||||||
|
import androidx.lifecycle.ViewModelProvider
|
||||||
|
import androidx.lifecycle.viewModelScope
|
||||||
|
import java.io.File
|
||||||
|
import kotlinx.coroutines.Dispatchers
|
||||||
|
import kotlinx.coroutines.launch
|
||||||
|
import kotlinx.coroutines.withContext
|
||||||
|
import org.linphone.LinphoneApplication.Companion.coreContext
|
||||||
|
import org.linphone.core.tools.Log
|
||||||
|
|
||||||
|
class PdfFileViewModelFactory(private val filePath: String) :
|
||||||
|
ViewModelProvider.NewInstanceFactory() {
|
||||||
|
|
||||||
|
@Suppress("UNCHECKED_CAST")
|
||||||
|
override fun <T : ViewModel?> create(modelClass: Class<T>): T {
|
||||||
|
return PdfFileViewModel(filePath) as T
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
class PdfFileViewModel(filePath: String) : ViewModel() {
|
||||||
|
val operationInProgress = MutableLiveData<Boolean>()
|
||||||
|
|
||||||
|
val pages = MutableLiveData<ArrayList<PdfPageViewModel>>()
|
||||||
|
|
||||||
|
private val pdfRenderer: PdfRenderer
|
||||||
|
|
||||||
|
init {
|
||||||
|
operationInProgress.value = false
|
||||||
|
|
||||||
|
val input = ParcelFileDescriptor.open(File(filePath), ParcelFileDescriptor.MODE_READ_ONLY)
|
||||||
|
pdfRenderer = PdfRenderer(input)
|
||||||
|
Log.i("[PDF Viewer] ${pdfRenderer.pageCount} pages in file $filePath")
|
||||||
|
|
||||||
|
loadPdf()
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun onCleared() {
|
||||||
|
for (page in pages.value.orEmpty()) {
|
||||||
|
page.destroy()
|
||||||
|
}
|
||||||
|
pages.value?.clear()
|
||||||
|
super.onCleared()
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun loadPdf() {
|
||||||
|
viewModelScope.launch {
|
||||||
|
withContext(Dispatchers.IO) {
|
||||||
|
try {
|
||||||
|
operationInProgress.postValue(true)
|
||||||
|
|
||||||
|
for (index in 0 until pdfRenderer.pageCount) {
|
||||||
|
val page: PdfRenderer.Page = pdfRenderer.openPage(index)
|
||||||
|
val width = if (coreContext.screenWidth <= coreContext.screenHeight) coreContext.screenWidth else coreContext.screenHeight
|
||||||
|
val bm = Bitmap.createBitmap(
|
||||||
|
width.toInt(),
|
||||||
|
(width / page.width * page.height).toInt(),
|
||||||
|
Bitmap.Config.ARGB_8888
|
||||||
|
)
|
||||||
|
page.render(bm, null, null, PdfRenderer.Page.RENDER_MODE_FOR_DISPLAY)
|
||||||
|
page.close()
|
||||||
|
|
||||||
|
val pageViewModel = PdfPageViewModel(bm)
|
||||||
|
val list = arrayListOf<PdfPageViewModel>()
|
||||||
|
list.addAll(pages.value.orEmpty())
|
||||||
|
list.add(pageViewModel)
|
||||||
|
pages.postValue(list)
|
||||||
|
}
|
||||||
|
|
||||||
|
operationInProgress.postValue(false)
|
||||||
|
} catch (e: Exception) {
|
||||||
|
Log.e("[PDF Viewer] Exception: $e")
|
||||||
|
operationInProgress.postValue(false)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
class PdfPageViewModel(val bitmap: Bitmap) {
|
||||||
|
fun destroy() {
|
||||||
|
bitmap.recycle()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,78 @@
|
||||||
|
/*
|
||||||
|
* Copyright (c) 2010-2021 Belledonne Communications SARL.
|
||||||
|
*
|
||||||
|
* This file is part of linphone-android
|
||||||
|
* (see https://www.linphone.org).
|
||||||
|
*
|
||||||
|
* This program is free software: you can redistribute it and/or modify
|
||||||
|
* it under the terms of the GNU General Public License as published by
|
||||||
|
* the Free Software Foundation, either version 3 of the License, or
|
||||||
|
* (at your option) any later version.
|
||||||
|
*
|
||||||
|
* This program is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
* GNU General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License
|
||||||
|
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
package org.linphone.activities.main.files.viewmodels
|
||||||
|
|
||||||
|
import androidx.lifecycle.MutableLiveData
|
||||||
|
import androidx.lifecycle.ViewModel
|
||||||
|
import androidx.lifecycle.ViewModelProvider
|
||||||
|
import androidx.lifecycle.viewModelScope
|
||||||
|
import java.io.BufferedReader
|
||||||
|
import java.io.FileReader
|
||||||
|
import java.lang.StringBuilder
|
||||||
|
import kotlinx.coroutines.Dispatchers
|
||||||
|
import kotlinx.coroutines.launch
|
||||||
|
import kotlinx.coroutines.withContext
|
||||||
|
import org.linphone.core.tools.Log
|
||||||
|
|
||||||
|
class TextFileViewModelFactory(private val filePath: String) :
|
||||||
|
ViewModelProvider.NewInstanceFactory() {
|
||||||
|
|
||||||
|
@Suppress("UNCHECKED_CAST")
|
||||||
|
override fun <T : ViewModel?> create(modelClass: Class<T>): T {
|
||||||
|
return TextFileViewModel(filePath) as T
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
class TextFileViewModel(filePath: String) : ViewModel() {
|
||||||
|
val operationInProgress = MutableLiveData<Boolean>()
|
||||||
|
|
||||||
|
val text = MutableLiveData<String>()
|
||||||
|
|
||||||
|
init {
|
||||||
|
operationInProgress.value = false
|
||||||
|
|
||||||
|
openFile(filePath)
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun openFile(filePath: String) {
|
||||||
|
viewModelScope.launch {
|
||||||
|
withContext(Dispatchers.IO) {
|
||||||
|
operationInProgress.postValue(true)
|
||||||
|
|
||||||
|
try {
|
||||||
|
val br = BufferedReader(FileReader(filePath))
|
||||||
|
var line: String?
|
||||||
|
var textBuilder = StringBuilder()
|
||||||
|
while (br.readLine().also { line = it } != null) {
|
||||||
|
textBuilder.append(line)
|
||||||
|
textBuilder.append('\n')
|
||||||
|
}
|
||||||
|
br.close()
|
||||||
|
|
||||||
|
text.postValue(textBuilder.toString())
|
||||||
|
operationInProgress.postValue(false)
|
||||||
|
} catch (e: Exception) {
|
||||||
|
Log.e("[Text Viewer] Exception: $e")
|
||||||
|
operationInProgress.postValue(false)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,60 @@
|
||||||
|
/*
|
||||||
|
* Copyright (c) 2010-2021 Belledonne Communications SARL.
|
||||||
|
*
|
||||||
|
* This file is part of linphone-android
|
||||||
|
* (see https://www.linphone.org).
|
||||||
|
*
|
||||||
|
* This program is free software: you can redistribute it and/or modify
|
||||||
|
* it under the terms of the GNU General Public License as published by
|
||||||
|
* the Free Software Foundation, either version 3 of the License, or
|
||||||
|
* (at your option) any later version.
|
||||||
|
*
|
||||||
|
* This program is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
* GNU General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License
|
||||||
|
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
package org.linphone.activities.main.files.viewmodels
|
||||||
|
|
||||||
|
import android.widget.MediaController
|
||||||
|
import android.widget.VideoView
|
||||||
|
import androidx.lifecycle.ViewModel
|
||||||
|
import androidx.lifecycle.ViewModelProvider
|
||||||
|
import org.linphone.core.tools.Log
|
||||||
|
|
||||||
|
class VideoFileViewModelFactory(private val filePath: String) :
|
||||||
|
ViewModelProvider.NewInstanceFactory() {
|
||||||
|
|
||||||
|
@Suppress("UNCHECKED_CAST")
|
||||||
|
override fun <T : ViewModel?> create(modelClass: Class<T>): T {
|
||||||
|
return VideoFileViewModel(filePath) as T
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
class VideoFileViewModel(val filePath: String) : ViewModel() {
|
||||||
|
|
||||||
|
fun initMediaController(mediaController: MediaController, videoView: VideoView) {
|
||||||
|
videoView.setOnPreparedListener { mediaPlayer ->
|
||||||
|
mediaPlayer.setOnVideoSizeChangedListener { _, _, _ ->
|
||||||
|
videoView.setMediaController(mediaController)
|
||||||
|
// The following will make the video controls above the video
|
||||||
|
// mediaController.setAnchorView(videoView)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
videoView.setOnCompletionListener { mediaPlayer ->
|
||||||
|
mediaPlayer.release()
|
||||||
|
}
|
||||||
|
|
||||||
|
videoView.setOnErrorListener { _, what, extra ->
|
||||||
|
Log.e("[Video Viewer] Error: $what ($extra)")
|
||||||
|
false
|
||||||
|
}
|
||||||
|
|
||||||
|
videoView.setVideoPath(filePath)
|
||||||
|
videoView.start()
|
||||||
|
}
|
||||||
|
}
|
|
@ -48,6 +48,8 @@ class SharedMainViewModel : ViewModel() {
|
||||||
MutableLiveData<Event<ChatMessage>>()
|
MutableLiveData<Event<ChatMessage>>()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
val fileToOpen = MutableLiveData<String>()
|
||||||
|
|
||||||
var createEncryptedChatRoom: Boolean = false
|
var createEncryptedChatRoom: Boolean = false
|
||||||
|
|
||||||
val chatRoomParticipants = MutableLiveData<ArrayList<Address>>()
|
val chatRoomParticipants = MutableLiveData<ArrayList<Address>>()
|
||||||
|
|
|
@ -56,6 +56,9 @@ class CoreContext(val context: Context, coreConfig: Config) {
|
||||||
val core: Core
|
val core: Core
|
||||||
val handler: Handler = Handler(Looper.getMainLooper())
|
val handler: Handler = Handler(Looper.getMainLooper())
|
||||||
|
|
||||||
|
var screenWidth: Float = 0f
|
||||||
|
var screenHeight: Float = 0f
|
||||||
|
|
||||||
val appVersion: String by lazy {
|
val appVersion: String by lazy {
|
||||||
val appVersion = org.linphone.BuildConfig.VERSION_NAME
|
val appVersion = org.linphone.BuildConfig.VERSION_NAME
|
||||||
val appBranch = context.getString(R.string.linphone_app_branch)
|
val appBranch = context.getString(R.string.linphone_app_branch)
|
||||||
|
|
|
@ -59,6 +59,18 @@ class FileUtils {
|
||||||
return extension
|
return extension
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fun isPlainTextFile(path: String): Boolean {
|
||||||
|
val extension = getExtensionFromFileName(path).toLowerCase(Locale.getDefault())
|
||||||
|
val type = MimeTypeMap.getSingleton().getMimeTypeFromExtension(extension)
|
||||||
|
return type?.startsWith("text/plain") ?: false
|
||||||
|
}
|
||||||
|
|
||||||
|
fun isExtensionPdf(path: String): Boolean {
|
||||||
|
val extension = getExtensionFromFileName(path).toLowerCase(Locale.getDefault())
|
||||||
|
val type = MimeTypeMap.getSingleton().getMimeTypeFromExtension(extension)
|
||||||
|
return type?.startsWith("application/pdf") ?: false
|
||||||
|
}
|
||||||
|
|
||||||
fun isExtensionImage(path: String): Boolean {
|
fun isExtensionImage(path: String): Boolean {
|
||||||
val extension = getExtensionFromFileName(path).toLowerCase(Locale.getDefault())
|
val extension = getExtensionFromFileName(path).toLowerCase(Locale.getDefault())
|
||||||
val type = MimeTypeMap.getSingleton().getMimeTypeFromExtension(extension)
|
val type = MimeTypeMap.getSingleton().getMimeTypeFromExtension(extension)
|
||||||
|
|
38
app/src/main/res/layout/file_viewer_top_bar_fragment.xml
Normal file
38
app/src/main/res/layout/file_viewer_top_bar_fragment.xml
Normal file
|
@ -0,0 +1,38 @@
|
||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<layout xmlns:android="http://schemas.android.com/apk/res/android">
|
||||||
|
|
||||||
|
<data>
|
||||||
|
<import type="android.view.View"/>
|
||||||
|
<variable
|
||||||
|
name="backClickListener"
|
||||||
|
type="android.view.View.OnClickListener"/>
|
||||||
|
</data>
|
||||||
|
|
||||||
|
<LinearLayout
|
||||||
|
android:id="@+id/top_bar"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="60dp"
|
||||||
|
android:layout_gravity="center_horizontal"
|
||||||
|
android:background="?attr/lightToolbarBackgroundColor"
|
||||||
|
android:orientation="horizontal">
|
||||||
|
|
||||||
|
<ImageView
|
||||||
|
android:id="@+id/back"
|
||||||
|
android:onClick="@{backClickListener}"
|
||||||
|
android:contentDescription="@string/content_description_go_back"
|
||||||
|
android:layout_width="0dp"
|
||||||
|
android:layout_height="match_parent"
|
||||||
|
android:layout_weight="0.2"
|
||||||
|
android:background="?attr/button_background_drawable"
|
||||||
|
android:padding="18dp"
|
||||||
|
android:src="@drawable/back" />
|
||||||
|
|
||||||
|
<View
|
||||||
|
android:layout_width="0dp"
|
||||||
|
android:layout_height="match_parent"
|
||||||
|
android:layout_weight="0.8"
|
||||||
|
android:visibility="invisible" />
|
||||||
|
|
||||||
|
</LinearLayout>
|
||||||
|
|
||||||
|
</layout>
|
43
app/src/main/res/layout/image_viewer_fragment.xml
Normal file
43
app/src/main/res/layout/image_viewer_fragment.xml
Normal file
|
@ -0,0 +1,43 @@
|
||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<layout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||||
|
xmlns:tools="http://schemas.android.com/tools">
|
||||||
|
|
||||||
|
<data>
|
||||||
|
<import type="android.view.View"/>
|
||||||
|
<variable
|
||||||
|
name="viewModel"
|
||||||
|
type="org.linphone.activities.main.files.viewmodels.ImageFileViewModel" />
|
||||||
|
</data>
|
||||||
|
|
||||||
|
<RelativeLayout
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="match_parent"
|
||||||
|
android:background="@color/black_color">
|
||||||
|
|
||||||
|
<androidx.fragment.app.FragmentContainerView
|
||||||
|
android:id="@+id/top_bar_fragment"
|
||||||
|
android:name="org.linphone.activities.main.files.fragments.TopBarFragment"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:layout_alignParentTop="true"
|
||||||
|
tools:layout="@layout/file_viewer_top_bar_fragment" />
|
||||||
|
|
||||||
|
<LinearLayout
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="match_parent"
|
||||||
|
android:layout_below="@id/top_bar_fragment"
|
||||||
|
android:orientation="vertical">
|
||||||
|
|
||||||
|
<ImageView
|
||||||
|
android:id="@+id/imageView"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="match_parent"
|
||||||
|
android:adjustViewBounds="true"
|
||||||
|
android:scaleType="fitCenter"
|
||||||
|
glidePath="@{viewModel.filePath}"/>
|
||||||
|
|
||||||
|
</LinearLayout>
|
||||||
|
|
||||||
|
</RelativeLayout>
|
||||||
|
|
||||||
|
</layout>
|
23
app/src/main/res/layout/pdf_viewer_cell.xml
Normal file
23
app/src/main/res/layout/pdf_viewer_cell.xml
Normal file
|
@ -0,0 +1,23 @@
|
||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<layout xmlns:android="http://schemas.android.com/apk/res/android">
|
||||||
|
|
||||||
|
<data>
|
||||||
|
<import type="android.view.View"/>
|
||||||
|
<variable
|
||||||
|
name="data"
|
||||||
|
type="org.linphone.activities.main.files.viewmodels.PdfFileViewModel.PdfPageViewModel" />
|
||||||
|
</data>
|
||||||
|
|
||||||
|
<RelativeLayout
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="wrap_content">
|
||||||
|
|
||||||
|
<ImageView
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:layout_centerHorizontal="true"
|
||||||
|
android:src="@{data.bitmap}" />
|
||||||
|
|
||||||
|
</RelativeLayout>
|
||||||
|
|
||||||
|
</layout>
|
46
app/src/main/res/layout/pdf_viewer_fragment.xml
Normal file
46
app/src/main/res/layout/pdf_viewer_fragment.xml
Normal file
|
@ -0,0 +1,46 @@
|
||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<layout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||||
|
xmlns:bind="http://schemas.android.com/apk/res-auto"
|
||||||
|
xmlns:tools="http://schemas.android.com/tools">
|
||||||
|
|
||||||
|
<data>
|
||||||
|
<import type="android.view.View"/>
|
||||||
|
<variable
|
||||||
|
name="viewModel"
|
||||||
|
type="org.linphone.activities.main.files.viewmodels.PdfFileViewModel" />
|
||||||
|
</data>
|
||||||
|
|
||||||
|
<RelativeLayout
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="match_parent"
|
||||||
|
android:background="?attr/backgroundColor">
|
||||||
|
|
||||||
|
<androidx.fragment.app.FragmentContainerView
|
||||||
|
android:id="@+id/top_bar_fragment"
|
||||||
|
android:name="org.linphone.activities.main.files.fragments.TopBarFragment"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:layout_alignParentTop="true"
|
||||||
|
tools:layout="@layout/file_viewer_top_bar_fragment" />
|
||||||
|
|
||||||
|
<ScrollView
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="match_parent"
|
||||||
|
android:layout_below="@id/top_bar_fragment">
|
||||||
|
|
||||||
|
<LinearLayout
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:orientation="vertical"
|
||||||
|
bind:entries="@{viewModel.pages}"
|
||||||
|
bind:layout="@{@layout/pdf_viewer_cell}"/>
|
||||||
|
|
||||||
|
</ScrollView>
|
||||||
|
|
||||||
|
<include
|
||||||
|
layout="@layout/wait_layout"
|
||||||
|
bind:visibility="@{viewModel.operationInProgress}"/>
|
||||||
|
|
||||||
|
</RelativeLayout>
|
||||||
|
|
||||||
|
</layout>
|
46
app/src/main/res/layout/text_viewer_fragment.xml
Normal file
46
app/src/main/res/layout/text_viewer_fragment.xml
Normal file
|
@ -0,0 +1,46 @@
|
||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<layout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||||
|
xmlns:tools="http://schemas.android.com/tools"
|
||||||
|
xmlns:bind="http://schemas.android.com/apk/res-auto">
|
||||||
|
|
||||||
|
<data>
|
||||||
|
<import type="android.view.View"/>
|
||||||
|
<variable
|
||||||
|
name="viewModel"
|
||||||
|
type="org.linphone.activities.main.files.viewmodels.TextFileViewModel" />
|
||||||
|
</data>
|
||||||
|
|
||||||
|
<RelativeLayout
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="match_parent"
|
||||||
|
android:background="?attr/backgroundColor">
|
||||||
|
|
||||||
|
<androidx.fragment.app.FragmentContainerView
|
||||||
|
android:id="@+id/top_bar_fragment"
|
||||||
|
android:name="org.linphone.activities.main.files.fragments.TopBarFragment"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:layout_alignParentTop="true"
|
||||||
|
tools:layout="@layout/file_viewer_top_bar_fragment" />
|
||||||
|
|
||||||
|
<ScrollView
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="match_parent"
|
||||||
|
android:layout_below="@id/top_bar_fragment">
|
||||||
|
|
||||||
|
<TextView
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:layout_margin="10dp"
|
||||||
|
android:singleLine="false"
|
||||||
|
android:text="@{viewModel.text}"/>
|
||||||
|
|
||||||
|
</ScrollView>
|
||||||
|
|
||||||
|
<include
|
||||||
|
layout="@layout/wait_layout"
|
||||||
|
bind:visibility="@{viewModel.operationInProgress}"/>
|
||||||
|
|
||||||
|
</RelativeLayout>
|
||||||
|
|
||||||
|
</layout>
|
40
app/src/main/res/layout/video_viewer_fragment.xml
Normal file
40
app/src/main/res/layout/video_viewer_fragment.xml
Normal file
|
@ -0,0 +1,40 @@
|
||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<layout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||||
|
xmlns:tools="http://schemas.android.com/tools">
|
||||||
|
|
||||||
|
<data>
|
||||||
|
<import type="android.view.View"/>
|
||||||
|
<variable
|
||||||
|
name="viewModel"
|
||||||
|
type="org.linphone.activities.main.files.viewmodels.VideoFileViewModel" />
|
||||||
|
</data>
|
||||||
|
|
||||||
|
<RelativeLayout
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="match_parent"
|
||||||
|
android:background="@color/black_color">
|
||||||
|
|
||||||
|
<androidx.fragment.app.FragmentContainerView
|
||||||
|
android:id="@+id/top_bar_fragment"
|
||||||
|
android:name="org.linphone.activities.main.files.fragments.TopBarFragment"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:layout_alignParentTop="true"
|
||||||
|
tools:layout="@layout/file_viewer_top_bar_fragment" />
|
||||||
|
|
||||||
|
<RelativeLayout
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="match_parent"
|
||||||
|
android:layout_below="@id/top_bar_fragment">
|
||||||
|
|
||||||
|
<VideoView
|
||||||
|
android:id="@+id/video_view"
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:layout_centerInParent="true"/>
|
||||||
|
|
||||||
|
</RelativeLayout>
|
||||||
|
|
||||||
|
</RelativeLayout>
|
||||||
|
|
||||||
|
</layout>
|
|
@ -320,5 +320,25 @@
|
||||||
android:name="IsLinking"
|
android:name="IsLinking"
|
||||||
app:argType="boolean" />
|
app:argType="boolean" />
|
||||||
</fragment>
|
</fragment>
|
||||||
|
<fragment
|
||||||
|
android:id="@+id/textViewerFragment"
|
||||||
|
android:name="org.linphone.activities.main.files.fragments.TextViewerFragment"
|
||||||
|
android:label="TextViewerFragment" />
|
||||||
|
<action android:id="@+id/action_global_textViewerFragment" app:destination="@id/textViewerFragment" />
|
||||||
|
<fragment
|
||||||
|
android:id="@+id/pdfViewerFragment"
|
||||||
|
android:name="org.linphone.activities.main.files.fragments.PdfViewerFragment"
|
||||||
|
android:label="PdfViewerFragment" />
|
||||||
|
<action android:id="@+id/action_global_pdfViewerFragment" app:destination="@id/pdfViewerFragment" />
|
||||||
|
<fragment
|
||||||
|
android:id="@+id/imageViewerFragment"
|
||||||
|
android:name="org.linphone.activities.main.files.fragments.ImageViewerFragment"
|
||||||
|
android:label="ImageViewerFragment" />
|
||||||
|
<action android:id="@+id/action_global_imageViewerFragment" app:destination="@id/imageViewerFragment"/>
|
||||||
|
<fragment
|
||||||
|
android:id="@+id/videoViewerFragment"
|
||||||
|
android:name="org.linphone.activities.main.files.fragments.VideoViewerFragment"
|
||||||
|
android:label="VideoViewerFragment" />
|
||||||
|
<action android:id="@+id/action_global_videoViewerFragment" app:destination="@id/videoViewerFragment"/>
|
||||||
|
|
||||||
</navigation>
|
</navigation>
|
|
@ -173,6 +173,7 @@
|
||||||
<string name="chat_room_dummy_subject" translatable="false">dummy subject</string>
|
<string name="chat_room_dummy_subject" translatable="false">dummy subject</string>
|
||||||
<string name="chat_room_toast_choose_for_sharing">Select a conversation or create a new one</string>
|
<string name="chat_room_toast_choose_for_sharing">Select a conversation or create a new one</string>
|
||||||
<string name="chat_room_cant_open_file_no_app_found">Can\'t open file, no application available for this format.</string>
|
<string name="chat_room_cant_open_file_no_app_found">Can\'t open file, no application available for this format.</string>
|
||||||
|
<string name="chat_room_file_not_found">File not found</string>
|
||||||
<string name="chat_room_creation_failed">Chat room creation failed</string>
|
<string name="chat_room_creation_failed">Chat room creation failed</string>
|
||||||
<string name="chat_room_context_menu_group_info">Group info</string>
|
<string name="chat_room_context_menu_group_info">Group info</string>
|
||||||
<string name="chat_room_context_menu_participants_devices">Conversation\'s devices</string>
|
<string name="chat_room_context_menu_participants_devices">Conversation\'s devices</string>
|
||||||
|
|
Loading…
Reference in a new issue