Search in sources :

Example 1 with Post

use of com.github.moko256.latte.client.base.entity.Post in project twicalico by moko256.

the class TwitterStringUtils method setLinkedSequenceTo.

@SuppressLint("StaticFieldLeak")
public static void setLinkedSequenceTo(Status item, TextView textView) {
    Context context = textView.getContext();
    String tweet = item.getText();
    if (GlobalApplication.clientType == Type.MASTODON) {
        Spanned html = Html.fromHtml(tweet);
        int length = html.length();
        // Trim unless \n\n made by fromHtml() after post
        if (length == 3 && item.getMediaEntities().length > 0 && html.charAt(0) == ".".charAt(0)) {
            // If post has media only, context of post from Mastodon is "."
            textView.setText("");
            return;
        } else if (length >= 2) {
            html = (Spanned) html.subSequence(0, length - 2);
        }
        SpannableStringBuilder builder = convertUrlSpanToCustomTabs(html, context);
        textView.setText(builder);
        List<Emoji> list = ((StatusCacheMap.CachedStatus) item).getEmojis();
        if (list != null) {
            Matcher matcher = containsEmoji.matcher(builder);
            boolean matches = matcher.matches();
            int imageSize;
            if (matches) {
                imageSize = (int) Math.floor((textView.getTextSize() * 1.15) * 2.0);
            } else {
                imageSize = (int) Math.floor(textView.getTextSize() * 1.15);
            }
            new AsyncTask<Void, Void, Map<String, Drawable>>() {

                @Override
                protected Map<String, Drawable> doInBackground(Void... params) {
                    Map<String, Drawable> map = new ArrayMap<>();
                    GlideRequests glideRequests = GlideApp.with(context);
                    for (Emoji emoji : list) {
                        try {
                            Drawable value = glideRequests.load(emoji.getUrl()).submit().get();
                            value.setBounds(0, 0, imageSize, imageSize);
                            map.put(emoji.getShortCode(), value);
                        } catch (InterruptedException | ExecutionException e) {
                            e.printStackTrace();
                        }
                    }
                    return map;
                }

                @Override
                protected void onPostExecute(Map<String, Drawable> map) {
                    if (TextUtils.equals(builder, textView.getText())) {
                        boolean found = matches || matcher.find();
                        while (found) {
                            String shortCode = matcher.group(1);
                            Drawable drawable = map.get(shortCode);
                            if (drawable != null) {
                                builder.setSpan(new ImageSpan(drawable), matcher.start(), matcher.end(), Spanned.SPAN_EXCLUSIVE_EXCLUSIVE);
                            }
                            found = matcher.find();
                        }
                        textView.setText(builder);
                    }
                }
            }.execute();
        }
        return;
    }
    SpannableStringBuilder spannableStringBuilder = new SpannableStringBuilder(tweet);
    for (SymbolEntity symbolEntity : item.getSymbolEntities()) {
        spannableStringBuilder.setSpan(new ClickableSpan() {

            @Override
            public void onClick(View view) {
                context.startActivity(SearchResultActivity.getIntent(context, symbolEntity.getText()));
            }
        }, tweet.offsetByCodePoints(0, symbolEntity.getStart()), tweet.offsetByCodePoints(0, symbolEntity.getEnd()), Spanned.SPAN_INCLUSIVE_INCLUSIVE);
    }
    for (HashtagEntity hashtagEntity : item.getHashtagEntities()) {
        spannableStringBuilder.setSpan(new ClickableSpan() {

            @Override
            public void onClick(View view) {
                context.startActivity(SearchResultActivity.getIntent(context, "#" + hashtagEntity.getText()));
            }
        }, tweet.offsetByCodePoints(0, hashtagEntity.getStart()), tweet.offsetByCodePoints(0, hashtagEntity.getEnd()), Spanned.SPAN_INCLUSIVE_INCLUSIVE);
    }
    for (UserMentionEntity userMentionEntity : item.getUserMentionEntities()) {
        spannableStringBuilder.setSpan(new ClickableSpan() {

            @Override
            public void onClick(View view) {
                context.startActivity(ShowUserActivity.getIntent(context, userMentionEntity.getScreenName()));
            }
        }, tweet.offsetByCodePoints(0, userMentionEntity.getStart()), tweet.offsetByCodePoints(0, userMentionEntity.getEnd()), Spanned.SPAN_INCLUSIVE_INCLUSIVE);
    }
    boolean hasMedia = item.getMediaEntities().length > 0;
    List<URLEntity> urlEntities = new ArrayList<>(item.getURLEntities().length + (hasMedia ? 1 : 0));
    urlEntities.addAll(Arrays.asList(item.getURLEntities()));
    if (hasMedia) {
        urlEntities.add(item.getMediaEntities()[0]);
    }
    int tweetLength = tweet.codePointCount(0, tweet.length());
    int sp = 0;
    for (URLEntity entity : urlEntities) {
        String url = entity.getURL();
        String displayUrl = entity.getDisplayURL();
        int urlLength = url.codePointCount(0, url.length());
        int displayUrlLength = displayUrl.codePointCount(0, displayUrl.length());
        if (entity.getStart() <= tweetLength && entity.getEnd() <= tweetLength) {
            int dusp = displayUrlLength - urlLength;
            spannableStringBuilder.replace(tweet.offsetByCodePoints(0, entity.getStart()) + sp, tweet.offsetByCodePoints(0, entity.getEnd()) + sp, displayUrl);
            spannableStringBuilder.setSpan(new ClickableSpan() {

                @Override
                public void onClick(View view) {
                    AppCustomTabsKt.launchChromeCustomTabs(context, entity.getExpandedURL());
                }
            }, tweet.offsetByCodePoints(0, entity.getStart()) + sp, tweet.offsetByCodePoints(0, entity.getEnd()) + sp + dusp, Spanned.SPAN_INCLUSIVE_INCLUSIVE);
            sp += dusp;
        }
    }
    textView.setText(spannableStringBuilder);
}
Also used : Matcher(java.util.regex.Matcher) GlideRequests(com.github.moko256.twicalico.GlideRequests) ArrayList(java.util.ArrayList) SymbolEntity(twitter4j.SymbolEntity) Emoji(com.github.moko256.twicalico.entity.Emoji) HashtagEntity(twitter4j.HashtagEntity) Context(android.content.Context) URLEntity(twitter4j.URLEntity) Drawable(android.graphics.drawable.Drawable) Spanned(android.text.Spanned) ClickableSpan(android.text.style.ClickableSpan) View(android.view.View) TextView(android.widget.TextView) SuppressLint(android.annotation.SuppressLint) UserMentionEntity(twitter4j.UserMentionEntity) ArrayMap(android.support.v4.util.ArrayMap) Map(java.util.Map) StatusCacheMap(com.github.moko256.twicalico.cacheMap.StatusCacheMap) SpannableStringBuilder(android.text.SpannableStringBuilder) ImageSpan(android.text.style.ImageSpan) SuppressLint(android.annotation.SuppressLint)

Example 2 with Post

use of com.github.moko256.latte.client.base.entity.Post in project twicalico by moko256.

the class ShowTweetActivity method onCreate.

@SuppressLint("WrongConstant")
@Override
public void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_show_tweet);
    statusId = getIntent().getLongExtra("statusId", -1);
    client = GlobalApplicationKt.getClient(this);
    requestManager = Glide.with(this);
    statusActionModel = new StatusActionModelImpl(client.getApiClient(), client.getPostCache());
    ActionBar actionBar = getSupportActionBar();
    actionBar.setDisplayHomeAsUpEnabled(true);
    actionBar.setHomeAsUpIndicator(R.drawable.ic_back_white_24dp);
    tweetIsReply = findViewById(R.id.tweet_show_is_reply_text);
    statusViewBinder = new StatusViewBinder(findViewById(R.id.tweet_show_tweet));
    timestampText = findViewById(R.id.tweet_show_timestamp);
    viaText = findViewById(R.id.tweet_show_via);
    replyFab = findViewById(R.id.tweet_show_fab);
    SwipeRefreshLayout swipeRefreshLayout = findViewById(R.id.tweet_show_swipe_refresh);
    swipeRefreshLayout.setColorSchemeResources(R.color.color_primary);
    swipeRefreshLayout.setOnRefreshListener(() -> statusActionModel.updateStatus(statusId));
    disposables.addAll(statusActionModel.getStatusObservable().subscribe(id -> {
        Post post = client.getPostCache().getPost(statusId);
        if (post != null) {
            if (!isVisible) {
                isVisible = true;
                swipeRefreshLayout.getChildAt(0).setVisibility(VISIBLE);
            }
            updateView(post);
        }
        swipeRefreshLayout.setRefreshing(false);
    }), statusActionModel.getDidActionObservable().subscribe(it -> Toast.makeText(this, TwitterStringUtils.getDidActionStringRes(client.getAccessToken().getClientType(), it), Toast.LENGTH_SHORT).show()), statusActionModel.getErrorObservable().subscribe(error -> {
        error.printStackTrace();
        Toast.makeText(this, error.getMessage(), Toast.LENGTH_LONG).show();
        swipeRefreshLayout.setRefreshing(false);
        if (client.getPostCache().getPost(statusId) == null) {
            finish();
        }
    }));
    Post status = client.getPostCache().getPost(statusId);
    if (status != null) {
        updateView(status);
    } else {
        swipeRefreshLayout.setRefreshing(true);
        isVisible = false;
        swipeRefreshLayout.getChildAt(0).setVisibility(GONE);
        statusActionModel.updateStatus(statusId);
    }
}
Also used : Context(android.content.Context) Bundle(android.os.Bundle) StatusActionModel(com.github.moko256.twitlatte.model.base.StatusActionModel) Intent(android.content.Intent) LinkMovementMethod(android.text.method.LinkMovementMethod) AppCompatActivity(androidx.appcompat.app.AppCompatActivity) AppCustomTabsKt(com.github.moko256.twitlatte.intent.AppCustomTabsKt) MenuItem(android.view.MenuItem) ClipData(android.content.ClipData) ActionBar(androidx.appcompat.app.ActionBar) SuppressLint(android.annotation.SuppressLint) ActivityOptionsCompat(androidx.core.app.ActivityOptionsCompat) RequestManager(com.bumptech.glide.RequestManager) TwitterStringUtils(com.github.moko256.twitlatte.text.TwitterStringUtils) Toast(android.widget.Toast) FloatingActionButton(com.google.android.material.floatingactionbutton.FloatingActionButton) Menu(android.view.Menu) ClipboardManager(android.content.ClipboardManager) View(android.view.View) Button(android.widget.Button) VISIBLE(android.view.View.VISIBLE) StatusActionModelImpl(com.github.moko256.twitlatte.model.impl.StatusActionModelImpl) DateFormat(java.text.DateFormat) Post(com.github.moko256.latte.client.base.entity.Post) SwipeRefreshLayout(androidx.swiperefreshlayout.widget.SwipeRefreshLayout) Client(com.github.moko256.twitlatte.entity.Client) CompositeDisposable(io.reactivex.disposables.CompositeDisposable) Unit(kotlin.Unit) TextView(android.widget.TextView) Glide(com.bumptech.glide.Glide) GONE(android.view.View.GONE) StatusActionModelImpl(com.github.moko256.twitlatte.model.impl.StatusActionModelImpl) Post(com.github.moko256.latte.client.base.entity.Post) SwipeRefreshLayout(androidx.swiperefreshlayout.widget.SwipeRefreshLayout) ActionBar(androidx.appcompat.app.ActionBar) SuppressLint(android.annotation.SuppressLint)

Example 3 with Post

use of com.github.moko256.latte.client.base.entity.Post in project twicalico by moko256.

the class ShowTweetActivity method updateView.

private void updateView(Post item) {
    shareUrl = item.getStatus().getUrl();
    long replyTweetId = item.getStatus().getInReplyToStatusId();
    if (replyTweetId != -1) {
        tweetIsReply.setVisibility(VISIBLE);
        tweetIsReply.setOnClickListener(v -> startActivity(GlobalApplicationKt.setAccountKeyForActivity(getIntent(this, replyTweetId), this)));
    } else {
        tweetIsReply.setVisibility(GONE);
    }
    statusViewBinder.getTweetSpoilerText().setOnLongClickListener(v -> {
        Toast.makeText(this, R.string.did_copy, Toast.LENGTH_SHORT).show();
        ClipboardManager clipboard = (ClipboardManager) getSystemService(CLIPBOARD_SERVICE);
        clipboard.setPrimaryClip(ClipData.newPlainText("spoiler_text", item.getStatus().getSpoilerText()));
        return true;
    });
    statusViewBinder.getTweetContext().setOnLongClickListener(v -> {
        Toast.makeText(this, R.string.did_copy, Toast.LENGTH_SHORT).show();
        ClipboardManager clipboard = (ClipboardManager) getSystemService(CLIPBOARD_SERVICE);
        clipboard.setPrimaryClip(ClipData.newPlainText("post_context", item.getStatus().getText()));
        return true;
    });
    statusViewBinder.getUserImage().setOnClickListener(v -> {
        ActivityOptionsCompat animation = ActivityOptionsCompat.makeSceneTransitionAnimation(this, v, "icon_image");
        startActivity(GlobalApplicationKt.setAccountKeyForActivity(ShowUserActivity.getIntent(this, item.getUser().getId()), this), animation.toBundle());
    });
    statusViewBinder.setOnQuotedStatusClicked(v -> startActivity(GlobalApplicationKt.setAccountKeyForActivity(ShowTweetActivity.getIntent(this, item.getQuotedRepeatingStatus().getId()), this)));
    statusViewBinder.setOnCardClicked(v -> AppCustomTabsKt.launchChromeCustomTabs(this, item.getStatus().getCard().getUrl(), false));
    statusViewBinder.getLikeButton().setOnCheckedChangeListener((compoundButton, b) -> {
        if (b) {
            statusActionModel.createFavorite(item.getId());
        } else {
            statusActionModel.removeFavorite(item.getId());
        }
        return Unit.INSTANCE;
    });
    statusViewBinder.getRepeatButton().setOnCheckedChangeListener((compoundButton, b) -> {
        if (b) {
            statusActionModel.createRepeat(item.getId());
        } else {
            statusActionModel.removeRepeat(item.getId());
        }
        return Unit.INSTANCE;
    });
    View.OnClickListener replyOnClickListener = v -> startActivity(PostActivity.getIntent(this, item.getStatus().getId(), TwitterStringUtils.convertToReplyTopString(client.getUserCache().get(client.getAccessToken().getUserId()).getScreenName(), item.getUser().getScreenName(), item.getStatus().getMentions()).toString()));
    statusViewBinder.getReplyButton().setOnClickListener(replyOnClickListener);
    replyFab.setOnClickListener(replyOnClickListener);
    statusViewBinder.setStatus(client, requestManager, item.getRepeatedUser(), item.getRepeat(), item.getUser(), item.getStatus(), item.getQuotedRepeatingUser(), item.getQuotedRepeatingStatus());
    statusViewBinder.getSendVote().setOnClickListener(v -> statusActionModel.sendVote(statusId, item.getStatus().getPoll().getId(), statusViewBinder.getPollAdapter().getSelections()));
    timestampText.setText(DateFormat.getDateTimeInstance(DateFormat.FULL, DateFormat.FULL).format(item.getStatus().getCreatedAt()));
    if (item.getStatus().getSourceName() != null) {
        viaText.setText(TwitterStringUtils.appendLinkAtViaText(item.getStatus().getSourceName(), item.getStatus().getSourceWebsite()));
        viaText.setMovementMethod(new LinkMovementMethod());
    } else {
        viaText.setVisibility(GONE);
    }
}
Also used : ClipboardManager(android.content.ClipboardManager) Context(android.content.Context) Bundle(android.os.Bundle) StatusActionModel(com.github.moko256.twitlatte.model.base.StatusActionModel) Intent(android.content.Intent) LinkMovementMethod(android.text.method.LinkMovementMethod) AppCompatActivity(androidx.appcompat.app.AppCompatActivity) AppCustomTabsKt(com.github.moko256.twitlatte.intent.AppCustomTabsKt) MenuItem(android.view.MenuItem) ClipData(android.content.ClipData) ActionBar(androidx.appcompat.app.ActionBar) SuppressLint(android.annotation.SuppressLint) ActivityOptionsCompat(androidx.core.app.ActivityOptionsCompat) RequestManager(com.bumptech.glide.RequestManager) TwitterStringUtils(com.github.moko256.twitlatte.text.TwitterStringUtils) Toast(android.widget.Toast) FloatingActionButton(com.google.android.material.floatingactionbutton.FloatingActionButton) Menu(android.view.Menu) ClipboardManager(android.content.ClipboardManager) View(android.view.View) Button(android.widget.Button) VISIBLE(android.view.View.VISIBLE) StatusActionModelImpl(com.github.moko256.twitlatte.model.impl.StatusActionModelImpl) DateFormat(java.text.DateFormat) Post(com.github.moko256.latte.client.base.entity.Post) SwipeRefreshLayout(androidx.swiperefreshlayout.widget.SwipeRefreshLayout) Client(com.github.moko256.twitlatte.entity.Client) CompositeDisposable(io.reactivex.disposables.CompositeDisposable) Unit(kotlin.Unit) TextView(android.widget.TextView) Glide(com.bumptech.glide.Glide) GONE(android.view.View.GONE) LinkMovementMethod(android.text.method.LinkMovementMethod) ActivityOptionsCompat(androidx.core.app.ActivityOptionsCompat) View(android.view.View) TextView(android.widget.TextView)

Example 4 with Post

use of com.github.moko256.latte.client.base.entity.Post in project twicalico by moko256.

the class StatusesAdapter method onBindViewHolder.

@Override
public void onBindViewHolder(@NonNull RecyclerView.ViewHolder viewHolder, final int i) {
    if (viewHolder instanceof MoreLoadViewHolder) {
        ViewGroup.LayoutParams layoutParams = viewHolder.itemView.getLayoutParams();
        if (layoutParams instanceof StaggeredGridLayoutManager.LayoutParams) {
            ((StaggeredGridLayoutManager.LayoutParams) layoutParams).setFullSpan(true);
        }
        ((MoreLoadViewHolder) viewHolder).setIsLoading(false);
        viewHolder.itemView.setOnClickListener(v -> {
            ((MoreLoadViewHolder) viewHolder).setIsLoading(true);
            onLoadMoreClick.onClick(i);
        });
    } else {
        Post post = client.getPostCache().getPost(data.get(i));
        if (post != null) {
            if (viewHolder instanceof StatusViewHolder) {
                ((StatusViewHolder) viewHolder).setStatus(client, statusActionModel, glideRequests, post.getRepeatedUser(), post.getRepeat(), post.getUser(), post.getStatus(), post.getQuotedRepeatingUser(), post.getQuotedRepeatingStatus());
            } else if (viewHolder instanceof ImagesOnlyTweetViewHolder) {
                ((ImagesOnlyTweetViewHolder) viewHolder).setStatus(client, post.getStatus(), glideRequests);
            }
        }
    }
}
Also used : ViewGroup(android.view.ViewGroup) Post(com.github.moko256.latte.client.base.entity.Post)

Example 5 with Post

use of com.github.moko256.latte.client.base.entity.Post in project twicalico by moko256.

the class StatusesAdapter method getItemViewType.

@Override
public int getItemViewType(int position) {
    if (data.get(position) == -1L) {
        return R.layout.layout_list_load_more_text;
    }
    Post post = client.getPostCache().getPost(data.get(position));
    if (!(post != null && post.getStatus() != null)) {
        return R.layout.layout_list_load_more_text;
    }
    Status item = post.getStatus();
    User user = post.getUser();
    if ((conf.getBoolean(KEY_IS_PATTERN_TWEET_MUTE, false) && conf.getPattern(KEY_TWEET_MUTE_PATTERN).matcher(item.getText()).find()) || (conf.getBoolean(KEY_IS_PATTERN_USER_SCREEN_NAME_MUTE, false) && conf.getPattern(KEY_USER_SCREEN_NAME_MUTE_PATTERN).matcher(user.getScreenName()).find()) || (conf.getBoolean(KEY_IS_PATTERN_USER_NAME_MUTE, false) && conf.getPattern(KEY_USER_NAME_MUTE_PATTERN).matcher(user.getName()).find()) || (conf.getBoolean(KEY_IS_PATTERN_TWEET_SOURCE_MUTE, false) && conf.getPattern(KEY_TWEET_SOURCE_MUTE_PATTERN).matcher((item.getSourceName() != null) ? item.getSourceName() : "").find())) {
        return R.layout.layout_list_muted_text;
    } else if (shouldShowMediaOnly || (conf.getBoolean(KEY_IS_PATTERN_TWEET_MUTE_SHOW_ONLY_IMAGE, false) && item.getMedias() != null && conf.getPattern(KEY_TWEET_MUTE_SHOW_ONLY_IMAGE_PATTERN).matcher(item.getText()).find())) {
        return R.layout.layout_list_tweet_only_image;
    } else {
        return R.layout.layout_post_card;
    }
}
Also used : Status(com.github.moko256.latte.client.base.entity.Status) User(com.github.moko256.latte.client.base.entity.User) Post(com.github.moko256.latte.client.base.entity.Post)

Aggregations

Post (com.github.moko256.latte.client.base.entity.Post)4 SuppressLint (android.annotation.SuppressLint)3 Context (android.content.Context)3 View (android.view.View)3 TextView (android.widget.TextView)3 ClipData (android.content.ClipData)2 ClipboardManager (android.content.ClipboardManager)2 Intent (android.content.Intent)2 Bundle (android.os.Bundle)2 LinkMovementMethod (android.text.method.LinkMovementMethod)2 Menu (android.view.Menu)2 MenuItem (android.view.MenuItem)2 GONE (android.view.View.GONE)2 VISIBLE (android.view.View.VISIBLE)2 Button (android.widget.Button)2 Toast (android.widget.Toast)2 ActionBar (androidx.appcompat.app.ActionBar)2 AppCompatActivity (androidx.appcompat.app.AppCompatActivity)2 ActivityOptionsCompat (androidx.core.app.ActivityOptionsCompat)2 SwipeRefreshLayout (androidx.swiperefreshlayout.widget.SwipeRefreshLayout)2