mirror of
				https://github.com/KokaKiwi/BarInsta
				synced 2025-10-31 11:35:34 +00:00 
			
		
		
		
	More suspend funs
This commit is contained in:
		
							parent
							
								
									538a1406a6
								
							
						
					
					
						commit
						741a997424
					
				| @ -88,9 +88,9 @@ import awais.instagrabber.repositories.requests.directmessages.ThreadIdOrUserIds | |||||||
| import awais.instagrabber.repositories.responses.Media; | import awais.instagrabber.repositories.responses.Media; | ||||||
| import awais.instagrabber.repositories.responses.StoryStickerResponse; | import awais.instagrabber.repositories.responses.StoryStickerResponse; | ||||||
| import awais.instagrabber.repositories.responses.directmessages.DirectThread; | import awais.instagrabber.repositories.responses.directmessages.DirectThread; | ||||||
| import awais.instagrabber.repositories.responses.directmessages.DirectThreadBroadcastResponse; |  | ||||||
| import awais.instagrabber.utils.Constants; | import awais.instagrabber.utils.Constants; | ||||||
| import awais.instagrabber.utils.CookieUtils; | import awais.instagrabber.utils.CookieUtils; | ||||||
|  | import awais.instagrabber.utils.CoroutineUtilsKt; | ||||||
| import awais.instagrabber.utils.DownloadUtils; | import awais.instagrabber.utils.DownloadUtils; | ||||||
| import awais.instagrabber.utils.TextUtils; | import awais.instagrabber.utils.TextUtils; | ||||||
| import awais.instagrabber.utils.Utils; | import awais.instagrabber.utils.Utils; | ||||||
| @ -231,32 +231,21 @@ public class StoryViewerFragment extends Fragment { | |||||||
|                                     return; |                                     return; | ||||||
|                                 } |                                 } | ||||||
|                                 final DirectThread thread = response.body(); |                                 final DirectThread thread = response.body(); | ||||||
|                                 final Call<DirectThreadBroadcastResponse> request = directMessagesService.broadcastStoryReply( |                                 directMessagesService.broadcastStoryReply( | ||||||
|                                         ThreadIdOrUserIds.of(thread.getThreadId()), |                                         ThreadIdOrUserIds.of(thread.getThreadId()), | ||||||
|                                         input.getText().toString(), |                                         input.getText().toString(), | ||||||
|                                         currentStory.getStoryMediaId(), |                                         currentStory.getStoryMediaId(), | ||||||
|                                         String.valueOf(currentStory.getUserId()) |                                         String.valueOf(currentStory.getUserId()), | ||||||
|                                 ); |                                         CoroutineUtilsKt.getContinuation((directThreadBroadcastResponse, throwable) -> { | ||||||
|                                 request.enqueue(new Callback<DirectThreadBroadcastResponse>() { |                                             if (throwable != null) { | ||||||
|                                     @Override |                                                 Toast.makeText(context, R.string.downloader_unknown_error, Toast.LENGTH_SHORT).show(); | ||||||
|                                     public void onResponse(@NonNull final Call<DirectThreadBroadcastResponse> call, |                                                 Log.e(TAG, "onFailure: ", throwable); | ||||||
|                                                            @NonNull final Response<DirectThreadBroadcastResponse> response) { |                                                 return; | ||||||
|                                         if (!response.isSuccessful()) { |                                             } | ||||||
|                                             Toast.makeText(context, R.string.downloader_unknown_error, Toast.LENGTH_SHORT).show(); |                                             Toast.makeText(context, R.string.answered_story, Toast.LENGTH_SHORT).show(); | ||||||
|                                             return; |                                         }) | ||||||
|                                         } |  | ||||||
|                                         Toast.makeText(context, R.string.answered_story, Toast.LENGTH_SHORT).show(); |  | ||||||
|                                     } |  | ||||||
| 
 | 
 | ||||||
|                                     @Override |                                 ); | ||||||
|                                     public void onFailure(@NonNull final Call<DirectThreadBroadcastResponse> call, @NonNull final Throwable t) { |  | ||||||
|                                         try { |  | ||||||
|                                             Toast.makeText(context, R.string.downloader_unknown_error, Toast.LENGTH_SHORT).show(); |  | ||||||
|                                             Log.e(TAG, "onFailure: ", t); |  | ||||||
|                                         } catch (Throwable ignored) { |  | ||||||
|                                         } |  | ||||||
|                                     } |  | ||||||
|                                 }); |  | ||||||
|                             } |                             } | ||||||
| 
 | 
 | ||||||
|                             @Override |                             @Override | ||||||
|  | |||||||
| @ -12,7 +12,6 @@ import awais.instagrabber.models.Resource.Companion.success | |||||||
| import awais.instagrabber.repositories.requests.directmessages.ThreadIdOrUserIds.Companion.of | import awais.instagrabber.repositories.requests.directmessages.ThreadIdOrUserIds.Companion.of | ||||||
| import awais.instagrabber.repositories.responses.User | import awais.instagrabber.repositories.responses.User | ||||||
| import awais.instagrabber.repositories.responses.directmessages.DirectThread | import awais.instagrabber.repositories.responses.directmessages.DirectThread | ||||||
| import awais.instagrabber.repositories.responses.directmessages.DirectThreadBroadcastResponse |  | ||||||
| import awais.instagrabber.repositories.responses.directmessages.RankedRecipient | import awais.instagrabber.repositories.responses.directmessages.RankedRecipient | ||||||
| import awais.instagrabber.utils.Constants | import awais.instagrabber.utils.Constants | ||||||
| import awais.instagrabber.utils.Utils | import awais.instagrabber.utils.Utils | ||||||
| @ -21,6 +20,8 @@ import awais.instagrabber.utils.getUserIdFromCookie | |||||||
| import awais.instagrabber.webservices.DirectMessagesService | import awais.instagrabber.webservices.DirectMessagesService | ||||||
| import awais.instagrabber.webservices.DirectMessagesService.Companion.getInstance | import awais.instagrabber.webservices.DirectMessagesService.Companion.getInstance | ||||||
| import kotlinx.coroutines.CoroutineScope | import kotlinx.coroutines.CoroutineScope | ||||||
|  | import kotlinx.coroutines.Dispatchers | ||||||
|  | import kotlinx.coroutines.launch | ||||||
| import retrofit2.Call | import retrofit2.Call | ||||||
| import retrofit2.Callback | import retrofit2.Callback | ||||||
| import retrofit2.Response | import retrofit2.Response | ||||||
| @ -137,7 +138,7 @@ object DirectMessagesManager { | |||||||
|             // create thread and forward |             // create thread and forward | ||||||
|             createThread(recipient.user.pk) { (threadId) -> |             createThread(recipient.user.pk) { (threadId) -> | ||||||
|                 val threadIdTemp = threadId ?: return@createThread |                 val threadIdTemp = threadId ?: return@createThread | ||||||
|                 sendMedia(threadIdTemp, mediaId) { |                 sendMedia(threadIdTemp, mediaId, scope) { | ||||||
|                     if (refreshInbox) { |                     if (refreshInbox) { | ||||||
|                         inboxManager.refresh(scope) |                         inboxManager.refresh(scope) | ||||||
|                     } |                     } | ||||||
| @ -149,7 +150,7 @@ object DirectMessagesManager { | |||||||
|         // just forward |         // just forward | ||||||
|         val thread = recipient.thread |         val thread = recipient.thread | ||||||
|         val threadId = thread.threadId ?: return |         val threadId = thread.threadId ?: return | ||||||
|         sendMedia(threadId, mediaId) { |         sendMedia(threadId, mediaId, scope) { | ||||||
|             if (refreshInbox) { |             if (refreshInbox) { | ||||||
|                 inboxManager.refresh(scope) |                 inboxManager.refresh(scope) | ||||||
|             } |             } | ||||||
| @ -160,55 +161,26 @@ object DirectMessagesManager { | |||||||
|     private fun sendMedia( |     private fun sendMedia( | ||||||
|         threadId: String, |         threadId: String, | ||||||
|         mediaId: String, |         mediaId: String, | ||||||
|  |         scope: CoroutineScope, | ||||||
|         callback: (() -> Unit)?, |         callback: (() -> Unit)?, | ||||||
|     ): LiveData<Resource<Any?>> { |     ): LiveData<Resource<Any?>> { | ||||||
|         val data = MutableLiveData<Resource<Any?>>() |         val data = MutableLiveData<Resource<Any?>>() | ||||||
|         data.postValue(loading(null)) |         data.postValue(loading(null)) | ||||||
|         val request = service.broadcastMediaShare( |         scope.launch(Dispatchers.IO) { | ||||||
|             UUID.randomUUID().toString(), |             try { | ||||||
|             of(threadId), |                 service.broadcastMediaShare( | ||||||
|             mediaId |                     UUID.randomUUID().toString(), | ||||||
|         ) |                     of(threadId), | ||||||
|         request.enqueue(object : Callback<DirectThreadBroadcastResponse?> { |                     mediaId | ||||||
|             override fun onResponse( |                 ) | ||||||
|                 call: Call<DirectThreadBroadcastResponse?>, |                 data.postValue(success(Any())) | ||||||
|                 response: Response<DirectThreadBroadcastResponse?>, |                 callback?.invoke() | ||||||
|             ) { |             } catch (e: Exception) { | ||||||
|                 if (response.isSuccessful) { |                 Log.e(TAG, "sendMedia: ", e) | ||||||
|                     data.postValue(success(Any())) |                 data.postValue(error(e.message, null)) | ||||||
|                     callback?.invoke() |  | ||||||
|                     return |  | ||||||
|                 } |  | ||||||
|                 val errorBody = response.errorBody() |  | ||||||
|                 if (errorBody != null) { |  | ||||||
|                     try { |  | ||||||
|                         val string = errorBody.string() |  | ||||||
|                         val msg = String.format(Locale.US, |  | ||||||
|                             "onResponse: url: %s, responseCode: %d, errorBody: %s", |  | ||||||
|                             call.request().url().toString(), |  | ||||||
|                             response.code(), |  | ||||||
|                             string) |  | ||||||
|                         Log.e(TAG, msg) |  | ||||||
|                         data.postValue(error(msg, null)) |  | ||||||
|                     } catch (e: IOException) { |  | ||||||
|                         Log.e(TAG, "onResponse: ", e) |  | ||||||
|                         data.postValue(error(e.message, null)) |  | ||||||
|                     } |  | ||||||
|                     callback?.invoke() |  | ||||||
|                     return |  | ||||||
|                 } |  | ||||||
|                 val msg = "onResponse: request was not successful and response error body was null" |  | ||||||
|                 Log.e(TAG, msg) |  | ||||||
|                 data.postValue(error(msg, null)) |  | ||||||
|                 callback?.invoke() |                 callback?.invoke() | ||||||
|             } |             } | ||||||
| 
 |         } | ||||||
|             override fun onFailure(call: Call<DirectThreadBroadcastResponse?>, t: Throwable) { |  | ||||||
|                 Log.e(TAG, "onFailure: ", t) |  | ||||||
|                 data.postValue(error(t.message, null)) |  | ||||||
|                 callback?.invoke() |  | ||||||
|             } |  | ||||||
|         }) |  | ||||||
|         return data |         return data | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|  | |||||||
| @ -21,8 +21,6 @@ import kotlinx.coroutines.CoroutineScope | |||||||
| import kotlinx.coroutines.Dispatchers | import kotlinx.coroutines.Dispatchers | ||||||
| import kotlinx.coroutines.launch | import kotlinx.coroutines.launch | ||||||
| import retrofit2.Call | import retrofit2.Call | ||||||
| import retrofit2.Callback |  | ||||||
| import retrofit2.Response |  | ||||||
| import java.util.* | import java.util.* | ||||||
| import java.util.concurrent.TimeUnit | import java.util.concurrent.TimeUnit | ||||||
| 
 | 
 | ||||||
| @ -66,49 +64,23 @@ class InboxManager private constructor(private val pending: Boolean) { | |||||||
|                 inbox.postValue(error(e.message, currentDirectInbox)) |                 inbox.postValue(error(e.message, currentDirectInbox)) | ||||||
|                 hasOlder = false |                 hasOlder = false | ||||||
|             } |             } | ||||||
|             // inboxRequest?.enqueue(object : Callback<DirectInboxResponse?> { |  | ||||||
|             //     override fun onResponse(call: Call<DirectInboxResponse?>, response: Response<DirectInboxResponse?>) { |  | ||||||
|             //         val body = response.body() |  | ||||||
|             //         if (body == null) { |  | ||||||
|             //             Log.e(TAG, "parseInboxResponse: Response is null") |  | ||||||
|             //             inbox.postValue(error(R.string.generic_null_response, currentDirectInbox)) |  | ||||||
|             //             hasOlder = false |  | ||||||
|             //             return |  | ||||||
|             //         } |  | ||||||
|             // |  | ||||||
|             //     } |  | ||||||
|             // |  | ||||||
|             //     override fun onFailure(call: Call<DirectInboxResponse?>, t: Throwable) { |  | ||||||
|             //         Log.e(TAG, "Failed fetching dm inbox", t) |  | ||||||
|             //         inbox.postValue(error(t.message, currentDirectInbox)) |  | ||||||
|             //         hasOlder = false |  | ||||||
|             //     } |  | ||||||
|             // }) |  | ||||||
|         } |         } | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|     fun fetchUnseenCount() { |     fun fetchUnseenCount(scope: CoroutineScope) { | ||||||
|         val unseenCountResource = unseenCount.value |         val unseenCountResource = unseenCount.value | ||||||
|         if (unseenCountResource != null && unseenCountResource.status === Resource.Status.LOADING) return |         if (unseenCountResource != null && unseenCountResource.status === Resource.Status.LOADING) return | ||||||
|         stopCurrentUnseenCountRequest() |         stopCurrentUnseenCountRequest() | ||||||
|         unseenCount.postValue(loading(currentUnseenCount)) |         unseenCount.postValue(loading(currentUnseenCount)) | ||||||
|         unseenCountRequest = service.fetchUnseenCount() |         scope.launch(Dispatchers.IO) { | ||||||
|         unseenCountRequest?.enqueue(object : Callback<DirectBadgeCount?> { |             try { | ||||||
|             override fun onResponse(call: Call<DirectBadgeCount?>, response: Response<DirectBadgeCount?>) { |                 val directBadgeCount = service.fetchUnseenCount() | ||||||
|                 val directBadgeCount = response.body() |  | ||||||
|                 if (directBadgeCount == null) { |  | ||||||
|                     Log.e(TAG, "onResponse: directBadgeCount Response is null") |  | ||||||
|                     unseenCount.postValue(error(R.string.dms_inbox_error_null_count, currentUnseenCount)) |  | ||||||
|                     return |  | ||||||
|                 } |  | ||||||
|                 unseenCount.postValue(success(directBadgeCount.badgeCount)) |                 unseenCount.postValue(success(directBadgeCount.badgeCount)) | ||||||
|  |             } catch (e: Exception) { | ||||||
|  |                 Log.e(TAG, "Failed fetching unseen count", e) | ||||||
|  |                 unseenCount.postValue(error(e.message, currentUnseenCount)) | ||||||
|             } |             } | ||||||
| 
 |         } | ||||||
|             override fun onFailure(call: Call<DirectBadgeCount?>, t: Throwable) { |  | ||||||
|                 Log.e(TAG, "Failed fetching unseen count", t) |  | ||||||
|                 unseenCount.postValue(error(t.message, currentUnseenCount)) |  | ||||||
|             } |  | ||||||
|         }) |  | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|     fun refresh(scope: CoroutineScope) { |     fun refresh(scope: CoroutineScope) { | ||||||
| @ -117,7 +89,7 @@ class InboxManager private constructor(private val pending: Boolean) { | |||||||
|         hasOlder = true |         hasOlder = true | ||||||
|         fetchInbox(scope) |         fetchInbox(scope) | ||||||
|         if (!pending) { |         if (!pending) { | ||||||
|             fetchUnseenCount() |             fetchUnseenCount(scope) | ||||||
|         } |         } | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
| @ -350,9 +322,5 @@ class InboxManager private constructor(private val pending: Boolean) { | |||||||
|             val threads = inbox?.threads ?: emptyList() |             val threads = inbox?.threads ?: emptyList() | ||||||
|             ImmutableList.sortedCopyOf(THREAD_COMPARATOR, threads) |             ImmutableList.sortedCopyOf(THREAD_COMPARATOR, threads) | ||||||
|         }) |         }) | ||||||
|         // fetchInbox() |  | ||||||
|         if (!pending) { |  | ||||||
|             fetchUnseenCount() |  | ||||||
|         } |  | ||||||
|     } |     } | ||||||
| } | } | ||||||
| @ -10,11 +10,11 @@ import androidx.lifecycle.Transformations.distinctUntilChanged | |||||||
| import androidx.lifecycle.Transformations.map | import androidx.lifecycle.Transformations.map | ||||||
| import awais.instagrabber.R | import awais.instagrabber.R | ||||||
| import awais.instagrabber.customviews.emoji.Emoji | import awais.instagrabber.customviews.emoji.Emoji | ||||||
| import awais.instagrabber.models.enums.DirectItemType.Companion.getName |  | ||||||
| import awais.instagrabber.models.Resource | import awais.instagrabber.models.Resource | ||||||
| import awais.instagrabber.models.Resource.Companion.error | import awais.instagrabber.models.Resource.Companion.error | ||||||
| import awais.instagrabber.models.Resource.Companion.loading | import awais.instagrabber.models.Resource.Companion.loading | ||||||
| import awais.instagrabber.models.Resource.Companion.success | import awais.instagrabber.models.Resource.Companion.success | ||||||
|  | import awais.instagrabber.models.enums.DirectItemType | ||||||
| import awais.instagrabber.repositories.requests.UploadFinishOptions | import awais.instagrabber.repositories.requests.UploadFinishOptions | ||||||
| import awais.instagrabber.repositories.requests.VideoOptions | import awais.instagrabber.repositories.requests.VideoOptions | ||||||
| import awais.instagrabber.repositories.requests.directmessages.ThreadIdOrUserIds | import awais.instagrabber.repositories.requests.directmessages.ThreadIdOrUserIds | ||||||
| @ -400,7 +400,7 @@ class ThreadManager private constructor( | |||||||
|         return temp |         return temp | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|     fun sendText(text: String): LiveData<Resource<Any?>> { |     fun sendText(text: String, scope: CoroutineScope): LiveData<Resource<Any?>> { | ||||||
|         val data = MutableLiveData<Resource<Any?>>() |         val data = MutableLiveData<Resource<Any?>>() | ||||||
|         val userId = getCurrentUserId(data) ?: return data |         val userId = getCurrentUserId(data) ?: return data | ||||||
|         val clientContext = UUID.randomUUID().toString() |         val clientContext = UUID.randomUUID().toString() | ||||||
| @ -412,29 +412,36 @@ class ThreadManager private constructor( | |||||||
|         data.postValue(loading(directItem)) |         data.postValue(loading(directItem)) | ||||||
|         val repliedToItemId = replyToItemValue?.itemId |         val repliedToItemId = replyToItemValue?.itemId | ||||||
|         val repliedToClientContext = replyToItemValue?.clientContext |         val repliedToClientContext = replyToItemValue?.clientContext | ||||||
|         val request = service.broadcastText( |         scope.launch(Dispatchers.IO) { | ||||||
|             clientContext, |             try { | ||||||
|             threadIdOrUserIds, |                 val response = service.broadcastText( | ||||||
|             text, |                     clientContext, | ||||||
|             repliedToItemId, |                     threadIdOrUserIds, | ||||||
|             repliedToClientContext |                     text, | ||||||
|         ) |                     repliedToItemId, | ||||||
|         enqueueRequest(request, data, directItem) |                     repliedToClientContext | ||||||
|  |                 ) | ||||||
|  |                 parseResponse(response, data, directItem) | ||||||
|  |             } catch (e: Exception) { | ||||||
|  |                 data.postValue(error(e.message, directItem)) | ||||||
|  |                 Log.e(TAG, "sendText: ", e) | ||||||
|  |             } | ||||||
|  |         } | ||||||
|         return data |         return data | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|     fun sendUri(entry: MediaController.MediaEntry): LiveData<Resource<Any?>> { |     fun sendUri(entry: MediaController.MediaEntry, scope: CoroutineScope): LiveData<Resource<Any?>> { | ||||||
|         val data = MutableLiveData<Resource<Any?>>() |         val data = MutableLiveData<Resource<Any?>>() | ||||||
|         val uri = Uri.fromFile(File(entry.path)) |         val uri = Uri.fromFile(File(entry.path)) | ||||||
|         if (!entry.isVideo) { |         if (!entry.isVideo) { | ||||||
|             sendPhoto(data, uri, entry.width, entry.height) |             sendPhoto(data, uri, entry.width, entry.height, scope) | ||||||
|             return data |             return data | ||||||
|         } |         } | ||||||
|         sendVideo(data, uri, entry.size, entry.duration, entry.width, entry.height) |         sendVideo(data, uri, entry.size, entry.duration, entry.width, entry.height, scope) | ||||||
|         return data |         return data | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|     fun sendUri(uri: Uri): LiveData<Resource<Any?>> { |     fun sendUri(uri: Uri, scope: CoroutineScope): LiveData<Resource<Any?>> { | ||||||
|         val data = MutableLiveData<Resource<Any?>>() |         val data = MutableLiveData<Resource<Any?>>() | ||||||
|         val mimeType = Utils.getMimeType(uri, contentResolver) |         val mimeType = Utils.getMimeType(uri, contentResolver) | ||||||
|         if (isEmpty(mimeType)) { |         if (isEmpty(mimeType)) { | ||||||
| @ -443,16 +450,16 @@ class ThreadManager private constructor( | |||||||
|         } |         } | ||||||
|         val isPhoto = mimeType != null && mimeType.startsWith("image") |         val isPhoto = mimeType != null && mimeType.startsWith("image") | ||||||
|         if (isPhoto) { |         if (isPhoto) { | ||||||
|             sendPhoto(data, uri) |             sendPhoto(data, uri, scope) | ||||||
|             return data |             return data | ||||||
|         } |         } | ||||||
|         if (mimeType != null && mimeType.startsWith("video")) { |         if (mimeType != null && mimeType.startsWith("video")) { | ||||||
|             sendVideo(data, uri) |             sendVideo(data, uri, scope) | ||||||
|         } |         } | ||||||
|         return data |         return data | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|     fun sendAnimatedMedia(giphyGif: GiphyGif): LiveData<Resource<Any?>> { |     fun sendAnimatedMedia(giphyGif: GiphyGif, scope: CoroutineScope): LiveData<Resource<Any?>> { | ||||||
|         val data = MutableLiveData<Resource<Any?>>() |         val data = MutableLiveData<Resource<Any?>>() | ||||||
|         val userId = getCurrentUserId(data) ?: return data |         val userId = getCurrentUserId(data) ?: return data | ||||||
|         val clientContext = UUID.randomUUID().toString() |         val clientContext = UUID.randomUUID().toString() | ||||||
| @ -460,12 +467,19 @@ class ThreadManager private constructor( | |||||||
|         directItem.isPending = true |         directItem.isPending = true | ||||||
|         addItems(0, listOf(directItem)) |         addItems(0, listOf(directItem)) | ||||||
|         data.postValue(loading(directItem)) |         data.postValue(loading(directItem)) | ||||||
|         val request = service.broadcastAnimatedMedia( |         scope.launch(Dispatchers.IO) { | ||||||
|             clientContext, |             try { | ||||||
|             threadIdOrUserIds, |                 val request = service.broadcastAnimatedMedia( | ||||||
|             giphyGif |                     clientContext, | ||||||
|         ) |                     threadIdOrUserIds, | ||||||
|         enqueueRequest(request, data, directItem) |                     giphyGif | ||||||
|  |                 ) | ||||||
|  |                 parseResponse(request, data, directItem) | ||||||
|  |             } catch (e: Exception) { | ||||||
|  |                 data.postValue(error(e.message, directItem)) | ||||||
|  |                 Log.e(TAG, "sendAnimatedMedia: ", e) | ||||||
|  |             } | ||||||
|  |         } | ||||||
|         return data |         return data | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
| @ -476,6 +490,7 @@ class ThreadManager private constructor( | |||||||
|         samplingFreq: Int, |         samplingFreq: Int, | ||||||
|         duration: Long, |         duration: Long, | ||||||
|         byteLength: Long, |         byteLength: Long, | ||||||
|  |         scope: CoroutineScope, | ||||||
|     ) { |     ) { | ||||||
|         if (duration > 60000) { |         if (duration > 60000) { | ||||||
|             // instagram does not allow uploading audio longer than 60 secs for Direct messages |             // instagram does not allow uploading audio longer than 60 secs for Direct messages | ||||||
| @ -502,14 +517,21 @@ class ThreadManager private constructor( | |||||||
|                 uploadFinishRequest.enqueue(object : Callback<String?> { |                 uploadFinishRequest.enqueue(object : Callback<String?> { | ||||||
|                     override fun onResponse(call: Call<String?>, response: Response<String?>) { |                     override fun onResponse(call: Call<String?>, response: Response<String?>) { | ||||||
|                         if (response.isSuccessful) { |                         if (response.isSuccessful) { | ||||||
|                             val request = service.broadcastVoice( |                             scope.launch(Dispatchers.IO) { | ||||||
|                                 clientContext, |                                 try { | ||||||
|                                 threadIdOrUserIds, |                                     val request = service.broadcastVoice( | ||||||
|                                 uploadDmVoiceOptions.uploadId, |                                         clientContext, | ||||||
|                                 waveform, |                                         threadIdOrUserIds, | ||||||
|                                 samplingFreq |                                         uploadDmVoiceOptions.uploadId, | ||||||
|                             ) |                                         waveform, | ||||||
|                             enqueueRequest(request, data, directItem) |                                         samplingFreq | ||||||
|  |                                     ) | ||||||
|  |                                     parseResponse(request, data, directItem) | ||||||
|  |                                 } catch (e: Exception) { | ||||||
|  |                                     data.postValue(error(e.message, directItem)) | ||||||
|  |                                     Log.e(TAG, "sendVoice: ", e) | ||||||
|  |                                 } | ||||||
|  |                             } | ||||||
|                             return |                             return | ||||||
|                         } |                         } | ||||||
|                         if (response.errorBody() != null) { |                         if (response.errorBody() != null) { | ||||||
| @ -537,6 +559,7 @@ class ThreadManager private constructor( | |||||||
|     fun sendReaction( |     fun sendReaction( | ||||||
|         item: DirectItem, |         item: DirectItem, | ||||||
|         emoji: Emoji, |         emoji: Emoji, | ||||||
|  |         scope: CoroutineScope, | ||||||
|     ): LiveData<Resource<Any?>> { |     ): LiveData<Resource<Any?>> { | ||||||
|         val data = MutableLiveData<Resource<Any?>>() |         val data = MutableLiveData<Resource<Any?>>() | ||||||
|         val userId = getCurrentUserId(data) |         val userId = getCurrentUserId(data) | ||||||
| @ -557,18 +580,24 @@ class ThreadManager private constructor( | |||||||
|             data.postValue(error("itemId is null", null)) |             data.postValue(error("itemId is null", null)) | ||||||
|             return data |             return data | ||||||
|         } |         } | ||||||
|         val request = service.broadcastReaction( |         scope.launch(Dispatchers.IO) { | ||||||
|             clientContext, |             try { | ||||||
|             threadIdOrUserIds, |                 service.broadcastReaction( | ||||||
|             itemId, |                     clientContext, | ||||||
|             emojiUnicode, |                     threadIdOrUserIds, | ||||||
|             false |                     itemId, | ||||||
|         ) |                     emojiUnicode, | ||||||
|         handleBroadcastReactionRequest(data, item, request) |                     false | ||||||
|  |                 ) | ||||||
|  |             } catch (e: Exception) { | ||||||
|  |                 data.postValue(error(e.message, null)) | ||||||
|  |                 Log.e(TAG, "sendReaction: ", e) | ||||||
|  |             } | ||||||
|  |         } | ||||||
|         return data |         return data | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|     fun sendDeleteReaction(itemId: String): LiveData<Resource<Any?>> { |     fun sendDeleteReaction(itemId: String, scope: CoroutineScope): LiveData<Resource<Any?>> { | ||||||
|         val data = MutableLiveData<Resource<Any?>>() |         val data = MutableLiveData<Resource<Any?>>() | ||||||
|         val item = getItem(itemId) |         val item = getItem(itemId) | ||||||
|         if (item == null) { |         if (item == null) { | ||||||
| @ -588,8 +617,14 @@ class ThreadManager private constructor( | |||||||
|             data.postValue(error("itemId is null", null)) |             data.postValue(error("itemId is null", null)) | ||||||
|             return data |             return data | ||||||
|         } |         } | ||||||
|         val request = service.broadcastReaction(clientContext, threadIdOrUserIds, itemId1, null, true) |         scope.launch(Dispatchers.IO) { | ||||||
|         handleBroadcastReactionRequest(data, item, request) |             try { | ||||||
|  |                 service.broadcastReaction(clientContext, threadIdOrUserIds, itemId1, null, true) | ||||||
|  |             } catch (e: Exception) { | ||||||
|  |                 data.postValue(error(e.message, null)) | ||||||
|  |                 Log.e(TAG, "sendDeleteReaction: ", e) | ||||||
|  |             } | ||||||
|  |         } | ||||||
|         return data |         return data | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
| @ -660,7 +695,7 @@ class ThreadManager private constructor( | |||||||
|             data.postValue(error("item type is null", null)) |             data.postValue(error("item type is null", null)) | ||||||
|             return data |             return data | ||||||
|         } |         } | ||||||
|         val itemTypeName = getName(itemType) |         val itemTypeName = DirectItemType.getName(itemType) | ||||||
|         if (itemTypeName == null) { |         if (itemTypeName == null) { | ||||||
|             Log.e(TAG, "forward: itemTypeName was null!") |             Log.e(TAG, "forward: itemTypeName was null!") | ||||||
|             data.postValue(error("itemTypeName is null", null)) |             data.postValue(error("itemTypeName is null", null)) | ||||||
| @ -798,6 +833,7 @@ class ThreadManager private constructor( | |||||||
|     private fun sendPhoto( |     private fun sendPhoto( | ||||||
|         data: MutableLiveData<Resource<Any?>>, |         data: MutableLiveData<Resource<Any?>>, | ||||||
|         uri: Uri, |         uri: Uri, | ||||||
|  |         scope: CoroutineScope, | ||||||
|     ) { |     ) { | ||||||
|         try { |         try { | ||||||
|             val dimensions = BitmapUtils.decodeDimensions(contentResolver, uri) |             val dimensions = BitmapUtils.decodeDimensions(contentResolver, uri) | ||||||
| @ -805,7 +841,7 @@ class ThreadManager private constructor( | |||||||
|                 data.postValue(error("Decoding dimensions failed", null)) |                 data.postValue(error("Decoding dimensions failed", null)) | ||||||
|                 return |                 return | ||||||
|             } |             } | ||||||
|             sendPhoto(data, uri, dimensions.first, dimensions.second) |             sendPhoto(data, uri, dimensions.first, dimensions.second, scope) | ||||||
|         } catch (e: IOException) { |         } catch (e: IOException) { | ||||||
|             data.postValue(error(e.message, null)) |             data.postValue(error(e.message, null)) | ||||||
|             Log.e(TAG, "sendPhoto: ", e) |             Log.e(TAG, "sendPhoto: ", e) | ||||||
| @ -817,6 +853,7 @@ class ThreadManager private constructor( | |||||||
|         uri: Uri, |         uri: Uri, | ||||||
|         width: Int, |         width: Int, | ||||||
|         height: Int, |         height: Int, | ||||||
|  |         scope: CoroutineScope, | ||||||
|     ) { |     ) { | ||||||
|         val userId = getCurrentUserId(data) ?: return |         val userId = getCurrentUserId(data) ?: return | ||||||
|         val clientContext = UUID.randomUUID().toString() |         val clientContext = UUID.randomUUID().toString() | ||||||
| @ -829,8 +866,15 @@ class ThreadManager private constructor( | |||||||
|                 if (handleInvalidResponse(data, response)) return |                 if (handleInvalidResponse(data, response)) return | ||||||
|                 val response1 = response.response ?: return |                 val response1 = response.response ?: return | ||||||
|                 val uploadId = response1.optString("upload_id") |                 val uploadId = response1.optString("upload_id") | ||||||
|                 val request = service.broadcastPhoto(clientContext, threadIdOrUserIds, uploadId) |                 scope.launch(Dispatchers.IO) { | ||||||
|                 enqueueRequest(request, data, directItem) |                     try { | ||||||
|  |                         val response2 = service.broadcastPhoto(clientContext, threadIdOrUserIds, uploadId) | ||||||
|  |                         parseResponse(response2, data, directItem) | ||||||
|  |                     } catch (e: Exception) { | ||||||
|  |                         data.postValue(error(e.message, null)) | ||||||
|  |                         Log.e(TAG, "sendPhoto: ", e) | ||||||
|  |                     } | ||||||
|  |                 } | ||||||
|             } |             } | ||||||
| 
 | 
 | ||||||
|             override fun onFailure(t: Throwable) { |             override fun onFailure(t: Throwable) { | ||||||
| @ -843,6 +887,7 @@ class ThreadManager private constructor( | |||||||
|     private fun sendVideo( |     private fun sendVideo( | ||||||
|         data: MutableLiveData<Resource<Any?>>, |         data: MutableLiveData<Resource<Any?>>, | ||||||
|         uri: Uri, |         uri: Uri, | ||||||
|  |         scope: CoroutineScope, | ||||||
|     ) { |     ) { | ||||||
|         MediaUtils.getVideoInfo(contentResolver, uri, object : OnInfoLoadListener<VideoInfo?> { |         MediaUtils.getVideoInfo(contentResolver, uri, object : OnInfoLoadListener<VideoInfo?> { | ||||||
|             override fun onLoad(info: VideoInfo?) { |             override fun onLoad(info: VideoInfo?) { | ||||||
| @ -850,7 +895,7 @@ class ThreadManager private constructor( | |||||||
|                     data.postValue(error("Could not get the video info", null)) |                     data.postValue(error("Could not get the video info", null)) | ||||||
|                     return |                     return | ||||||
|                 } |                 } | ||||||
|                 sendVideo(data, uri, info.size, info.duration, info.width, info.height) |                 sendVideo(data, uri, info.size, info.duration, info.width, info.height, scope) | ||||||
|             } |             } | ||||||
| 
 | 
 | ||||||
|             override fun onFailure(t: Throwable) { |             override fun onFailure(t: Throwable) { | ||||||
| @ -866,6 +911,7 @@ class ThreadManager private constructor( | |||||||
|         duration: Long, |         duration: Long, | ||||||
|         width: Int, |         width: Int, | ||||||
|         height: Int, |         height: Int, | ||||||
|  |         scope: CoroutineScope, | ||||||
|     ) { |     ) { | ||||||
|         if (duration > 60000) { |         if (duration > 60000) { | ||||||
|             // instagram does not allow uploading videos longer than 60 secs for Direct messages |             // instagram does not allow uploading videos longer than 60 secs for Direct messages | ||||||
| @ -892,14 +938,21 @@ class ThreadManager private constructor( | |||||||
|                 uploadFinishRequest.enqueue(object : Callback<String?> { |                 uploadFinishRequest.enqueue(object : Callback<String?> { | ||||||
|                     override fun onResponse(call: Call<String?>, response: Response<String?>) { |                     override fun onResponse(call: Call<String?>, response: Response<String?>) { | ||||||
|                         if (response.isSuccessful) { |                         if (response.isSuccessful) { | ||||||
|                             val request = service.broadcastVideo( |                             scope.launch(Dispatchers.IO) { | ||||||
|                                 clientContext, |                                 try { | ||||||
|                                 threadIdOrUserIds, |                                     val response1 = service.broadcastVideo( | ||||||
|                                 uploadDmVideoOptions.uploadId, |                                         clientContext, | ||||||
|                                 "", |                                         threadIdOrUserIds, | ||||||
|                                 true |                                         uploadDmVideoOptions.uploadId, | ||||||
|                             ) |                                         "", | ||||||
|                             enqueueRequest(request, data, directItem) |                                         true | ||||||
|  |                                     ) | ||||||
|  |                                     parseResponse(response1, data, directItem) | ||||||
|  |                                 } catch (e: Exception) { | ||||||
|  |                                     data.postValue(error(e.message, null)) | ||||||
|  |                                     Log.e(TAG, "sendVideo: ", e) | ||||||
|  |                                 } | ||||||
|  |                             } | ||||||
|                             return |                             return | ||||||
|                         } |                         } | ||||||
|                         if (response.errorBody() != null) { |                         if (response.errorBody() != null) { | ||||||
| @ -924,64 +977,36 @@ class ThreadManager private constructor( | |||||||
|         }) |         }) | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|     private fun enqueueRequest( |     private fun parseResponse( | ||||||
|         request: Call<DirectThreadBroadcastResponse?>, |         response: DirectThreadBroadcastResponse, | ||||||
|         data: MutableLiveData<Resource<Any?>>, |         data: MutableLiveData<Resource<Any?>>, | ||||||
|         directItem: DirectItem, |         directItem: DirectItem, | ||||||
|     ) { |     ) { | ||||||
|         request.enqueue(object : Callback<DirectThreadBroadcastResponse?> { |         val payloadClientContext: String? | ||||||
|             override fun onResponse( |         val timestamp: Long | ||||||
|                 call: Call<DirectThreadBroadcastResponse?>, |         val itemId: String? | ||||||
|                 response: Response<DirectThreadBroadcastResponse?>, |         val payload = response.payload | ||||||
|             ) { |         if (payload == null) { | ||||||
|                 if (response.isSuccessful) { |             val messageMetadata = response.messageMetadata | ||||||
|                     val broadcastResponse = response.body() |             if (messageMetadata == null || messageMetadata.isEmpty()) { | ||||||
|                     if (broadcastResponse == null) { |                 data.postValue(success(directItem)) | ||||||
|                         data.postValue(error(R.string.generic_null_response, directItem)) |                 return | ||||||
|                         Log.e(TAG, "enqueueRequest: onResponse: response body is null") |  | ||||||
|                         return |  | ||||||
|                     } |  | ||||||
|                     val payloadClientContext: String? |  | ||||||
|                     val timestamp: Long |  | ||||||
|                     val itemId: String? |  | ||||||
|                     val payload = broadcastResponse.payload |  | ||||||
|                     if (payload == null) { |  | ||||||
|                         val messageMetadata = broadcastResponse.messageMetadata |  | ||||||
|                         if (messageMetadata == null || messageMetadata.isEmpty()) { |  | ||||||
|                             data.postValue(success(directItem)) |  | ||||||
|                             return |  | ||||||
|                         } |  | ||||||
|                         val (clientContext, itemId1, timestamp1) = messageMetadata[0] |  | ||||||
|                         payloadClientContext = clientContext |  | ||||||
|                         itemId = itemId1 |  | ||||||
|                         timestamp = timestamp1 |  | ||||||
|                     } else { |  | ||||||
|                         payloadClientContext = payload.clientContext |  | ||||||
|                         timestamp = payload.timestamp |  | ||||||
|                         itemId = payload.itemId |  | ||||||
|                     } |  | ||||||
|                     if (payloadClientContext == null) { |  | ||||||
|                         data.postValue(error("clientContext in response was null", null)) |  | ||||||
|                         return |  | ||||||
|                     } |  | ||||||
|                     updateItemSent(payloadClientContext, timestamp, itemId) |  | ||||||
|                     data.postValue(success(directItem)) |  | ||||||
|                     return |  | ||||||
|                 } |  | ||||||
|                 if (response.errorBody() != null) { |  | ||||||
|                     handleErrorBody(call, response, data) |  | ||||||
|                 } |  | ||||||
|                 data.postValue(error(R.string.generic_failed_request, directItem)) |  | ||||||
|             } |             } | ||||||
| 
 |             val (clientContext, itemId1, timestamp1) = messageMetadata[0] | ||||||
|             override fun onFailure( |             payloadClientContext = clientContext | ||||||
|                 call: Call<DirectThreadBroadcastResponse?>, |             itemId = itemId1 | ||||||
|                 t: Throwable, |             timestamp = timestamp1 | ||||||
|             ) { |         } else { | ||||||
|                 data.postValue(error(t.message, directItem)) |             payloadClientContext = payload.clientContext | ||||||
|                 Log.e(TAG, "enqueueRequest: onFailure: ", t) |             timestamp = payload.timestamp | ||||||
|             } |             itemId = payload.itemId | ||||||
|         }) |         } | ||||||
|  |         if (payloadClientContext == null) { | ||||||
|  |             data.postValue(error("clientContext in response was null", null)) | ||||||
|  |             return | ||||||
|  |         } | ||||||
|  |         updateItemSent(payloadClientContext, timestamp, itemId) | ||||||
|  |         data.postValue(success(directItem)) | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|     private fun updateItemSent( |     private fun updateItemSent( | ||||||
| @ -1054,38 +1079,6 @@ class ThreadManager private constructor( | |||||||
|             .firstOrNull() |             .firstOrNull() | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|     private fun handleBroadcastReactionRequest( |  | ||||||
|         data: MutableLiveData<Resource<Any?>>, |  | ||||||
|         item: DirectItem, |  | ||||||
|         request: Call<DirectThreadBroadcastResponse?>, |  | ||||||
|     ) { |  | ||||||
|         request.enqueue(object : Callback<DirectThreadBroadcastResponse?> { |  | ||||||
|             override fun onResponse( |  | ||||||
|                 call: Call<DirectThreadBroadcastResponse?>, |  | ||||||
|                 response: Response<DirectThreadBroadcastResponse?>, |  | ||||||
|             ) { |  | ||||||
|                 if (!response.isSuccessful) { |  | ||||||
|                     if (response.errorBody() != null) { |  | ||||||
|                         handleErrorBody(call, response, data) |  | ||||||
|                         return |  | ||||||
|                     } |  | ||||||
|                     data.postValue(error(R.string.generic_failed_request, item)) |  | ||||||
|                     return |  | ||||||
|                 } |  | ||||||
|                 val body = response.body() |  | ||||||
|                 if (body == null) { |  | ||||||
|                     data.postValue(error(R.string.generic_null_response, item)) |  | ||||||
|                 } |  | ||||||
|                 // otherwise nothing to do? maybe update the timestamp in the emoji? |  | ||||||
|             } |  | ||||||
| 
 |  | ||||||
|             override fun onFailure(call: Call<DirectThreadBroadcastResponse?>, t: Throwable) { |  | ||||||
|                 data.postValue(error(t.message, item)) |  | ||||||
|                 Log.e(TAG, "enqueueRequest: onFailure: ", t) |  | ||||||
|             } |  | ||||||
|         }) |  | ||||||
|     } |  | ||||||
| 
 |  | ||||||
|     private fun stopCurrentRequest() { |     private fun stopCurrentRequest() { | ||||||
|         chatsRequest?.let { |         chatsRequest?.let { | ||||||
|             if (it.isExecuted || it.isCanceled) return |             if (it.isExecuted || it.isCanceled) return | ||||||
| @ -1583,7 +1576,7 @@ class ThreadManager private constructor( | |||||||
|         }) |         }) | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|     fun markAsSeen(directItem: DirectItem): LiveData<Resource<Any?>> { |     fun markAsSeen(directItem: DirectItem, scope: CoroutineScope): LiveData<Resource<Any?>> { | ||||||
|         val data = MutableLiveData<Resource<Any?>>() |         val data = MutableLiveData<Resource<Any?>>() | ||||||
|         data.postValue(loading(null)) |         data.postValue(loading(null)) | ||||||
|         val request = service.markAsSeen(threadId, directItem) |         val request = service.markAsSeen(threadId, directItem) | ||||||
| @ -1606,7 +1599,7 @@ class ThreadManager private constructor( | |||||||
|                     data.postValue(error(R.string.generic_null_response, null)) |                     data.postValue(error(R.string.generic_null_response, null)) | ||||||
|                     return |                     return | ||||||
|                 } |                 } | ||||||
|                 inboxManager.fetchUnseenCount() |                 inboxManager.fetchUnseenCount(scope) | ||||||
|                 val payload = seenResponse.payload ?: return |                 val payload = seenResponse.payload ?: return | ||||||
|                 val timestamp = payload.timestamp |                 val timestamp = payload.timestamp | ||||||
|                 val thread = thread.value ?: return |                 val thread = thread.value ?: return | ||||||
|  | |||||||
| @ -1,46 +1,62 @@ | |||||||
| package awais.instagrabber.models.enums | package awais.instagrabber.models.enums | ||||||
| 
 | 
 | ||||||
| import com.google.gson.annotations.SerializedName | import com.google.gson.annotations.SerializedName | ||||||
| 
 |  | ||||||
| import java.io.Serializable | import java.io.Serializable | ||||||
| import java.util.* |  | ||||||
| 
 | 
 | ||||||
| enum class DirectItemType(val id: Int) : Serializable { | enum class DirectItemType(val id: Int) : Serializable { | ||||||
|     UNKNOWN(0), |     UNKNOWN(0), | ||||||
|  | 
 | ||||||
|     @SerializedName("text") |     @SerializedName("text") | ||||||
|     TEXT(1), |     TEXT(1), | ||||||
|  | 
 | ||||||
|     @SerializedName("like") |     @SerializedName("like") | ||||||
|     LIKE(2), |     LIKE(2), | ||||||
|  | 
 | ||||||
|     @SerializedName("link") |     @SerializedName("link") | ||||||
|     LINK(3), |     LINK(3), | ||||||
|  | 
 | ||||||
|     @SerializedName("media") |     @SerializedName("media") | ||||||
|     MEDIA(4), |     MEDIA(4), | ||||||
|  | 
 | ||||||
|     @SerializedName("raven_media") |     @SerializedName("raven_media") | ||||||
|     RAVEN_MEDIA(5), |     RAVEN_MEDIA(5), | ||||||
|  | 
 | ||||||
|     @SerializedName("profile") |     @SerializedName("profile") | ||||||
|     PROFILE(6), |     PROFILE(6), | ||||||
|  | 
 | ||||||
|     @SerializedName("video_call_event") |     @SerializedName("video_call_event") | ||||||
|     VIDEO_CALL_EVENT(7), |     VIDEO_CALL_EVENT(7), | ||||||
|  | 
 | ||||||
|     @SerializedName("animated_media") |     @SerializedName("animated_media") | ||||||
|     ANIMATED_MEDIA(8), |     ANIMATED_MEDIA(8), | ||||||
|  | 
 | ||||||
|     @SerializedName("voice_media") |     @SerializedName("voice_media") | ||||||
|     VOICE_MEDIA(9), |     VOICE_MEDIA(9), | ||||||
|  | 
 | ||||||
|     @SerializedName("media_share") |     @SerializedName("media_share") | ||||||
|     MEDIA_SHARE(10), |     MEDIA_SHARE(10), | ||||||
|  | 
 | ||||||
|     @SerializedName("reel_share") |     @SerializedName("reel_share") | ||||||
|     REEL_SHARE(11), |     REEL_SHARE(11), | ||||||
|  | 
 | ||||||
|     @SerializedName("action_log") |     @SerializedName("action_log") | ||||||
|     ACTION_LOG(12), |     ACTION_LOG(12), | ||||||
|  | 
 | ||||||
|     @SerializedName("placeholder") |     @SerializedName("placeholder") | ||||||
|     PLACEHOLDER(13), |     PLACEHOLDER(13), | ||||||
|  | 
 | ||||||
|     @SerializedName("story_share") |     @SerializedName("story_share") | ||||||
|     STORY_SHARE(14), |     STORY_SHARE(14), | ||||||
|  | 
 | ||||||
|     @SerializedName("clip") |     @SerializedName("clip") | ||||||
|     CLIP(15),        // media_share but reel |     CLIP(15),        // media_share but reel | ||||||
|  | 
 | ||||||
|     @SerializedName("felix_share") |     @SerializedName("felix_share") | ||||||
|     FELIX_SHARE(16), // media_share but igtv |     FELIX_SHARE(16), // media_share but igtv | ||||||
|  | 
 | ||||||
|     @SerializedName("location") |     @SerializedName("location") | ||||||
|     LOCATION(17), |     LOCATION(17), | ||||||
|  | 
 | ||||||
|     @SerializedName("xma") |     @SerializedName("xma") | ||||||
|     XMA(18); // self avatar stickers |     XMA(18); // self avatar stickers | ||||||
| 
 | 
 | ||||||
| @ -52,7 +68,6 @@ enum class DirectItemType(val id: Int) : Serializable { | |||||||
|             return map[id] |             return map[id] | ||||||
|         } |         } | ||||||
| 
 | 
 | ||||||
|         @JvmStatic |  | ||||||
|         fun getName(directItemType: DirectItemType): String? { |         fun getName(directItemType: DirectItemType): String? { | ||||||
|             when (directItemType) { |             when (directItemType) { | ||||||
|                 TEXT -> return "text" |                 TEXT -> return "text" | ||||||
| @ -72,12 +87,12 @@ enum class DirectItemType(val id: Int) : Serializable { | |||||||
|                 CLIP -> return "clip" |                 CLIP -> return "clip" | ||||||
|                 FELIX_SHARE -> return "felix_share" |                 FELIX_SHARE -> return "felix_share" | ||||||
|                 LOCATION -> return "location" |                 LOCATION -> return "location" | ||||||
|  |                 else -> return null | ||||||
|             } |             } | ||||||
|             return null |  | ||||||
|         } |         } | ||||||
| 
 | 
 | ||||||
|         init { |         init { | ||||||
|             for (type in DirectItemType.values()) { |             for (type in values()) { | ||||||
|                 map[type.id] = type |                 map[type.id] = type | ||||||
|             } |             } | ||||||
|         } |         } | ||||||
|  | |||||||
| @ -18,14 +18,14 @@ interface DirectMessagesRepository { | |||||||
|     ): DirectThreadFeedResponse |     ): DirectThreadFeedResponse | ||||||
| 
 | 
 | ||||||
|     @GET("/api/v1/direct_v2/get_badge_count/?no_raven=1") |     @GET("/api/v1/direct_v2/get_badge_count/?no_raven=1") | ||||||
|     fun fetchUnseenCount(): Call<DirectBadgeCount?> |     suspend fun fetchUnseenCount(): DirectBadgeCount | ||||||
| 
 | 
 | ||||||
|     @FormUrlEncoded |     @FormUrlEncoded | ||||||
|     @POST("/api/v1/direct_v2/threads/broadcast/{item}/") |     @POST("/api/v1/direct_v2/threads/broadcast/{item}/") | ||||||
|     fun broadcast( |     suspend fun broadcast( | ||||||
|         @Path("item") item: String, |         @Path("item") item: String, | ||||||
|         @FieldMap signedForm: Map<String, String>, |         @FieldMap signedForm: Map<String, String>, | ||||||
|     ): Call<DirectThreadBroadcastResponse?> |     ): DirectThreadBroadcastResponse | ||||||
| 
 | 
 | ||||||
|     @FormUrlEncoded |     @FormUrlEncoded | ||||||
|     @POST("/api/v1/direct_v2/threads/{threadId}/add_user/") |     @POST("/api/v1/direct_v2/threads/{threadId}/add_user/") | ||||||
|  | |||||||
							
								
								
									
										19
									
								
								app/src/main/java/awais/instagrabber/utils/CoroutineUtils.kt
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										19
									
								
								app/src/main/java/awais/instagrabber/utils/CoroutineUtils.kt
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,19 @@ | |||||||
|  | package awais.instagrabber.utils | ||||||
|  | 
 | ||||||
|  | import kotlinx.coroutines.CoroutineDispatcher | ||||||
|  | import kotlinx.coroutines.Dispatchers | ||||||
|  | import java.util.function.BiConsumer | ||||||
|  | import kotlin.coroutines.Continuation | ||||||
|  | import kotlin.coroutines.CoroutineContext | ||||||
|  | 
 | ||||||
|  | @JvmOverloads | ||||||
|  | fun <R> getContinuation(onFinished: BiConsumer<R?, Throwable?>, dispatcher: CoroutineDispatcher = Dispatchers.Default): Continuation<R> { | ||||||
|  |     return object : Continuation<R> { | ||||||
|  |         override val context: CoroutineContext | ||||||
|  |             get() = dispatcher | ||||||
|  | 
 | ||||||
|  |         override fun resumeWith(result: Result<R>) { | ||||||
|  |             onFinished.accept(result.getOrNull(), result.exceptionOrNull()) | ||||||
|  |         } | ||||||
|  |     } | ||||||
|  | } | ||||||
| @ -32,5 +32,6 @@ class DirectInboxViewModel : ViewModel() { | |||||||
| 
 | 
 | ||||||
|     init { |     init { | ||||||
|         inboxManager.fetchInbox(viewModelScope) |         inboxManager.fetchInbox(viewModelScope) | ||||||
|  |         inboxManager.fetchUnseenCount(viewModelScope) | ||||||
|     } |     } | ||||||
| } | } | ||||||
| @ -74,15 +74,15 @@ class DirectThreadViewModel( | |||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|     fun sendText(text: String): LiveData<Resource<Any?>> { |     fun sendText(text: String): LiveData<Resource<Any?>> { | ||||||
|         return threadManager.sendText(text) |         return threadManager.sendText(text, viewModelScope) | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|     fun sendUri(entry: MediaController.MediaEntry): LiveData<Resource<Any?>> { |     fun sendUri(entry: MediaController.MediaEntry): LiveData<Resource<Any?>> { | ||||||
|         return threadManager.sendUri(entry) |         return threadManager.sendUri(entry, viewModelScope) | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|     fun sendUri(uri: Uri): LiveData<Resource<Any?>> { |     fun sendUri(uri: Uri): LiveData<Resource<Any?>> { | ||||||
|         return threadManager.sendUri(uri) |         return threadManager.sendUri(uri, viewModelScope) | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|     fun startRecording(): LiveData<Resource<Any?>> { |     fun startRecording(): LiveData<Resource<Any?>> { | ||||||
| @ -106,12 +106,15 @@ class DirectThreadViewModel( | |||||||
|                     MediaUtils.getVoiceInfo(contentResolver, uri, object : OnInfoLoadListener<VideoInfo?> { |                     MediaUtils.getVoiceInfo(contentResolver, uri, object : OnInfoLoadListener<VideoInfo?> { | ||||||
|                         override fun onLoad(videoInfo: VideoInfo?) { |                         override fun onLoad(videoInfo: VideoInfo?) { | ||||||
|                             if (videoInfo == null) return |                             if (videoInfo == null) return | ||||||
|                             threadManager.sendVoice(data, |                             threadManager.sendVoice( | ||||||
|  |                                 data, | ||||||
|                                 uri, |                                 uri, | ||||||
|                                 result.waveform, |                                 result.waveform, | ||||||
|                                 result.samplingFreq, |                                 result.samplingFreq, | ||||||
|                                 videoInfo.duration, |                                 videoInfo.duration, | ||||||
|                                 videoInfo.size) |                                 videoInfo.size, | ||||||
|  |                                 viewModelScope, | ||||||
|  |                             ) | ||||||
|                         } |                         } | ||||||
| 
 | 
 | ||||||
|                         override fun onFailure(t: Throwable) { |                         override fun onFailure(t: Throwable) { | ||||||
| @ -133,11 +136,11 @@ class DirectThreadViewModel( | |||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|     fun sendReaction(item: DirectItem, emoji: Emoji): LiveData<Resource<Any?>> { |     fun sendReaction(item: DirectItem, emoji: Emoji): LiveData<Resource<Any?>> { | ||||||
|         return threadManager.sendReaction(item, emoji) |         return threadManager.sendReaction(item, emoji, viewModelScope) | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|     fun sendDeleteReaction(itemId: String): LiveData<Resource<Any?>> { |     fun sendDeleteReaction(itemId: String): LiveData<Resource<Any?>> { | ||||||
|         return threadManager.sendDeleteReaction(itemId) |         return threadManager.sendDeleteReaction(itemId, viewModelScope) | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|     fun unsend(item: DirectItem): LiveData<Resource<Any?>> { |     fun unsend(item: DirectItem): LiveData<Resource<Any?>> { | ||||||
| @ -145,7 +148,7 @@ class DirectThreadViewModel( | |||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|     fun sendAnimatedMedia(giphyGif: GiphyGif): LiveData<Resource<Any?>> { |     fun sendAnimatedMedia(giphyGif: GiphyGif): LiveData<Resource<Any?>> { | ||||||
|         return threadManager.sendAnimatedMedia(giphyGif) |         return threadManager.sendAnimatedMedia(giphyGif, viewModelScope) | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|     fun getUser(userId: Long): User? { |     fun getUser(userId: Long): User? { | ||||||
| @ -197,7 +200,7 @@ class DirectThreadViewModel( | |||||||
|                 return successEventResObjectLiveData |                 return successEventResObjectLiveData | ||||||
|             } |             } | ||||||
|         } |         } | ||||||
|         return threadManager.markAsSeen(directItem) |         return threadManager.markAsSeen(directItem, viewModelScope) | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|     private val successEventResObjectLiveData: MutableLiveData<Resource<Any?>> |     private val successEventResObjectLiveData: MutableLiveData<Resource<Any?>> | ||||||
|  | |||||||
| @ -53,17 +53,15 @@ class DirectMessagesService private constructor( | |||||||
|         return repository.fetchThread(threadId, queryMap) |         return repository.fetchThread(threadId, queryMap) | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|     fun fetchUnseenCount(): Call<DirectBadgeCount?> { |     suspend fun fetchUnseenCount(): DirectBadgeCount = repository.fetchUnseenCount() | ||||||
|         return repository.fetchUnseenCount() |  | ||||||
|     } |  | ||||||
| 
 | 
 | ||||||
|     fun broadcastText( |     suspend fun broadcastText( | ||||||
|         clientContext: String, |         clientContext: String, | ||||||
|         threadIdOrUserIds: ThreadIdOrUserIds, |         threadIdOrUserIds: ThreadIdOrUserIds, | ||||||
|         text: String, |         text: String, | ||||||
|         repliedToItemId: String?, |         repliedToItemId: String?, | ||||||
|         repliedToClientContext: String?, |         repliedToClientContext: String?, | ||||||
|     ): Call<DirectThreadBroadcastResponse?> { |     ): DirectThreadBroadcastResponse { | ||||||
|         val urls = extractUrls(text) |         val urls = extractUrls(text) | ||||||
|         if (urls.isNotEmpty()) { |         if (urls.isNotEmpty()) { | ||||||
|             return broadcastLink(clientContext, threadIdOrUserIds, text, urls, repliedToItemId, repliedToClientContext) |             return broadcastLink(clientContext, threadIdOrUserIds, text, urls, repliedToItemId, repliedToClientContext) | ||||||
| @ -76,14 +74,14 @@ class DirectMessagesService private constructor( | |||||||
|         return broadcast(broadcastOptions) |         return broadcast(broadcastOptions) | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|     private fun broadcastLink( |     private suspend fun broadcastLink( | ||||||
|         clientContext: String, |         clientContext: String, | ||||||
|         threadIdOrUserIds: ThreadIdOrUserIds, |         threadIdOrUserIds: ThreadIdOrUserIds, | ||||||
|         linkText: String, |         linkText: String, | ||||||
|         urls: List<String>, |         urls: List<String>, | ||||||
|         repliedToItemId: String?, |         repliedToItemId: String?, | ||||||
|         repliedToClientContext: String?, |         repliedToClientContext: String?, | ||||||
|     ): Call<DirectThreadBroadcastResponse?> { |     ): DirectThreadBroadcastResponse { | ||||||
|         val broadcastOptions = LinkBroadcastOptions(clientContext, threadIdOrUserIds, linkText, urls) |         val broadcastOptions = LinkBroadcastOptions(clientContext, threadIdOrUserIds, linkText, urls) | ||||||
|         if (!repliedToItemId.isNullOrBlank() && !repliedToClientContext.isNullOrBlank()) { |         if (!repliedToItemId.isNullOrBlank() && !repliedToClientContext.isNullOrBlank()) { | ||||||
|             broadcastOptions.repliedToItemId = repliedToItemId |             broadcastOptions.repliedToItemId = repliedToItemId | ||||||
| @ -92,70 +90,70 @@ class DirectMessagesService private constructor( | |||||||
|         return broadcast(broadcastOptions) |         return broadcast(broadcastOptions) | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|     fun broadcastPhoto( |     suspend fun broadcastPhoto( | ||||||
|         clientContext: String, |         clientContext: String, | ||||||
|         threadIdOrUserIds: ThreadIdOrUserIds, |         threadIdOrUserIds: ThreadIdOrUserIds, | ||||||
|         uploadId: String, |         uploadId: String, | ||||||
|     ): Call<DirectThreadBroadcastResponse?> { |     ): DirectThreadBroadcastResponse { | ||||||
|         return broadcast(PhotoBroadcastOptions(clientContext, threadIdOrUserIds, true, uploadId)) |         return broadcast(PhotoBroadcastOptions(clientContext, threadIdOrUserIds, true, uploadId)) | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|     fun broadcastVideo( |     suspend fun broadcastVideo( | ||||||
|         clientContext: String, |         clientContext: String, | ||||||
|         threadIdOrUserIds: ThreadIdOrUserIds, |         threadIdOrUserIds: ThreadIdOrUserIds, | ||||||
|         uploadId: String, |         uploadId: String, | ||||||
|         videoResult: String, |         videoResult: String, | ||||||
|         sampled: Boolean, |         sampled: Boolean, | ||||||
|     ): Call<DirectThreadBroadcastResponse?> { |     ): DirectThreadBroadcastResponse { | ||||||
|         return broadcast(VideoBroadcastOptions(clientContext, threadIdOrUserIds, videoResult, uploadId, sampled)) |         return broadcast(VideoBroadcastOptions(clientContext, threadIdOrUserIds, videoResult, uploadId, sampled)) | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|     fun broadcastVoice( |     suspend fun broadcastVoice( | ||||||
|         clientContext: String, |         clientContext: String, | ||||||
|         threadIdOrUserIds: ThreadIdOrUserIds, |         threadIdOrUserIds: ThreadIdOrUserIds, | ||||||
|         uploadId: String, |         uploadId: String, | ||||||
|         waveform: List<Float>, |         waveform: List<Float>, | ||||||
|         samplingFreq: Int, |         samplingFreq: Int, | ||||||
|     ): Call<DirectThreadBroadcastResponse?> { |     ): DirectThreadBroadcastResponse { | ||||||
|         return broadcast(VoiceBroadcastOptions(clientContext, threadIdOrUserIds, uploadId, waveform, samplingFreq)) |         return broadcast(VoiceBroadcastOptions(clientContext, threadIdOrUserIds, uploadId, waveform, samplingFreq)) | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|     fun broadcastStoryReply( |     suspend fun broadcastStoryReply( | ||||||
|         threadIdOrUserIds: ThreadIdOrUserIds, |         threadIdOrUserIds: ThreadIdOrUserIds, | ||||||
|         text: String, |         text: String, | ||||||
|         mediaId: String, |         mediaId: String, | ||||||
|         reelId: String, |         reelId: String, | ||||||
|     ): Call<DirectThreadBroadcastResponse?> { |     ): DirectThreadBroadcastResponse { | ||||||
|         return broadcast(StoryReplyBroadcastOptions(UUID.randomUUID().toString(), threadIdOrUserIds, text, mediaId, reelId)) |         return broadcast(StoryReplyBroadcastOptions(UUID.randomUUID().toString(), threadIdOrUserIds, text, mediaId, reelId)) | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|     fun broadcastReaction( |     suspend fun broadcastReaction( | ||||||
|         clientContext: String, |         clientContext: String, | ||||||
|         threadIdOrUserIds: ThreadIdOrUserIds, |         threadIdOrUserIds: ThreadIdOrUserIds, | ||||||
|         itemId: String, |         itemId: String, | ||||||
|         emoji: String?, |         emoji: String?, | ||||||
|         delete: Boolean, |         delete: Boolean, | ||||||
|     ): Call<DirectThreadBroadcastResponse?> { |     ): DirectThreadBroadcastResponse { | ||||||
|         return broadcast(ReactionBroadcastOptions(clientContext, threadIdOrUserIds, itemId, emoji, delete)) |         return broadcast(ReactionBroadcastOptions(clientContext, threadIdOrUserIds, itemId, emoji, delete)) | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|     fun broadcastAnimatedMedia( |     suspend fun broadcastAnimatedMedia( | ||||||
|         clientContext: String, |         clientContext: String, | ||||||
|         threadIdOrUserIds: ThreadIdOrUserIds, |         threadIdOrUserIds: ThreadIdOrUserIds, | ||||||
|         giphyGif: GiphyGif, |         giphyGif: GiphyGif, | ||||||
|     ): Call<DirectThreadBroadcastResponse?> { |     ): DirectThreadBroadcastResponse { | ||||||
|         return broadcast(AnimatedMediaBroadcastOptions(clientContext, threadIdOrUserIds, giphyGif)) |         return broadcast(AnimatedMediaBroadcastOptions(clientContext, threadIdOrUserIds, giphyGif)) | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|     fun broadcastMediaShare( |     suspend fun broadcastMediaShare( | ||||||
|         clientContext: String, |         clientContext: String, | ||||||
|         threadIdOrUserIds: ThreadIdOrUserIds, |         threadIdOrUserIds: ThreadIdOrUserIds, | ||||||
|         mediaId: String, |         mediaId: String, | ||||||
|     ): Call<DirectThreadBroadcastResponse?> { |     ): DirectThreadBroadcastResponse { | ||||||
|         return broadcast(MediaShareBroadcastOptions(clientContext, threadIdOrUserIds, mediaId)) |         return broadcast(MediaShareBroadcastOptions(clientContext, threadIdOrUserIds, mediaId)) | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|     private fun broadcast(broadcastOptions: BroadcastOptions): Call<DirectThreadBroadcastResponse?> { |     private suspend fun broadcast(broadcastOptions: BroadcastOptions): DirectThreadBroadcastResponse { | ||||||
|         require(!isEmpty(broadcastOptions.clientContext)) { "Broadcast requires a valid client context value" } |         require(!isEmpty(broadcastOptions.clientContext)) { "Broadcast requires a valid client context value" } | ||||||
|         val form = mutableMapOf<String, Any>() |         val form = mutableMapOf<String, Any>() | ||||||
|         val threadId = broadcastOptions.threadId |         val threadId = broadcastOptions.threadId | ||||||
|  | |||||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user