Commit 8fb7e4dc authored by Thomas's avatar Thomas
Browse files

comment issue #702 - Add Bubble timeline

parent f976b6dd
Loading
Loading
Loading
Loading
+1 −0
Original line number Diff line number Diff line
@@ -683,6 +683,7 @@ public abstract class BaseMainActivity extends BaseActivity implements NetworkSt
                regex_local = sharedpreferences.getString(getString(R.string.SET_FILTER_REGEX_LOCAL) + currentUserID + currentInstance, null);
                regex_public = sharedpreferences.getString(getString(R.string.SET_FILTER_REGEX_PUBLIC) + currentUserID + currentInstance, null);
                show_art_nsfw = sharedpreferences.getBoolean(getString(R.string.SET_ART_WITH_NSFW) + currentUserID + currentInstance, false);

                binding.profilePicture.setOnClickListener(v -> binding.drawerLayout.openDrawer(GravityCompat.START));
                Helper.loadPP(BaseMainActivity.this, binding.profilePicture, currentAccount);
                headerMainBinding.accountAcc.setText(String.format("%s@%s", currentAccount.mastodon_account.username, currentAccount.instance));
+35 −0
Original line number Diff line number Diff line
package app.fedilab.android.client.entities.app;
/* Copyright 2022 Thomas Schneider
 *
 * This file is a part of Fedilab
 *
 * This program is free software; you can redistribute it and/or modify it under the terms of the
 * GNU General Public License as published by the Free Software Foundation; either version 3 of the
 * License, or (at your option) any later version.
 *
 * Fedilab is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even
 * the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General
 * Public License for more details.
 *
 * You should have received a copy of the GNU General Public License along with Fedilab; if not,
 * see <http://www.gnu.org/licenses>. */

import com.google.gson.annotations.SerializedName;

import java.io.Serializable;
import java.util.List;

public class BubbleTimeline implements Serializable {
    @SerializedName("id")
    public int id;
    @SerializedName("only_media")
    public boolean only_media = false;
    @SerializedName("remote")
    public boolean remote = false;
    @SerializedName("with_muted")
    public boolean with_muted;
    @SerializedName("exclude_visibilities")
    public List<String> exclude_visibilities = null;
    @SerializedName("reply_visibility")
    public String reply_visibility = null;
}
+2 −0
Original line number Diff line number Diff line
@@ -38,6 +38,8 @@ public class PinnedTimeline implements Serializable {
    public RemoteInstance remoteInstance;
    @SerializedName("tagTimeline")
    public TagTimeline tagTimeline;
    @SerializedName("bubbleTimeline")
    public BubbleTimeline bubbleTimeline;
    @SerializedName("mastodonList")
    public MastodonList mastodonList;
    @SerializedName("currentFilter")
+1 −0
Original line number Diff line number Diff line
@@ -257,6 +257,7 @@ public class Helper {
    public static final String ARG_SEARCH_KEYWORD_CACHE = "ARG_SEARCH_KEYWORD_CACHE";
    public static final String ARG_VIEW_MODEL_KEY = "ARG_VIEW_MODEL_KEY";
    public static final String ARG_TAG_TIMELINE = "ARG_TAG_TIMELINE";
    public static final String ARG_BUBBLE_TIMELINE = "ARG_BUBBLE_TIMELINE";
    public static final String ARG_MEDIA_POSITION = "ARG_MEDIA_POSITION";
    public static final String ARG_MEDIA_ATTACHMENT = "ARG_MEDIA_ATTACHMENT";
    public static final String ARG_MEDIA_ATTACHMENTS = "ARG_MEDIA_ATTACHMENTS";
+245 −0
Original line number Diff line number Diff line
@@ -14,6 +14,7 @@ package app.fedilab.android.helper;
 * You should have received a copy of the GNU General Public License along with Fedilab; if not,
 * see <http://www.gnu.org/licenses>. */


import static app.fedilab.android.BaseMainActivity.currentAccount;
import static app.fedilab.android.BaseMainActivity.currentInstance;
import static app.fedilab.android.BaseMainActivity.currentUserID;
@@ -59,6 +60,7 @@ import app.fedilab.android.R;
import app.fedilab.android.activities.MainActivity;
import app.fedilab.android.client.entities.api.MastodonList;
import app.fedilab.android.client.entities.app.BottomMenu;
import app.fedilab.android.client.entities.app.BubbleTimeline;
import app.fedilab.android.client.entities.app.Pinned;
import app.fedilab.android.client.entities.app.PinnedTimeline;
import app.fedilab.android.client.entities.app.RemoteInstance;
@@ -66,6 +68,8 @@ import app.fedilab.android.client.entities.app.StatusCache;
import app.fedilab.android.client.entities.app.TagTimeline;
import app.fedilab.android.client.entities.app.Timeline;
import app.fedilab.android.databinding.ActivityMainBinding;
import app.fedilab.android.databinding.DialogBubbleExcludeVisibilityBinding;
import app.fedilab.android.databinding.DialogBubbleReplyVisibilityBinding;
import app.fedilab.android.databinding.TabCustomDefaultViewBinding;
import app.fedilab.android.databinding.TabCustomViewBinding;
import app.fedilab.android.exception.DBException;
@@ -498,6 +502,9 @@ public class PinnedTimelineHelper {
                    case TAG:
                        tagClick(activity, finalPinned, v, activityMainBinding, finalI, activityMainBinding.tabLayout.getTabAt(finalI).getTag().toString());
                        break;
                    case BUBBLE:
                        bubbleClick(activity, finalPinned, v, activityMainBinding, finalI, activityMainBinding.tabLayout.getTabAt(finalI).getTag().toString());
                        break;
                    case REMOTE:
                        if (pinnedTimelineVisibleList.get(position).remoteInstance.type != RemoteInstance.InstanceType.NITTER) {
                            instanceClick(activity, finalPinned, v, activityMainBinding, finalI, activityMainBinding.tabLayout.getTabAt(finalI).getTag().toString());
@@ -980,6 +987,244 @@ public class PinnedTimelineHelper {
    }


    /**
     * Manage long clicks on Bubble timelines
     *
     * @param activity - BaseMainActivity activity
     * @param pinned   - {@link Pinned}
     * @param view     - View
     * @param position - int position of the tab
     */
    public static void bubbleClick(BaseMainActivity activity, Pinned pinned, View view, ActivityMainBinding activityMainBinding, int position, String slug) {
        int toRemove = itemToRemoveInBottomMenu(activity);
        PopupMenu popup = new PopupMenu(activity, view);
        int offSetPosition = position - (BOTTOM_TIMELINE_COUNT - toRemove);
        SharedPreferences sharedpreferences = PreferenceManager.getDefaultSharedPreferences(activity);
        boolean singleBar = sharedpreferences.getBoolean(activity.getString(R.string.SET_USE_SINGLE_TOPBAR), false);
        if (singleBar) {
            offSetPosition = position;
        }

        if (pinned.pinnedTimelines.get(offSetPosition).bubbleTimeline == null) {
            pinned.pinnedTimelines.get(offSetPosition).bubbleTimeline = new BubbleTimeline();
        }
        BubbleTimeline bubbleTimeline = pinned.pinnedTimelines.get(offSetPosition).bubbleTimeline;

        popup.getMenuInflater()
                .inflate(R.menu.option_bubble_timeline, popup.getMenu());
        Menu menu = popup.getMenu();

        final MenuItem itemMediaOnly = menu.findItem(R.id.action_show_media_only);
        final MenuItem itemRemote = menu.findItem(R.id.action_remote);


        final boolean[] changes = {false};
        final boolean[] mediaOnly = {false};
        final boolean[] remote = {false};
        mediaOnly[0] = bubbleTimeline.only_media;
        remote[0] = bubbleTimeline.remote;
        itemMediaOnly.setChecked(mediaOnly[0]);
        itemRemote.setChecked(remote[0]);
        popup.setOnDismissListener(menu1 -> {
            if (changes[0]) {
                if (activityMainBinding.viewPager.getAdapter() != null) {
                    try {
                        new StatusCache(activity).deleteForSlug(slug);
                    } catch (DBException e) {
                        e.printStackTrace();
                    }

                    SharedPreferences.Editor editor = sharedpreferences.edit();
                    editor.putString(activity.getString(R.string.SET_INNER_MARKER) + BaseMainActivity.currentUserID + BaseMainActivity.currentInstance + slug, null);
                    editor.commit();
                    Fragment fragmentMastodonTimeline = (Fragment) activityMainBinding.viewPager.getAdapter().instantiateItem(activityMainBinding.viewPager, activityMainBinding.tabLayout.getSelectedTabPosition());
                    if (fragmentMastodonTimeline instanceof FragmentMastodonTimeline && fragmentMastodonTimeline.isVisible()) {
                        FragmentTransaction fragTransaction = activity.getSupportFragmentManager().beginTransaction();
                        fragTransaction.detach(fragmentMastodonTimeline).commit();
                        Bundle bundle = new Bundle();
                        bundle.putSerializable(Helper.ARG_TIMELINE_TYPE, Timeline.TimeLineEnum.BUBBLE);
                        bundle.putSerializable(Helper.ARG_BUBBLE_TIMELINE, bubbleTimeline);
                        bundle.putSerializable(Helper.ARG_INITIALIZE_VIEW, false);
                        fragmentMastodonTimeline.setArguments(bundle);
                        FragmentTransaction fragTransaction2 = activity.getSupportFragmentManager().beginTransaction();
                        fragTransaction2.attach(fragmentMastodonTimeline);
                        fragTransaction2.commit();
                        ((FragmentMastodonTimeline) fragmentMastodonTimeline).recreate();
                    }
                }
            }
        });


        int finalOffSetPosition = offSetPosition;
        popup.setOnMenuItemClickListener(item -> {
            item.setShowAsAction(MenuItem.SHOW_AS_ACTION_COLLAPSE_ACTION_VIEW);
            item.setActionView(new View(activity));
            item.setOnActionExpandListener(new MenuItem.OnActionExpandListener() {
                @Override
                public boolean onMenuItemActionExpand(MenuItem item) {
                    return false;
                }

                @Override
                public boolean onMenuItemActionCollapse(MenuItem item) {
                    return false;
                }
            });
            changes[0] = true;
            int itemId = item.getItemId();
            if (itemId == R.id.action_show_media_only) {
                mediaOnly[0] = !mediaOnly[0];
                bubbleTimeline.only_media = mediaOnly[0];
                pinned.pinnedTimelines.get(finalOffSetPosition).bubbleTimeline = bubbleTimeline;
                itemMediaOnly.setChecked(mediaOnly[0]);
                try {
                    new Pinned(activity).updatePinned(pinned);
                } catch (DBException e) {
                    e.printStackTrace();
                }
            } else if (itemId == R.id.action_remote) {
                remote[0] = !remote[0];
                bubbleTimeline.remote = remote[0];
                pinned.pinnedTimelines.get(finalOffSetPosition).bubbleTimeline = bubbleTimeline;
                itemRemote.setChecked(remote[0]);
                try {
                    new Pinned(activity).updatePinned(pinned);
                } catch (DBException e) {
                    e.printStackTrace();
                }
            } else if (itemId == R.id.action_exclude_visibility) {
                AlertDialog.Builder dialogBuilder = new AlertDialog.Builder(activity, Helper.dialogStyle());
                DialogBubbleExcludeVisibilityBinding dialogBinding = DialogBubbleExcludeVisibilityBinding.inflate(activity.getLayoutInflater());
                dialogBuilder.setView(dialogBinding.getRoot());
                dialogBuilder.setTitle(R.string.exclude_visibility);
                if (bubbleTimeline.exclude_visibilities == null) {
                    bubbleTimeline.exclude_visibilities = new ArrayList<>();
                }
                for (String value : bubbleTimeline.exclude_visibilities) {
                    if (value.equalsIgnoreCase("public")) {
                        dialogBinding.valuePublic.setChecked(true);
                    }
                    if (value.equalsIgnoreCase("local")) {
                        dialogBinding.valueLocal.setChecked(true);
                    }
                    if (value.equalsIgnoreCase("direct")) {
                        dialogBinding.valueDirect.setChecked(true);
                    }
                    if (value.equalsIgnoreCase("list")) {
                        dialogBinding.valueList.setChecked(true);
                    }
                    if (value.equalsIgnoreCase("private")) {
                        dialogBinding.valuePrivate.setChecked(true);
                    }
                    if (value.equalsIgnoreCase("unlisted")) {
                        dialogBinding.valueUnlisted.setChecked(true);
                    }
                }
                dialogBinding.valuePrivate.setOnCheckedChangeListener((compoundButton, checked) -> {
                    if (checked) {
                        if (!bubbleTimeline.exclude_visibilities.contains("private")) {
                            bubbleTimeline.exclude_visibilities.add("private");
                        }
                    } else {
                        bubbleTimeline.exclude_visibilities.remove("private");
                    }
                });
                dialogBinding.valueDirect.setOnCheckedChangeListener((compoundButton, checked) -> {
                    if (checked) {
                        if (!bubbleTimeline.exclude_visibilities.contains("direct")) {
                            bubbleTimeline.exclude_visibilities.add("direct");
                        }
                    } else {
                        bubbleTimeline.exclude_visibilities.remove("direct");
                    }
                });
                dialogBinding.valueList.setOnCheckedChangeListener((compoundButton, checked) -> {
                    if (checked) {
                        if (!bubbleTimeline.exclude_visibilities.contains("list")) {
                            bubbleTimeline.exclude_visibilities.add("list");
                        }
                    } else {
                        bubbleTimeline.exclude_visibilities.remove("list");
                    }
                });
                dialogBinding.valueLocal.setOnCheckedChangeListener((compoundButton, checked) -> {
                    if (checked) {
                        if (!bubbleTimeline.exclude_visibilities.contains("local")) {
                            bubbleTimeline.exclude_visibilities.add("local");
                        }
                    } else {
                        bubbleTimeline.exclude_visibilities.remove("local");
                    }
                });
                dialogBinding.valuePublic.setOnCheckedChangeListener((compoundButton, checked) -> {
                    if (checked) {
                        if (!bubbleTimeline.exclude_visibilities.contains("public")) {
                            bubbleTimeline.exclude_visibilities.add("public");
                        }
                    } else {
                        bubbleTimeline.exclude_visibilities.remove("public");
                    }
                });
                dialogBinding.valueUnlisted.setOnCheckedChangeListener((compoundButton, checked) -> {
                    if (checked) {
                        if (!bubbleTimeline.exclude_visibilities.contains("unlisted")) {
                            bubbleTimeline.exclude_visibilities.add("unlisted");
                        }
                    } else {
                        bubbleTimeline.exclude_visibilities.remove("unlisted");
                    }
                });
                dialogBuilder.setPositiveButton(R.string.validate, (dialog, id) -> {
                    pinned.pinnedTimelines.get(finalOffSetPosition).bubbleTimeline = bubbleTimeline;
                    try {
                        new Pinned(activity).updatePinned(pinned);
                    } catch (DBException e) {
                        e.printStackTrace();
                    }
                });
                AlertDialog alertDialog = dialogBuilder.create();
                alertDialog.show();
            } else if (itemId == R.id.action_reply_visibility) {
                AlertDialog.Builder dialogBuilder;
                AlertDialog alertDialog;
                dialogBuilder = new AlertDialog.Builder(activity, Helper.dialogStyle());
                DialogBubbleReplyVisibilityBinding dialogBinding = DialogBubbleReplyVisibilityBinding.inflate(activity.getLayoutInflater());
                dialogBuilder.setView(dialogBinding.getRoot());
                dialogBuilder.setTitle(R.string.reply_visibility);
                int checkedId = R.id.all;
                if (bubbleTimeline.reply_visibility != null && bubbleTimeline.reply_visibility.equalsIgnoreCase("following")) {
                    checkedId = R.id.following;
                } else if (bubbleTimeline.reply_visibility != null && bubbleTimeline.reply_visibility.equalsIgnoreCase("self")) {
                    checkedId = R.id.self;
                }
                dialogBinding.replyVisibility.check(checkedId);
                dialogBinding.replyVisibility.setOnCheckedChangeListener((radioGroup, checkedElement) -> {
                    if (checkedElement == R.id.all) {
                        bubbleTimeline.reply_visibility = null;
                    } else if (checkedElement == R.id.following) {
                        bubbleTimeline.reply_visibility = "following";
                    } else if (checkedElement == R.id.self) {
                        bubbleTimeline.reply_visibility = "self";
                    }
                });
                dialogBuilder.setPositiveButton(R.string.validate, (dialog, id) -> {
                    pinned.pinnedTimelines.get(finalOffSetPosition).bubbleTimeline = bubbleTimeline;
                    try {
                        new Pinned(activity).updatePinned(pinned);
                    } catch (DBException e) {
                        e.printStackTrace();
                    }
                });
                alertDialog = dialogBuilder.create();
                alertDialog.show();
            }
            return false;
        });
        popup.show();
    }


    /**
     * Manage long clicks on followed instances
     *
Loading