Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
10 changes: 9 additions & 1 deletion app/src/main/AndroidManifest.xml
Original file line number Diff line number Diff line change
Expand Up @@ -188,15 +188,23 @@
<activity
android:name=".ui.forward.ForwardActivity"
android:configChanges="screenSize|smallestScreenSize|screenLayout|orientation"
android:exported="false"
android:launchMode="singleTask"
android:theme="@style/AppTheme.NoActionBar"
android:windowSoftInputMode="adjustResize|stateAlwaysHidden" />

<activity
android:name=".ui.forward.ShareActivity"
android:configChanges="screenSize|smallestScreenSize|screenLayout|orientation"
android:exported="false"
android:theme="@style/AppTheme.NoActionBar"
android:windowSoftInputMode="adjustResize|stateAlwaysHidden" />

<activity-alias
android:name="one.mixin.messenger.ShareActivity"
android:excludeFromRecents="true"
android:exported="true"
android:targetActivity=".ui.forward.ForwardActivity">
android:targetActivity=".ui.forward.ShareActivity">
<intent-filter>
<action android:name="android.intent.action.SEND" />
<category android:name="android.intent.category.DEFAULT" />
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -1484,6 +1484,7 @@ fun Context.shareMedia(
putExtra(Intent.EXTRA_STREAM, uri)
}
type = if (isVideo) "video/*" else "image/*"
addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION)
}
val name = getString(if (isVideo) R.string.Video else R.string.Photo)
val chooser = Intent.createChooser(sendIntent, getString(R.string.share_to, name))
Expand All @@ -1493,7 +1494,7 @@ fun Context.shareMedia(
grantUriPermission(
packageName,
uri,
Intent.FLAG_GRANT_READ_URI_PERMISSION or Intent.FLAG_GRANT_WRITE_URI_PERMISSION,
Intent.FLAG_GRANT_READ_URI_PERMISSION,
)
}
startActivity(chooser)
Expand Down
29 changes: 27 additions & 2 deletions app/src/main/java/one/mixin/android/extension/UrlExtension.kt
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,7 @@ import one.mixin.android.ui.setting.SettingActivity
import one.mixin.android.ui.setting.member.MixinMemberUpgradeBottomSheetDialogFragment
import one.mixin.android.ui.url.UrlInterpreterActivity
import one.mixin.android.ui.web.WebActivity
import one.mixin.android.util.GsonHelper
import one.mixin.android.util.analytics.AnalyticsTracker
import one.mixin.android.util.analytics.AnalyticsTracker.TradeSource
import one.mixin.android.util.analytics.AnalyticsTracker.TradeWallet
Expand All @@ -51,6 +52,7 @@ import one.mixin.android.vo.AppCardData
import one.mixin.android.vo.ForwardAction
import one.mixin.android.vo.ForwardMessage
import one.mixin.android.vo.ShareCategory
import one.mixin.android.vo.ShareImageData
import one.mixin.android.vo.User
import one.mixin.android.vo.generateConversationId
import one.mixin.android.vo.getShareCategory
Expand Down Expand Up @@ -695,6 +697,11 @@ fun Uri.handleSchemeSend(
val data = this.getRawQueryParameter("data")
val shareCategory = category?.getShareCategory()
if (shareCategory != null && data != null) {
val message = parseSchemeShareMessage(shareCategory, data)
if (message == null) {
onError?.invoke("Error data")
return
}
if (userId != null) {
scope.launch {
val identityNumber = Session.getAccount()?.identityNumber ?: return@launch
Expand All @@ -705,15 +712,15 @@ fun Uri.handleSchemeSend(
val bottomSheet = LinkBottomSheetDialogFragment.newInstance(this@handleSchemeSend.toString())
bottomSheet.showNow(supportFragmentManager, LinkBottomSheetDialogFragment.TAG)
} else {
sendMessage(context, scope, user, currentConversation, message = ForwardMessage(shareCategory, String(Base64.decode(data))))
sendMessage(context, scope, user, currentConversation, message = message)
}
}
} else {
try {
afterShareData?.invoke()
val fragment =
ShareMessageBottomSheetDialogFragment.newInstance(
ForwardMessage(shareCategory, String(Base64.decode(data))),
message,
conversationId,
app,
host,
Expand All @@ -733,6 +740,24 @@ fun Uri.handleSchemeSend(
}
}

internal fun parseSchemeShareMessage(category: ShareCategory, data: String): ForwardMessage? =
try {
val content = String(Base64.decode(data))
if (category == ShareCategory.Image) {
val image = GsonHelper.customGson.fromJson(content, ShareImageData::class.java)
val uri = URI(image.url)
if ((uri.scheme.equals("https", true) || uri.scheme.equals("http", true)) && uri.host != null && uri.rawUserInfo == null) {
ForwardMessage(category, GsonHelper.customGson.toJson(ShareImageData(image.url)))
} else {
null
}
} else {
ForwardMessage(category, content)
}
} catch (_: Exception) {
null
}

fun sendMessage(context: Context, scope: CoroutineScope, user: User, currentConversation: String?, message: ForwardMessage) {
val toConversation = generateConversationId(Session.getAccountId()!!, user.userId)
ForwardActivity.show(
Expand Down
6 changes: 6 additions & 0 deletions app/src/main/java/one/mixin/android/job/ConvertDataJob.kt
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ import one.mixin.android.extension.createDocumentTemp
import one.mixin.android.extension.getDocumentPath
import one.mixin.android.extension.getExtensionName
import one.mixin.android.extension.getFilePath
import one.mixin.android.util.ShareHelper
import one.mixin.android.vo.MediaStatus
import one.mixin.android.vo.Message
import one.mixin.android.vo.MessageStatus
Expand All @@ -35,6 +36,10 @@ class ConvertDataJob(
removeJob()
}

private fun releaseSource() {
message.mediaUrl?.let { ShareHelper.releaseJobSource(MixinApplication.appContext, Uri.parse(it)) }
}

override fun onRun() {
if (isCancelled) {
removeJob()
Expand Down Expand Up @@ -73,6 +78,7 @@ class ConvertDataJob(
),
),
)
releaseSource()
}
}
}
3 changes: 3 additions & 0 deletions app/src/main/java/one/mixin/android/job/ConvertVideoJob.kt
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,7 @@ import one.mixin.android.extension.getMimeType
import one.mixin.android.extension.getVideoModel
import one.mixin.android.extension.getVideoPath
import one.mixin.android.extension.nowInUtc
import one.mixin.android.util.ShareHelper
import one.mixin.android.util.tickerFlow
import one.mixin.android.util.video.VideoEditedInfo
import one.mixin.android.vo.EncryptCategory
Expand Down Expand Up @@ -82,6 +83,7 @@ class ConvertVideoJob(
override fun onAdded() {
val mimeType = getMimeType(uri)
if (video == null) {
ShareHelper.releaseJobSource(MixinApplication.appContext, uri)
return
}
if (mimeType != "video/mp4") {
Expand Down Expand Up @@ -273,6 +275,7 @@ class ConvertVideoJob(
messageDao.updateMediaDuration(duration.toString(), messageId)
MessageFlow.update(message.conversationId, message.messageId)
jobManager.addJobInBackground(SendAttachmentMessageJob(message))
ShareHelper.releaseJobSource(MixinApplication.appContext, uri)
}

removeJob()
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,7 @@ import one.mixin.android.repository.ConversationRepository
import one.mixin.android.repository.UserRepository
import one.mixin.android.util.Attachment
import one.mixin.android.util.GsonHelper
import one.mixin.android.util.ShareHelper
import one.mixin.android.util.image.Compressor
import one.mixin.android.vo.AppCap
import one.mixin.android.vo.AppCardData
Expand Down Expand Up @@ -329,6 +330,7 @@ class SendMessageHelper
MessageCategory.SIGNAL_DATA,
MessageCategory.ENCRYPTED_DATA,
)
val source = ShareHelper.retainJobSource(MixinApplication.appContext, attachment.uri)
val message =
createAttachmentMessage(
UUID.randomUUID().toString(),
Expand All @@ -337,7 +339,7 @@ class SendMessageHelper
category,
null,
attachment.filename,
attachment.uri.toString(),
source.toString(),
attachment.mimeType,
attachment.fileSize,
nowInUtc(),
Expand All @@ -348,7 +350,12 @@ class SendMessageHelper
replyMessage?.messageId,
replyMessage?.toQuoteMessageItem(),
)
jobManager.addJobInBackground(ConvertDataJob(message))
try {
jobManager.addJobInBackground(ConvertDataJob(message))
} catch (e: Exception) {
ShareHelper.releaseJobSource(MixinApplication.appContext, source)
throw e
}
}

fun sendAudioMessage(
Expand Down Expand Up @@ -462,7 +469,13 @@ class SendMessageHelper
replyMessage: MessageItem? = null,
) {
val mid = messageId ?: UUID.randomUUID().toString()
jobManager.addJobInBackground(ConvertVideoJob(conversationId, senderId, uri, start, end, encryptCategory, mid, createdAt, replyMessage))
val source = ShareHelper.retainJobSource(MixinApplication.appContext, uri)
try {
jobManager.addJobInBackground(ConvertVideoJob(conversationId, senderId, source, start, end, encryptCategory, mid, createdAt, replyMessage))
} catch (e: Exception) {
ShareHelper.releaseJobSource(MixinApplication.appContext, source)
throw e
}
}

fun sendRecallMessage(
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -1236,7 +1236,12 @@ class LinkBottomSheetDialogFragment : SchemeBottomSheet() {
showError()
return
} else {
d.base64RawURLDecode()
try {
d.base64RawURLDecode()
} catch (_: IllegalArgumentException) {
showError()
return
}
}
} else {
null
Expand Down
29 changes: 2 additions & 27 deletions app/src/main/java/one/mixin/android/ui/forward/ForwardActivity.kt
Original file line number Diff line number Diff line change
Expand Up @@ -14,10 +14,8 @@ import one.mixin.android.R
import one.mixin.android.extension.colorFromAttribute
import one.mixin.android.extension.replaceFragment
import one.mixin.android.extension.toast
import one.mixin.android.session.Session
import one.mixin.android.ui.common.BlazeBaseActivity
import one.mixin.android.ui.conversation.ConversationActivity
import one.mixin.android.util.ShareHelper
import one.mixin.android.util.SystemUIManager
import one.mixin.android.vo.ForwardAction
import one.mixin.android.vo.ForwardMessage
Expand Down Expand Up @@ -151,31 +149,8 @@ class ForwardActivity : BlazeBaseActivity() {
)
replaceFragment(f, R.id.container, ForwardFragment.TAG)
} else {
if (Session.getAccount() == null) {
toast(R.string.Not_logged_in)
finish()
return
}
val forwardMessageList = ShareHelper.get().generateForwardMessageList(intent)
val conversationId =
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.Q && intent.hasExtra(Intent.EXTRA_SHORTCUT_ID)) {
intent.getStringExtra(Intent.EXTRA_SHORTCUT_ID)
} else {
null
}
if (!forwardMessageList.isNullOrEmpty()) {
replaceFragment(
ForwardFragment.newInstance(
forwardMessageList,
ForwardAction.System(conversationId, getString(R.string.Share)),
),
R.id.container,
ForwardFragment.TAG,
)
} else {
toast(R.string.Share_error)
finish()
}
toast(R.string.Share_error)
finish()
}
}
}
50 changes: 8 additions & 42 deletions app/src/main/java/one/mixin/android/ui/forward/ForwardFragment.kt
Original file line number Diff line number Diff line change
Expand Up @@ -25,17 +25,14 @@ import com.bumptech.glide.Glide
import com.timehop.stickyheadersrecyclerview.StickyRecyclerHeadersDecoration
import com.uber.autodispose.autoDispose
import dagger.hilt.android.AndroidEntryPoint
import io.reactivex.android.schedulers.AndroidSchedulers
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.Job
import kotlinx.coroutines.launch
import kotlinx.coroutines.withContext
import one.mixin.android.MixinApplication
import one.mixin.android.R
import one.mixin.android.RxBus
import one.mixin.android.crypto.Base64
import one.mixin.android.databinding.FragmentForwardBinding
import one.mixin.android.event.AppAuthEvent
import one.mixin.android.extension.base64Encode
import one.mixin.android.extension.copyFromInputStream
import one.mixin.android.extension.getExtensionName
Expand Down Expand Up @@ -217,9 +214,7 @@ class ForwardFragment : BaseFragment(R.layout.fragment_forward) {
val cid = action.conversationId
if (cid != null) {
when (action) {
is ForwardAction.System -> {
sendDirectMessages(cid)
}
is ForwardAction.System -> Unit
else -> {
sendMessage(listOf(SelectItem(cid, null)))
requireActivity().finish()
Expand Down Expand Up @@ -301,19 +296,6 @@ class ForwardFragment : BaseFragment(R.layout.fragment_forward) {
binding.searchEt.addTextChangedListener(mWatcher)

loadData()

RxBus.listen(AppAuthEvent::class.java)
.observeOn(AndroidSchedulers.mainThread())
.autoDispose(destroyScope)
.subscribe {
if (action is ForwardAction.System && !needOpenEditor()) {
action.conversationId?.let { cid ->
lifecycleScope.launch {
sendAndGo2Chat(cid)
}
}
}
}
}

private fun loadData() =
Expand Down Expand Up @@ -341,6 +323,13 @@ class ForwardFragment : BaseFragment(R.layout.fragment_forward) {
adapter.sourceFriends = friends
adapter.sourceBots = bots

if (action is ForwardAction.System) {
val directShareTarget = action.conversationId
conversations.firstOrNull { it.conversationId == directShareTarget }?.let {
adapter.selectItem.add(it)
setForwardText()
}
}
adapter.changeData()
}

Expand Down Expand Up @@ -756,29 +745,6 @@ class ForwardFragment : BaseFragment(R.layout.fragment_forward) {
}
}

private fun sendDirectMessages(cid: String) =
lifecycleScope.launch {
if (needOpenEditor()) {
editorPreserver = EditorPreserver(messages[0], listOf(SelectItem(cid, null)))
editAndSend(requireNotNull(editorPreserver?.forwardMessage))
return@launch
}

if (!MixinApplication.get().checkAndShowAppAuth(requireActivity())) {
sendAndGo2Chat(cid)
}
}

private suspend fun sendAndGo2Chat(cid: String) {
val err = sendMessageInternal(SelectItem(cid, null))
if (err.isNullOrEmpty()) {
toast(R.string.Message_sent)
}
MainActivity.reopen(requireContext())
activity?.finish()
ConversationActivity.show(requireContext(), cid)
}

private fun updateDynamicShortcuts(selectItems: ArrayList<Any>) =
lifecycleScope.launch {
val shortcuts = mutableListOf<ShortcutInfoCompat>()
Expand Down
Loading