Using the Compose version of our QR scanning

Deleting non needed files
This commit is contained in:
ThomasSession 2024-09-05 15:33:33 +10:00 committed by fanchao
parent a7843af306
commit fa90b746b2
9 changed files with 70 additions and 415 deletions

View File

@ -37,6 +37,8 @@ class JoinCommunityFragment : Fragment() {
lateinit var delegate: StartConversationDelegate
var lastUrl: String? = null
override fun onCreateView(
inflater: LayoutInflater, container: ViewGroup?,
savedInstanceState: Bundle?
@ -66,45 +68,71 @@ class JoinCommunityFragment : Fragment() {
}
fun joinCommunityIfPossible(url: String) {
val openGroup = try {
OpenGroupUrlParser.parseUrl(url)
} catch (e: OpenGroupUrlParser.Error) {
when (e) {
is OpenGroupUrlParser.Error.MalformedURL, OpenGroupUrlParser.Error.NoRoom -> {
return Toast.makeText(activity, context?.resources?.getString(R.string.communityJoinError), Toast.LENGTH_SHORT).show()
}
is OpenGroupUrlParser.Error.InvalidPublicKey, OpenGroupUrlParser.Error.NoPublicKey -> {
return Toast.makeText(activity, R.string.communityEnterUrlErrorInvalidDescription, Toast.LENGTH_SHORT).show()
if(lastUrl == url) return
lastUrl = url
lifecycleScope.launch(Dispatchers.Main) {
val openGroup = try {
OpenGroupUrlParser.parseUrl(url)
} catch (e: OpenGroupUrlParser.Error) {
when (e) {
is OpenGroupUrlParser.Error.MalformedURL, OpenGroupUrlParser.Error.NoRoom -> {
return@launch Toast.makeText(
activity,
context?.resources?.getString(R.string.communityJoinError),
Toast.LENGTH_SHORT
).show()
}
is OpenGroupUrlParser.Error.InvalidPublicKey, OpenGroupUrlParser.Error.NoPublicKey -> {
return@launch Toast.makeText(
activity,
R.string.communityEnterUrlErrorInvalidDescription,
Toast.LENGTH_SHORT
).show()
}
}
}
}
showLoader()
showLoader()
lifecycleScope.launch(Dispatchers.IO) {
try {
val sanitizedServer = openGroup.server.removeSuffix("/")
val openGroupID = "$sanitizedServer.${openGroup.room}"
OpenGroupManager.add(sanitizedServer, openGroup.room, openGroup.serverPublicKey, requireContext())
val storage = MessagingModuleConfiguration.shared.storage
storage.onOpenGroupAdded(sanitizedServer, openGroup.room)
val threadID = GroupManager.getOpenGroupThreadID(openGroupID, requireContext())
val groupID = GroupUtil.getEncodedOpenGroupID(openGroupID.toByteArray())
withContext(Dispatchers.IO) {
try {
val sanitizedServer = openGroup.server.removeSuffix("/")
val openGroupID = "$sanitizedServer.${openGroup.room}"
OpenGroupManager.add(
sanitizedServer,
openGroup.room,
openGroup.serverPublicKey,
requireContext()
)
val storage = MessagingModuleConfiguration.shared.storage
storage.onOpenGroupAdded(sanitizedServer, openGroup.room)
val threadID =
GroupManager.getOpenGroupThreadID(openGroupID, requireContext())
val groupID = GroupUtil.getEncodedOpenGroupID(openGroupID.toByteArray())
ConfigurationMessageUtilities.forceSyncConfigurationNowIfNeeded(requireContext())
withContext(Dispatchers.Main) {
val recipient = Recipient.from(requireContext(), Address.fromSerialized(groupID), false)
openConversationActivity(requireContext(), threadID, recipient)
delegate.onDialogClosePressed()
ConfigurationMessageUtilities.forceSyncConfigurationNowIfNeeded(
requireContext()
)
withContext(Dispatchers.Main) {
val recipient = Recipient.from(
requireContext(),
Address.fromSerialized(groupID),
false
)
openConversationActivity(requireContext(), threadID, recipient)
delegate.onDialogClosePressed()
}
} catch (e: Exception) {
Log.e("Loki", "Couldn't join community.", e)
withContext(Dispatchers.Main) {
hideLoader()
val txt = Phrase.from(context, R.string.groupErrorJoin)
.put(GROUP_NAME_KEY, url).format().toString()
Toast.makeText(activity, txt, Toast.LENGTH_SHORT).show()
}
}
} catch (e: Exception) {
Log.e("Loki", "Couldn't join community.", e)
withContext(Dispatchers.Main) {
hideLoader()
val txt = Phrase.from(context, R.string.groupErrorJoin).put(GROUP_NAME_KEY, url).format().toString()
Toast.makeText(activity, txt, Toast.LENGTH_SHORT).show()
}
return@launch
}
}
}

View File

@ -1,5 +0,0 @@
package org.thoughtcrime.securesms.qr;
public interface ScanListener {
public void onQrDataFound(String data);
}

View File

@ -1,125 +0,0 @@
package org.thoughtcrime.securesms.qr;
import android.content.res.Configuration;
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import com.google.zxing.BinaryBitmap;
import com.google.zxing.ChecksumException;
import com.google.zxing.DecodeHintType;
import com.google.zxing.FormatException;
import com.google.zxing.NotFoundException;
import com.google.zxing.PlanarYUVLuminanceSource;
import com.google.zxing.Result;
import com.google.zxing.common.HybridBinarizer;
import com.google.zxing.qrcode.QRCodeReader;
import org.thoughtcrime.securesms.components.camera.CameraView;
import org.thoughtcrime.securesms.components.camera.CameraView.PreviewFrame;
import org.session.libsignal.utilities.Log;
import org.session.libsession.utilities.Util;
import java.util.HashMap;
import java.util.Map;
import java.util.concurrent.atomic.AtomicReference;
public class ScanningThread extends Thread implements CameraView.PreviewCallback {
private static final String TAG = ScanningThread.class.getSimpleName();
private final QRCodeReader reader = new QRCodeReader();
private final AtomicReference<ScanListener> scanListener = new AtomicReference<>();
private final Map<DecodeHintType, String> hints = new HashMap<>();
private boolean scanning = true;
private PreviewFrame previewFrame;
public void setCharacterSet(String characterSet) {
hints.put(DecodeHintType.CHARACTER_SET, characterSet);
}
public void setScanListener(ScanListener scanListener) {
this.scanListener.set(scanListener);
}
@Override
public void onPreviewFrame(@NonNull PreviewFrame previewFrame) {
try {
synchronized (this) {
this.previewFrame = previewFrame;
this.notify();
}
} catch (RuntimeException e) {
Log.w(TAG, e);
}
}
@Override
public void run() {
while (true) {
PreviewFrame ourFrame;
synchronized (this) {
while (scanning && previewFrame == null) {
Util.wait(this, 0);
}
if (!scanning) return;
else ourFrame = previewFrame;
previewFrame = null;
}
String data = getScannedData(ourFrame.getData(), ourFrame.getWidth(), ourFrame.getHeight(), ourFrame.getOrientation());
ScanListener scanListener = this.scanListener.get();
if (data != null && scanListener != null) {
scanListener.onQrDataFound(data);
return;
}
}
}
public void stopScanning() {
synchronized (this) {
scanning = false;
notify();
}
}
private @Nullable String getScannedData(byte[] data, int width, int height, int orientation) {
try {
if (orientation == Configuration.ORIENTATION_PORTRAIT) {
byte[] rotatedData = new byte[data.length];
for (int y = 0; y < height; y++) {
for (int x = 0; x < width; x++) {
rotatedData[x * height + height - y - 1] = data[x + y * width];
}
}
int tmp = width;
width = height;
height = tmp;
data = rotatedData;
}
PlanarYUVLuminanceSource source = new PlanarYUVLuminanceSource(data, width, height,
0, 0, width, height,
false);
BinaryBitmap bitmap = new BinaryBitmap(new HybridBinarizer(source));
Result result = reader.decode(bitmap, hints);
if (result != null) return result.getText();
} catch (NullPointerException | ChecksumException | FormatException | IndexOutOfBoundsException e) {
Log.w(TAG, e);
} catch (NotFoundException e) {
// Thanks ZXing...
}
return null;
}
}

View File

@ -1,65 +0,0 @@
package org.thoughtcrime.securesms.util
import android.content.res.Configuration
import android.os.Bundle
import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
import android.widget.LinearLayout
import androidx.core.view.isVisible
import androidx.fragment.app.Fragment
import network.loki.messenger.databinding.FragmentScanQrCodeBinding
import org.thoughtcrime.securesms.qr.ScanListener
import org.thoughtcrime.securesms.qr.ScanningThread
class ScanQRCodeFragment : Fragment() {
private lateinit var binding: FragmentScanQrCodeBinding
private val scanningThread = ScanningThread()
var scanListener: ScanListener? = null
set(value) { field = value; scanningThread.setScanListener(scanListener) }
var message: CharSequence = ""
override fun onCreateView(layoutInflater: LayoutInflater, viewGroup: ViewGroup?, bundle: Bundle?): View {
binding = FragmentScanQrCodeBinding.inflate(layoutInflater, viewGroup, false)
return binding.root
}
override fun onViewCreated(view: View, bundle: Bundle?) {
super.onViewCreated(view, bundle)
when (resources.configuration.orientation) {
Configuration.ORIENTATION_LANDSCAPE -> binding.overlayView.orientation = LinearLayout.HORIZONTAL
else -> binding.overlayView.orientation = LinearLayout.VERTICAL
}
binding.messageTextView.text = message
binding.messageTextView.isVisible = message.isNotEmpty()
}
override fun onResume() {
super.onResume()
binding.cameraView.onResume()
binding.cameraView.setPreviewCallback(scanningThread)
try {
scanningThread.start()
} catch (exception: Exception) {
// Do nothing
}
scanningThread.setScanListener(scanListener)
}
override fun onConfigurationChanged(newConfiguration: Configuration) {
super.onConfigurationChanged(newConfiguration)
binding.cameraView.onPause()
when (newConfiguration.orientation) {
Configuration.ORIENTATION_LANDSCAPE -> binding.overlayView.orientation = LinearLayout.HORIZONTAL
else -> binding.overlayView.orientation = LinearLayout.VERTICAL
}
binding.cameraView.onResume()
binding.cameraView.setPreviewCallback(scanningThread)
}
override fun onPause() {
super.onPause()
this.binding.cameraView.onPause()
this.scanningThread.stopScanning()
}
}

View File

@ -1,34 +0,0 @@
package org.thoughtcrime.securesms.util
import android.os.Bundle
import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
import androidx.fragment.app.Fragment
import com.squareup.phrase.Phrase
import network.loki.messenger.R
import network.loki.messenger.databinding.FragmentScanQrCodePlaceholderBinding
import org.session.libsession.utilities.StringSubstitutionConstants.APP_NAME_KEY
class ScanQRCodePlaceholderFragment: Fragment() {
private lateinit var binding: FragmentScanQrCodePlaceholderBinding
var delegate: ScanQRCodePlaceholderFragmentDelegate? = null
override fun onCreateView(layoutInflater: LayoutInflater, viewGroup: ViewGroup?, bundle: Bundle?): View {
binding = FragmentScanQrCodePlaceholderBinding.inflate(layoutInflater, viewGroup, false)
return binding.root
}
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
super.onViewCreated(view, savedInstanceState)
binding.grantCameraAccessButton.setOnClickListener { delegate?.requestCameraAccess() }
binding.needCameraPermissionsTV.text = Phrase.from(context, R.string.cameraGrantAccessQr)
.put(APP_NAME_KEY, getString(R.string.app_name))
.format()
}
}
interface ScanQRCodePlaceholderFragmentDelegate {
fun requestCameraAccess()
}

View File

@ -1,89 +1,27 @@
package org.thoughtcrime.securesms.util
import android.Manifest
import android.content.pm.PackageManager
import android.os.Bundle
import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
import androidx.core.content.ContextCompat
import androidx.fragment.app.Fragment
import com.tbruyelle.rxpermissions2.RxPermissions
import network.loki.messenger.R
import org.thoughtcrime.securesms.qr.ScanListener
import kotlinx.coroutines.flow.emptyFlow
import org.thoughtcrime.securesms.ui.components.QRScannerScreen
import org.thoughtcrime.securesms.ui.createThemedComposeView
class ScanQRCodeWrapperFragment : Fragment(), ScanQRCodePlaceholderFragmentDelegate, ScanListener {
class ScanQRCodeWrapperFragment : Fragment() {
companion object {
const val FRAGMENT_TAG = "ScanQRCodeWrapperFragment_FRAGMENT_TAG"
}
var delegate: ScanQRCodeWrapperFragmentDelegate? = null
var message: CharSequence = ""
var enabled: Boolean = true
set(value) {
val shouldUpdate = field != value // update if value changes (view appears or disappears)
field = value
if (shouldUpdate) {
update()
}
}
@Deprecated("Deprecated in Java")
override fun setUserVisibleHint(isVisibleToUser: Boolean) {
super.setUserVisibleHint(isVisibleToUser)
enabled = isVisibleToUser
}
override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View? {
return inflater.inflate(R.layout.fragment_scan_qr_code_wrapper, container, false)
}
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
super.onViewCreated(view, savedInstanceState)
update()
}
private fun update() {
if (!this.isAdded) return
val fragment: Fragment
if (!enabled) {
val manager = childFragmentManager
manager.findFragmentByTag(FRAGMENT_TAG)?.let { existingFragment ->
// remove existing camera fragment (if switching back to other page)
manager.beginTransaction().remove(existingFragment).commit()
}
return
}
if (ContextCompat.checkSelfPermission(requireActivity(), Manifest.permission.CAMERA) == PackageManager.PERMISSION_GRANTED) {
val scanQRCodeFragment = ScanQRCodeFragment()
scanQRCodeFragment.scanListener = this
scanQRCodeFragment.message = message
fragment = scanQRCodeFragment
} else {
val scanQRCodePlaceholderFragment = ScanQRCodePlaceholderFragment()
scanQRCodePlaceholderFragment.delegate = this
fragment = scanQRCodePlaceholderFragment
}
val transaction = childFragmentManager.beginTransaction()
transaction.replace(R.id.fragmentContainer, fragment, FRAGMENT_TAG)
transaction.commit()
}
override fun requestCameraAccess() {
@SuppressWarnings("unused")
val unused = RxPermissions(this).request(Manifest.permission.CAMERA).subscribe { isGranted ->
if (isGranted) {
update()
}
}
}
override fun onQrDataFound(data: String) {
activity?.runOnUiThread {
delegate?.handleQRCodeScanned(data)
}
override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View =
createThemedComposeView {
QRScannerScreen(emptyFlow(), onScan = {
delegate?.handleQRCodeScanned(it)
})
}
}

View File

@ -1,40 +0,0 @@
<?xml version="1.0" encoding="utf-8"?>
<FrameLayout
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:layout_width="match_parent"
android:layout_height="match_parent">
<org.thoughtcrime.securesms.components.camera.CameraView
android:id="@+id/cameraView"
android:layout_width="match_parent"
android:layout_height="match_parent"
app:camera="0" />
<LinearLayout
android:id="@+id/overlayView"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical"
android:weightSum="3" >
<org.thoughtcrime.securesms.components.ShapeScrim
android:layout_weight="2"
android:layout_width="match_parent"
android:layout_height="0dp"/>
<TextView
android:id="@+id/messageTextView"
android:layout_width="match_parent"
android:layout_height="0dp"
android:layout_weight="1"
android:padding="@dimen/very_large_spacing"
android:gravity="center"
android:text="@string/messageNewDescriptionMobile"
android:background="?android:windowBackground"
android:textSize="@dimen/small_font_size"
android:textColor="?android:textColorTertiary" />
</LinearLayout>
</FrameLayout>

View File

@ -1,36 +0,0 @@
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout
xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent">
<LinearLayout
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:orientation="vertical"
android:gravity="center_horizontal"
android:layout_centerInParent="true">
<TextView
android:id="@+id/needCameraPermissionsTV"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginLeft="@dimen/very_large_spacing"
android:layout_marginRight="@dimen/very_large_spacing"
android:textSize="@dimen/small_font_size"
android:textAlignment="center"
android:text="@string/cameraGrantAccessQr" />
<Button
style="@style/Widget.Session.Button.Common.ProminentOutline"
android:id="@+id/grantCameraAccessButton"
android:layout_width="wrap_content"
android:layout_height="@dimen/medium_button_height"
android:layout_marginTop="@dimen/medium_spacing"
android:paddingLeft="@dimen/medium_spacing"
android:paddingRight="@dimen/medium_spacing"
android:text="@string/cameraGrantAccess" />
</LinearLayout>
</RelativeLayout>

View File

@ -1,6 +0,0 @@
<?xml version="1.0" encoding="utf-8"?>
<FrameLayout
xmlns:android="http://schemas.android.com/apk/res/android"
android:id="@+id/fragmentContainer"
android:layout_width="match_parent"
android:layout_height="match_parent" />