private void retweetOrQuote(AsyncTwitterWrapper twitter, ParcelableStatus status) { final Dialog dialog = getDialog(); if (dialog == null) return; final EditText editComment = ((EditText) dialog.findViewById(R.id.edit_comment)); if (editComment.length() > 0) { final Menu menu = mPopupMenu.getMenu(); final MenuItem quoteOriginalStatus = menu.findItem(R.id.quote_original_status); final MenuItem linkToQuotedStatus = menu.findItem(R.id.link_to_quoted_status); final Uri statusLink; final long inReplyToStatusId; if (!status.is_quote || !quoteOriginalStatus.isChecked()) { inReplyToStatusId = status.id; statusLink = LinkCreator.getTwitterStatusLink(status.user_screen_name, status.id); } else { inReplyToStatusId = status.quoted_id; statusLink = LinkCreator.getTwitterStatusLink(status.quoted_user_screen_name, status.quoted_id); } final String commentText = editComment.getText() + " " + statusLink; twitter.updateStatusAsync( new long[] {status.account_id}, commentText, null, null, linkToQuotedStatus.isChecked() ? inReplyToStatusId : -1, status.is_possibly_sensitive); } else if (isMyRetweet(status)) { twitter.cancelRetweetAsync(status.account_id, status.id, status.my_retweet_id); } else { twitter.retweetStatusAsync(status.account_id, status.id); } }
@Override public void onClick(final DialogInterface dialog, final int which) { switch (which) { case DialogInterface.BUTTON_POSITIVE: final ParcelableUser user = getUser(); final AsyncTwitterWrapper twitter = getTwitterWrapper(); if (user == null || twitter == null) return; twitter.createBlockAsync(user.account_id, user.id); break; default: break; } }
@Override public void onClick(final DialogInterface dialog, final int which) { switch (which) { case DialogInterface.BUTTON_POSITIVE: final ParcelableUserList userList = getUserList(); final AsyncTwitterWrapper twitter = mTwitterWrapper; if (userList == null || twitter == null) return; twitter.destroyUserListSubscriptionAsync(userList.account_key, userList.id); break; default: break; } }
@Override protected List<TwitterWrapper.StatusListResponse> doInBackground(final Object... params) { final List<TwitterWrapper.StatusListResponse> result = new ArrayList<>(); if (accountIds == null) return result; int idx = 0; final SharedPreferencesWrapper preferences = twitterWrapper.getPreferences(); final Context context = twitterWrapper.getContext(); final ErrorInfoStore errorInfoStore = twitterWrapper.getErrorInfoStore(); final int loadItemLimit = preferences.getInt(KEY_LOAD_ITEM_LIMIT, DEFAULT_LOAD_ITEM_LIMIT); for (final long accountId : accountIds) { final Twitter twitter = TwitterAPIFactory.getTwitterInstance(context, accountId, true); if (twitter == null) continue; try { final Paging paging = new Paging(); paging.count(loadItemLimit); final long maxId, sinceId; if (maxIds != null && maxIds[idx] > 0) { maxId = maxIds[idx]; paging.maxId(maxId); } else { maxId = -1; } if (sinceIds != null && sinceIds[idx] > 0) { sinceId = sinceIds[idx]; paging.sinceId(sinceId - 1); if (maxIds == null || sinceIds[idx] <= 0) { paging.setLatestResults(true); } } else { sinceId = -1; } final List<org.mariotaku.twidere.api.twitter.model.Status> statuses = getStatuses(twitter, paging); TwitterContentUtils.getStatusesWithQuoteData(twitter, statuses); storeStatus(accountId, statuses, sinceId, maxId, true, loadItemLimit); publishProgress(new TwitterWrapper.StatusListResponse(accountId, statuses)); errorInfoStore.remove(getErrorInfoKey(), accountId); } catch (final TwitterException e) { if (BuildConfig.DEBUG) { Log.w(LOGTAG, e); } if (e.isCausedByNetworkIssue()) { errorInfoStore.put(getErrorInfoKey(), accountId, ErrorInfoStore.CODE_NETWORK_ERROR); } result.add(new TwitterWrapper.StatusListResponse(accountId, e)); } idx++; } return result; }
@Override protected void onPostExecute(List<TwitterWrapper.StatusListResponse> result) { super.onPostExecute(result); bus.post( new GetStatusesTaskEvent( getDatabaseUri(), false, AsyncTwitterWrapper.getException(result))); }
@SafeVarargs @Override protected final void onProgressUpdate( TwitterWrapper.TwitterListResponse<org.mariotaku.twidere.api.twitter.model.Status>... values) { AsyncTaskUtils.executeTask(new CacheUsersStatusesTask(twitterWrapper.getContext()), values); }
public GetStatusesTask( AsyncTwitterWrapper twitterWrapper, final long[] accountIds, final long[] maxIds, final long[] sinceIds, final String tag) { super(twitterWrapper.getContext(), tag); this.twitterWrapper = twitterWrapper; this.accountIds = accountIds; this.maxIds = maxIds; this.sinceIds = sinceIds; }
private void updateStatuses(ParcelableStatusUpdate... statuses) { final Builder builder = new Builder(this); startForeground( NOTIFICATION_ID_UPDATE_STATUS, updateUpdateStatusNotification(this, builder, 0, null)); for (final ParcelableStatusUpdate item : statuses) { mNotificationManager.notify( NOTIFICATION_ID_UPDATE_STATUS, updateUpdateStatusNotification(this, builder, 0, item)); final ContentValues draftValues = ContentValuesCreator.createStatusDraft( item, ParcelableAccount.getAccountIds(item.accounts)); final Uri draftUri = mResolver.insert(Drafts.CONTENT_URI, draftValues); final long draftId = ParseUtils.parseLong(draftUri.getLastPathSegment(), -1); mTwitter.addSendingDraftId(draftId); final List<SingleResponse<ParcelableStatus>> result = updateStatus(builder, item); boolean failed = false; Exception exception = null; final Expression where = Expression.equals(Drafts._ID, draftId); final List<Long> failedAccountIds = ListUtils.fromArray(ParcelableAccount.getAccountIds(item.accounts)); for (final SingleResponse<ParcelableStatus> response : result) { if (response.getData() == null) { failed = true; if (exception == null) { exception = response.getException(); } } else if (response.getData().account_id > 0) { failedAccountIds.remove(response.getData().account_id); // spice if (response.getData().media == null) { SpiceProfilingUtil.log( response.getData().id + ",Tweet," + response.getData().account_id + "," + response.getData().in_reply_to_user_id + "," + response.getData().in_reply_to_status_id); SpiceProfilingUtil.profile( this.getBaseContext(), response.getData().account_id, response.getData().id + ",Tweet," + response.getData().account_id + "," + response.getData().in_reply_to_user_id + "," + response.getData().in_reply_to_status_id); } else for (final ParcelableMedia spiceMedia : response.getData().media) { SpiceProfilingUtil.log( response.getData().id + ",Media," + response.getData().account_id + "," + response.getData().in_reply_to_user_id + "," + response.getData().in_reply_to_status_id + "," + spiceMedia.media_url + "," + TypeMappingUtil.getMediaType(spiceMedia.type)); SpiceProfilingUtil.profile( this.getBaseContext(), response.getData().account_id, response.getData().id + ",Media," + response.getData().account_id + "," + response.getData().in_reply_to_user_id + "," + response.getData().in_reply_to_status_id + "," + spiceMedia.media_url + "," + TypeMappingUtil.getMediaType(spiceMedia.type)); } // end } } if (result.isEmpty()) { showErrorMessage( R.string.action_updating_status, getString(R.string.no_account_selected), false); } else if (failed) { // If the status is a duplicate, there's no need to save it to // drafts. if (exception instanceof TwitterException && ((TwitterException) exception).getErrorCode() == StatusCodeMessageUtils.STATUS_IS_DUPLICATE) { showErrorMessage(getString(R.string.status_is_duplicate), false); } else { final ContentValues accountIdsValues = new ContentValues(); accountIdsValues.put( Drafts.ACCOUNT_IDS, ListUtils.toString(failedAccountIds, ',', false)); mResolver.update(Drafts.CONTENT_URI, accountIdsValues, where.getSQL(), null); showErrorMessage(R.string.action_updating_status, exception, true); final ContentValues notifValues = new ContentValues(); notifValues.put(BaseColumns._ID, draftId); mResolver.insert(Drafts.CONTENT_URI_NOTIFICATIONS, notifValues); } } else { showOkMessage(R.string.status_updated, false); mResolver.delete(Drafts.CONTENT_URI, where.getSQL(), null); if (item.media != null) { for (final ParcelableMediaUpdate media : item.media) { final String path = getImagePathFromUri(this, Uri.parse(media.uri)); if (path != null) { if (!new File(path).delete()) { Log.d(LOGTAG, String.format("unable to delete %s", path)); } } } } } mTwitter.removeSendingDraftId(draftId); if (mPreferences.getBoolean(KEY_REFRESH_AFTER_TWEET, false)) { mHandler.post( new Runnable() { @Override public void run() { mTwitter.refreshAll(); } }); } } stopForeground(false); mNotificationManager.cancel(NOTIFICATION_ID_UPDATE_STATUS); }
@Override public void displayStatus( @NonNull final ParcelableStatus status, final boolean displayInReplyTo, final boolean shouldDisplayExtraType) { final MediaLoaderWrapper loader = adapter.getMediaLoader(); final AsyncTwitterWrapper twitter = adapter.getTwitterWrapper(); final TwidereLinkify linkify = adapter.getTwidereLinkify(); final BidiFormatter formatter = adapter.getBidiFormatter(); final Context context = adapter.getContext(); final boolean nameFirst = adapter.isNameFirst(); final boolean showCardActions = isCardActionsShown(); actionButtons.setVisibility(showCardActions ? View.VISIBLE : View.GONE); itemMenu.setVisibility(showCardActions ? View.VISIBLE : View.GONE); if (statusContentLowerSpace != null) { statusContentLowerSpace.setVisibility(showCardActions ? View.GONE : View.VISIBLE); } final long replyCount = status.reply_count; final long retweetCount; final long favoriteCount; if (TwitterCardUtils.isPoll(status)) { statusInfoLabel.setText(R.string.label_poll); statusInfoIcon.setImageResource(R.drawable.ic_activity_action_poll); statusInfoLabel.setVisibility(View.VISIBLE); statusInfoIcon.setVisibility(View.VISIBLE); if (statusContentUpperSpace != null) { statusContentUpperSpace.setVisibility(View.GONE); } } else if (status.retweet_id != null) { final String retweetedBy = UserColorNameManager.decideDisplayName( status.retweet_user_nickname, status.retweeted_by_user_name, status.retweeted_by_user_screen_name, nameFirst); statusInfoLabel.setText( context.getString(R.string.name_retweeted, formatter.unicodeWrap(retweetedBy))); statusInfoIcon.setImageResource(R.drawable.ic_activity_action_retweet); statusInfoLabel.setVisibility(View.VISIBLE); statusInfoIcon.setVisibility(View.VISIBLE); if (statusContentUpperSpace != null) { statusContentUpperSpace.setVisibility(View.GONE); } } else if (status.in_reply_to_status_id != null && status.in_reply_to_user_id != null && displayInReplyTo) { final String inReplyTo = UserColorNameManager.decideDisplayName( status.in_reply_to_user_nickname, status.in_reply_to_name, status.in_reply_to_screen_name, nameFirst); statusInfoLabel.setText( context.getString(R.string.in_reply_to_name, formatter.unicodeWrap(inReplyTo))); statusInfoIcon.setImageResource(R.drawable.ic_activity_action_reply); statusInfoLabel.setVisibility(View.VISIBLE); statusInfoIcon.setVisibility(View.VISIBLE); if (statusContentUpperSpace != null) { statusContentUpperSpace.setVisibility(View.GONE); } } else { statusInfoLabel.setVisibility(View.GONE); statusInfoIcon.setVisibility(View.GONE); if (statusContentUpperSpace != null) { statusContentUpperSpace.setVisibility(View.VISIBLE); } } boolean skipLinksInText = status.extras != null && status.extras.support_entities; if (status.is_quote) { quotedNameView.setVisibility(View.VISIBLE); quotedTextView.setVisibility(View.VISIBLE); quoteIndicator.setVisibility(View.VISIBLE); quotedNameView.setName( UserColorNameManager.decideNickname( status.quoted_user_nickname, status.quoted_user_name)); quotedNameView.setScreenName("@" + status.quoted_user_screen_name); if (adapter.getLinkHighlightingStyle() != VALUE_LINK_HIGHLIGHT_OPTION_CODE_NONE) { final SpannableStringBuilder text = SpannableStringBuilder.valueOf(status.quoted_text_unescaped); ParcelableStatusUtils.applySpans(text, status.quoted_spans); linkify.applyAllLinks( text, status.account_key, getLayoutPosition(), status.is_possibly_sensitive, adapter.getLinkHighlightingStyle(), skipLinksInText); quotedTextView.setText(text); } else { final String text = status.quoted_text_unescaped; quotedTextView.setText(text); } quoteIndicator.setColor(status.quoted_user_color); itemContent.drawStart(status.user_color); } else { quotedNameView.setVisibility(View.GONE); quotedTextView.setVisibility(View.GONE); quoteIndicator.setVisibility(View.GONE); if (status.is_retweet) { final int retweetUserColor = status.retweet_user_color; final int userColor = status.user_color; if (retweetUserColor == 0) { itemContent.drawStart(userColor); } else if (userColor == 0) { itemContent.drawStart(retweetUserColor); } else { itemContent.drawStart(retweetUserColor, userColor); } } else { itemContent.drawStart(status.user_color); } } if (status.is_retweet) { timeView.setTime(status.retweet_timestamp); } else { timeView.setTime(status.timestamp); } nameView.setName(UserColorNameManager.decideNickname(status.user_nickname, status.user_name)); nameView.setScreenName("@" + status.user_screen_name); if (statusInfoSpace != null) { statusInfoSpace.setVisibility(View.VISIBLE); } if (adapter.isProfileImageEnabled()) { profileImageView.setVisibility(View.VISIBLE); if (profileImageSpace != null) { profileImageSpace.setVisibility(View.VISIBLE); } loader.displayProfileImage(profileImageView, status); profileTypeView.setImageResource( getUserTypeIconRes(status.user_is_verified, status.user_is_protected)); profileTypeView.setVisibility(View.VISIBLE); } else { profileTypeView.setVisibility(View.GONE); profileImageView.setVisibility(View.GONE); if (profileImageSpace != null) { profileImageSpace.setVisibility(View.GONE); } loader.cancelDisplayTask(profileImageView); profileTypeView.setImageDrawable(null); profileTypeView.setVisibility(View.GONE); } if (adapter.shouldShowAccountsColor()) { itemContent.drawEnd(status.account_color); } else { itemContent.drawEnd(); } if (adapter.isMediaPreviewEnabled() && (adapter.isSensitiveContentEnabled() || !status.is_possibly_sensitive)) { mediaPreview.setStyle(adapter.getMediaPreviewStyle()); quoteMediaPreview.setStyle(adapter.getMediaPreviewStyle()); final boolean showQuotedMedia = !ArrayUtils.isEmpty(status.quoted_media); final boolean showMedia = !showQuotedMedia && !ArrayUtils.isEmpty(status.media); mediaPreview.setVisibility(showMedia ? View.VISIBLE : View.GONE); if (textMediaSpace != null) { textMediaSpace.setVisibility( !status.is_quote && (showMedia || showCardActions) ? View.GONE : View.VISIBLE); } quoteMediaPreview.setVisibility(showQuotedMedia ? View.VISIBLE : View.GONE); if (quotedTextMediaSpace != null) { quotedTextMediaSpace.setVisibility( !status.is_quote || showQuotedMedia ? View.GONE : View.VISIBLE); } mediaPreview.displayMedia( status.media, loader, status.account_key, -1, this, adapter.getMediaLoadingHandler()); quoteMediaPreview.displayMedia( status.quoted_media, loader, status.account_key, -1, this, adapter.getMediaLoadingHandler()); } else { mediaPreview.setVisibility(View.GONE); quoteMediaPreview.setVisibility(View.GONE); if (textMediaSpace != null) { textMediaSpace.setVisibility( showCardActions && !status.is_quote ? View.GONE : View.VISIBLE); } if (quotedTextMediaSpace != null) { quotedTextMediaSpace.setVisibility(status.is_quote ? View.VISIBLE : View.GONE); } } if (adapter.getLinkHighlightingStyle() != VALUE_LINK_HIGHLIGHT_OPTION_CODE_NONE) { final SpannableStringBuilder text = SpannableStringBuilder.valueOf(status.text_unescaped); ParcelableStatusUtils.applySpans(text, status.spans); linkify.applyAllLinks( text, status.account_key, getLayoutPosition(), status.is_possibly_sensitive, adapter.getLinkHighlightingStyle(), skipLinksInText); textView.setText(text); } else { textView.setText(status.text_unescaped); } if (replyCount > 0) { replyCountView.setText(UnitConvertUtils.calculateProperCount(replyCount)); replyCountView.setVisibility(View.VISIBLE); } else { replyCountView.setText(null); replyCountView.setVisibility(View.GONE); } if (twitter.isDestroyingStatus(status.account_key, status.my_retweet_id)) { retweetIconView.setActivated(false); retweetCount = Math.max(0, status.retweet_count - 1); } else { final boolean creatingRetweet = twitter.isCreatingRetweet(status.account_key, status.id); retweetIconView.setActivated( creatingRetweet || status.retweeted || Utils.isMyRetweet( status.account_key, status.retweeted_by_user_key, status.my_retweet_id)); retweetCount = status.retweet_count + (creatingRetweet ? 1 : 0); } if (retweetCount > 0) { retweetCountView.setText(UnitConvertUtils.calculateProperCount(retweetCount)); retweetCountView.setVisibility(View.VISIBLE); } else { retweetCountView.setText(null); retweetCountView.setVisibility(View.GONE); } if (twitter.isDestroyingFavorite(status.account_key, status.id)) { favoriteIconView.setActivated(false); favoriteCount = Math.max(0, status.favorite_count - 1); } else { final boolean creatingFavorite = twitter.isCreatingFavorite(status.account_key, status.id); favoriteIconView.setActivated(creatingFavorite || status.is_favorite); favoriteCount = status.favorite_count + (creatingFavorite ? 1 : 0); } if (favoriteCount > 0) { favoriteCountView.setText(UnitConvertUtils.calculateProperCount(favoriteCount)); favoriteCountView.setVisibility(View.VISIBLE); } else { favoriteCountView.setText(null); favoriteCountView.setVisibility(View.GONE); } if (shouldDisplayExtraType) { displayExtraTypeIcon( status.card_name, status.media, status.location, status.place_full_name, status.is_possibly_sensitive); } else { extraTypeView.setVisibility(View.GONE); } nameView.updateText(formatter); quotedNameView.updateText(formatter); }
private void storeStatus( long accountId, List<org.mariotaku.twidere.api.twitter.model.Status> statuses, long sinceId, long maxId, boolean notify, int loadItemLimit) { if (statuses == null || statuses.isEmpty() || accountId <= 0) { return; } final Uri uri = getDatabaseUri(); final Context context = twitterWrapper.getContext(); final ContentResolver resolver = context.getContentResolver(); final boolean noItemsBefore = DataStoreUtils.getStatusCount(context, uri, accountId) <= 0; final ContentValues[] values = new ContentValues[statuses.size()]; final long[] statusIds = new long[statuses.size()]; long minId = -1; int minIdx = -1; boolean hasIntersection = false; for (int i = 0, j = statuses.size(); i < j; i++) { final org.mariotaku.twidere.api.twitter.model.Status status = statuses.get(i); values[i] = ContentValuesCreator.createStatus(status, accountId); values[i].put(Statuses.INSERTED_DATE, System.currentTimeMillis()); final long id = status.getId(); if (sinceId > 0 && id <= sinceId) { hasIntersection = true; } if (minId == -1 || id < minId) { minId = id; minIdx = i; } statusIds[i] = id; } // Delete all rows conflicting before new data inserted. final Expression accountWhere = Expression.equals(Statuses.ACCOUNT_ID, accountId); final Expression statusWhere = Expression.in(new Columns.Column(Statuses.STATUS_ID), new RawItemArray(statusIds)); final String countWhere = Expression.and(accountWhere, statusWhere).getSQL(); final String[] projection = {SQLFunctions.COUNT()}; final int rowsDeleted; final Cursor countCur = resolver.query(uri, projection, countWhere, null, null); try { if (countCur != null && countCur.moveToFirst()) { rowsDeleted = countCur.getInt(0); } else { rowsDeleted = 0; } } finally { Utils.closeSilently(countCur); } // BEGIN HotMobi final RefreshEvent event = RefreshEvent.create(context, statusIds, getTimelineType()); HotMobiLogger.getInstance(context).log(accountId, event); // END HotMobi // Insert a gap. final boolean deletedOldGap = rowsDeleted > 0 && ArrayUtils.contains(statusIds, maxId); final boolean noRowsDeleted = rowsDeleted == 0; final boolean insertGap = minId > 0 && (noRowsDeleted || deletedOldGap) && !noItemsBefore && !hasIntersection; if (insertGap && minIdx != -1) { values[minIdx].put(Statuses.IS_GAP, true); } // Insert previously fetched items. final Uri insertUri = UriUtils.appendQueryParameters(uri, QUERY_PARAM_NOTIFY, notify); ContentResolverUtils.bulkInsert(resolver, insertUri, values); }