diff --git a/app/src/main/java/ru/vtosters/lite/ui/fragments/dockbar/DockBarAdapter.java b/app/src/main/java/ru/vtosters/lite/ui/fragments/dockbar/DockBarAdapter.java new file mode 100644 index 000000000..1c7b52dd5 --- /dev/null +++ b/app/src/main/java/ru/vtosters/lite/ui/fragments/dockbar/DockBarAdapter.java @@ -0,0 +1,199 @@ +package ru.vtosters.lite.ui.fragments.dockbar; + +import android.content.res.ColorStateList; +import android.graphics.Color; +import android.graphics.Typeface; +import android.support.v7.widget.RecyclerView; +import android.util.Log; +import android.util.TypedValue; +import android.view.Gravity; +import android.view.View; +import android.view.ViewGroup; +import android.widget.ImageView; +import android.widget.LinearLayout; +import android.widget.TextView; + +import com.vtosters.lite.R; + +import java.util.List; + +import ru.vtosters.lite.utils.Helper; +import ru.vtosters.lite.utils.Themes; + +public class DockBarAdapter extends RecyclerView.a + implements IItemTouchHelper { + + public static final int SELECTED_TAB_TYPE = 1; + public static final int DISABLED_TAB_TYPE = 2; + + private final DockBarManager mDockBarManager = DockBarManager.getInstance(); + + @Override + public DockBarEditViewHolder b(ViewGroup parent, int i) { + LinearLayout container = new LinearLayout(parent.getContext()); + container.setLayoutParams(new LinearLayout.LayoutParams(-1, -2)); + + View tabItem = createTabItem(); + container.addView(tabItem, new LinearLayout.LayoutParams(-1, -2)); + + View groupTitle = createGroupTitle(); + container.addView(groupTitle, new LinearLayout.LayoutParams(-1, -2)); + + return new DockBarEditViewHolder(container); + } + + private View createTabItem() { + LinearLayout container = new LinearLayout(Helper.GetContext()); + container.setTag("tab_item_container"); + container.setGravity(Gravity.CENTER_VERTICAL); + container.setOrientation(LinearLayout.HORIZONTAL); + container.setPadding( + Helper.convertDpToPixel(12), + Helper.convertDpToPixel(12), + Helper.convertDpToPixel(12), + Helper.convertDpToPixel(12) + ); + container.setLayoutParams(new LinearLayout.LayoutParams(-1, Helper.convertDpToPixel(48))); + container.setVisibility(View.GONE); + + ImageView icon = new ImageView(Helper.GetContext()); + icon.setTag("icon"); + icon.setImageTintList(ColorStateList.valueOf(Themes.getAccentColor())); + icon.setLayoutParams(new LinearLayout.LayoutParams( + Helper.convertDpToPixel(24), + Helper.convertDpToPixel(24))); + container.addView(icon); + + TextView title = new TextView(Helper.GetContext()); + title.setTag("title"); + title.setTextSize(16.0f); + title.setTypeface(Typeface.DEFAULT_BOLD); + title.setTextColor(Themes.getTextAttr()); + LinearLayout.LayoutParams params = new LinearLayout.LayoutParams(0, -2); + params.weight = 1; + params.leftMargin = Helper.convertDpToPixel(16); + container.addView(title, params); + +// ImageView move = new ImageView(Helper.GetContext()); +// move.setTag("move"); +// move.setImageTintList(ColorStateList.valueOf(textSecondary)); +// move.setLayoutParams(new LinearLayout.LayoutParams( +// Helper.convertDpToPixel(24), +// Helper.convertDpToPixel(24))); +// container.addView(move); + + return container; + } + + private View createGroupTitle() { + TextView title = new TextView(Helper.GetContext()); + title.setTag("group_title"); + title.setTextSize(13.0f); + title.setPadding( + Helper.convertDpToPixel(16), + Helper.convertDpToPixel(13), + Helper.convertDpToPixel(16), + Helper.convertDpToPixel(13) + ); + title.setAllCaps(true); + title.setLayoutParams(new LinearLayout.LayoutParams(-1, -2)); + title.setVisibility(View.GONE); + + title.setTextColor(Themes.getTextAttr()); + + return title; + } + + @Override + public void a(DockBarEditViewHolder holder, int position) { + int viewType = mDockBarManager.getItemType(position); + if (viewType == 1) { + holder.bind(mDockBarManager.getSelectedTab(position)); + } else if (viewType == 2) { + holder.bind(mDockBarManager.getDisabledTab(position)); + } else if (viewType == androidx.recyclerview.widget.RecyclerView.INVALID_TYPE) { + holder.bind(mDockBarManager.getGroupTitle(position)); + } + } + + @Override + public int au_() { + return mDockBarManager.getItemCount(); + } + + @Override + public void onItemDismiss(int index) { + mDockBarManager.move(this, index); + } + + @Override + public boolean onItemMove(int fromPosition, int toPosition) { + int fromViewType = getItemType(fromPosition); + int toViewType = getItemType(toPosition); + + if (fromPosition < toPosition) { + + if (fromViewType != toViewType) { + mDockBarManager.swapAndMigrate(this, fromPosition, toPosition); + } else { + List list = fromViewType == 1 ? mDockBarManager.getSelectedTabs() : mDockBarManager.getDisabledTabs(); + mDockBarManager.swap(this, list, fromViewType, fromPosition, toPosition); + } + + } else if (toPosition != 0) { + + if (fromViewType != toViewType){ + mDockBarManager.swapAndMigrate(this, fromPosition, toPosition); + } else { + List list = fromViewType == 1 ? mDockBarManager.getSelectedTabs() : mDockBarManager.getDisabledTabs(); + mDockBarManager.swap(this, list, fromViewType, fromPosition, toPosition); + } + + } + + return true; + } + + public int getIndexByViewType(int position, int viewType) { + return mDockBarManager.getIndexByViewType(position, viewType); + } + + public int getItemType(int position) { + return mDockBarManager.getItemType(position); + } + + + + static class DockBarEditViewHolder extends RecyclerView.x { + + private LinearLayout mTabContainer; + private ImageView mIcon; + private TextView mTitle; +// private ImageView mMove; + + private TextView mGroupTitle; + + public DockBarEditViewHolder(View itemView) { + super(itemView); + + mTabContainer = itemView.findViewWithTag("tab_item_container"); + mIcon = itemView.findViewWithTag("icon"); + mTitle = itemView.findViewWithTag("title"); +// mMove = itemView.findViewWithTag("move"); + + mGroupTitle = itemView.findViewWithTag("group_title"); + } + + public void bind(DockBarTab tab) { + Log.d("guzno", String.format("Bind data: { Icon: %d, Title: %s }", tab.iconID, Helper.GetContext().getString(tab.titleID))); + mTabContainer.setVisibility(View.VISIBLE); + mIcon.setImageResource(tab.iconID); + mTitle.setText(tab.titleID); + } + + public void bind(String groupTitle) { + mGroupTitle.setVisibility(View.VISIBLE); + mGroupTitle.setText(groupTitle); + } + } +} diff --git a/app/src/main/java/ru/vtosters/lite/ui/fragments/dockbar/DockBarDragItem.java b/app/src/main/java/ru/vtosters/lite/ui/fragments/dockbar/DockBarDragItem.java new file mode 100644 index 000000000..814dab1c0 --- /dev/null +++ b/app/src/main/java/ru/vtosters/lite/ui/fragments/dockbar/DockBarDragItem.java @@ -0,0 +1,14 @@ +package ru.vtosters.lite.ui.fragments.dockbar; + +public class DockBarDragItem { + + public boolean active; + public int index; + public DockBarTab dockBarTab; + + public DockBarDragItem(boolean active, int index, DockBarTab dockBarTab) { + this.active = active; + this.index = index; + this.dockBarTab = dockBarTab; + } +} diff --git a/app/src/main/java/ru/vtosters/lite/ui/fragments/dockbar/DockBarFragment.java b/app/src/main/java/ru/vtosters/lite/ui/fragments/dockbar/DockBarFragment.java new file mode 100644 index 000000000..56dbebb6c --- /dev/null +++ b/app/src/main/java/ru/vtosters/lite/ui/fragments/dockbar/DockBarFragment.java @@ -0,0 +1,56 @@ +package ru.vtosters.lite.ui.fragments.dockbar; + +import android.os.Bundle; +import android.support.v7.widget.LinearLayoutManager; +import android.support.v7.widget.RecyclerView; +import android.support.v7.widget.a.ItemTouchHelper; +import android.util.Log; +import android.view.LayoutInflater; +import android.view.View; +import android.view.ViewGroup; +import android.widget.FrameLayout; +import android.widget.LinearLayout; +import me.grishka.appkit.fragments.ToolbarFragment; + +public class DockBarFragment extends ToolbarFragment { + + private RecyclerView mRecyclerView; + private DockBarAdapter mAdapter; + private ItemTouchHelper mItemTouchHelper; + + @Override + public View d(LayoutInflater layoutInflater, ViewGroup viewGroup, Bundle bundle) { + super.b(bundle); + + LinearLayout container = new LinearLayout(n()); + container.setLayoutParams(new FrameLayout.LayoutParams(-1, -1)); + + mRecyclerView = new RecyclerView(n()); + mRecyclerView.setHasFixedSize(true); + mRecyclerView.setLayoutManager(new LinearLayoutManager(n())); + mAdapter = new DockBarAdapter(); + mRecyclerView.setAdapter(mAdapter); + container.addView(mRecyclerView, new LinearLayout.LayoutParams(-1, -1)); + + mItemTouchHelper = new ItemTouchHelper(new ItemTouchHelperCallback(mAdapter)); + mItemTouchHelper.a(mRecyclerView); + + return container; + } + + @Override + public void a(View arg0, Bundle arg1) { + Log.d("test", "Called onViewCreated method"); + o_(true); + + super.a(arg0, arg1); + + a("Редактор докбара"); + } + + @Override + public void A_() { + super.A_(); + DockBarManager.getInstance().save(); + } +} diff --git a/app/src/main/java/ru/vtosters/lite/ui/fragments/dockbar/DockBarInjector.java b/app/src/main/java/ru/vtosters/lite/ui/fragments/dockbar/DockBarInjector.java new file mode 100644 index 000000000..efafe719f --- /dev/null +++ b/app/src/main/java/ru/vtosters/lite/ui/fragments/dockbar/DockBarInjector.java @@ -0,0 +1,199 @@ +package ru.vtosters.lite.ui.fragments.dockbar; + +import android.content.res.ColorStateList; +import android.graphics.drawable.Drawable; +import android.view.Menu; +import android.view.MenuItem; + +import com.vk.apps.AppsFragment; +import com.vk.core.d.RecoloredDrawable; +import com.vk.core.fragments.FragmentImpl; +import com.vtosters.lite.ui.bottomnavigation.BottomNavigationMenuView; +import com.vtosters.lite.ui.bottomnavigation.BottomNavigationView; + +import org.json.JSONArray; +import org.json.JSONException; +import org.json.JSONObject; + +import java.lang.reflect.Field; +import java.lang.reflect.InvocationTargetException; +import java.lang.reflect.Method; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.LinkedHashMap; +import java.util.List; +import java.util.Map; + +import ru.vtosters.lite.utils.Helper; + +public class DockBarInjector { + private static final DockBarManager sManager = DockBarManager.getInstance(); + + public static Map, Integer> injectMap() { + LinkedHashMap, Integer> map = new LinkedHashMap<>(); + for (DockBarTab tab : sManager.getSelectedTabs()) { + map.put(tab.fragmentClass, tab.id); + } + return map; + } + + public static void inject(BottomNavigationView navigationView) { + Menu menu = navigationView.getMenu(); + menu.clear(); + try { + Field field = BottomNavigationMenuView.class.getDeclaredField("h"); + field.setAccessible(true); + + Object synchronizedPool = field.get(null); + + Class synchronisedPoolCls = Class.forName("android.support.v4.f.Pools$a"); + + Method acquire = synchronisedPoolCls.getDeclaredMethod("a"); + + if (synchronizedPool != null) { + do { + } while (acquire.invoke(synchronizedPool) != null); + } + + } catch (NoSuchFieldException | IllegalAccessException | ClassNotFoundException | NoSuchMethodException | InvocationTargetException e) { + e.printStackTrace(); + } + + for (DockBarTab tab : sManager.getSelectedTabs()) { + MenuItem add = menu.add(0, tab.id, 0, tab.titleID); + Drawable drawable = Helper.GetContext().getResources().getDrawable(tab.iconID); + ColorStateList colorStateList = Helper.GetContext().getResources().getColorStateList(com.vtosters.lite.R.color.bottom_navigation_item); + add.setIcon((Drawable) new RecoloredDrawable(drawable, colorStateList)); + add.setShowAsAction(1); + add.setCheckable(true); + } + } + + public static int injectId(String tag) { + for (DockBarTab tab : sManager.getSelectedTabs()) { + if (tag.equals(tab.tag)) + return tab.id; + } + return 0; + } + + public static void injectMenuFragment(Menu menu) { + List menuItems = new ArrayList<>(); + for (int i = 0; i < menu.size(); i++) { + menuItems.add(menu.getItem(i)); + } + menu.clear(); + + for (DockBarTab tab : sManager.getSelectedTabs()) { + if (tab.id != com.vtosters.lite.R.id.tab_menu) { + int itemId = tab.id; + if (tab.id == com.vtosters.lite.R.id.tab_news) { + itemId = com.vtosters.lite.R.id.menu_newsfeed; + } else if (tab.id == com.vtosters.lite.R.id.tab_discover) { + itemId = com.vtosters.lite.R.id.menu_search; + } else if (tab.id == com.vtosters.lite.R.id.tab_feedback) { + itemId = com.vtosters.lite.R.id.menu_feedback; + } else if (tab.id == com.vtosters.lite.R.id.tab_messages) { + itemId = com.vtosters.lite.R.id.menu_messages; + } + + MenuItem add = menu.add(0, itemId, 0, tab.titleID); + add.setIcon(tab.iconID); + add.setVisible(true); + } + } + + for (MenuItem menuItem : menuItems) { + MenuItem item = menu.add(menuItem.getGroupId(), menuItem.getItemId(), menuItem.getOrder(), menuItem.getTitle()); + item.setIcon(menuItem.getIcon()); + } + menuItems.clear(); + + for (int i = 0; i < menu.size(); i++) { + MenuItem menuItem = menu.getItem(i); + for (DockBarTab tab : sManager.getSelectedTabs()) { + int itemId = menuItem.getItemId(); + if (itemId == com.vtosters.lite.R.id.menu_newsfeed) { + itemId = com.vtosters.lite.R.id.tab_news; + } else if (itemId == com.vtosters.lite.R.id.menu_search) { + itemId = com.vtosters.lite.R.id.tab_discover; + } else if (itemId == com.vtosters.lite.R.id.menu_feedback) { + itemId = com.vtosters.lite.R.id.tab_feedback; + } else if (itemId == com.vtosters.lite.R.id.menu_messages) { + itemId = com.vtosters.lite.R.id.tab_messages; + } + if (itemId == tab.id && tab.id != com.vtosters.lite.R.id.menu_vk_pay) { + menuItems.add(menuItem); + break; + } + } + } + + for (MenuItem menuItem : menuItems) { + menu.removeItem(menuItem.getItemId()); + } + } + + public static JSONArray injectMenuJSON(JSONArray arr) { + List arrayList = new ArrayList(Arrays.asList( + "news", + "messages", + "feedback", + "discover" + )); + for (DockBarTab tab : sManager.getSelectedTabs()) { + if (tab.id == com.vtosters.lite.R.id.tab_discover) { + arrayList.remove("discover"); + } else if (tab.id == com.vtosters.lite.R.id.tab_feedback) { + arrayList.remove("feedback"); + } else if (tab.id == com.vtosters.lite.R.id.tab_messages) { + arrayList.remove("messages"); + } else if (tab.id == com.vtosters.lite.R.id.tab_news) { + arrayList.remove("news"); + } + } + try { + JSONArray jSONArray = new JSONArray(); + for (int i = 0; i < arrayList.size(); i++) { + jSONArray.put(new JSONObject().put("name", arrayList.get(i))); + } + for (int i2 = 0; i2 < arr.length(); i2++) { + jSONArray.put(arr.getJSONObject(i2)); + } + return jSONArray; + } catch (JSONException e) { + e.printStackTrace(); + return arr; + } + } + + public static int getItemCount() { + return sManager.getSelectedTabs().size(); + } + + public static boolean isDockOpenAllowed(FragmentImpl fragment) { + return isDockOpenAllowed(fragment.getClass()); + } + + public static boolean isDockOpenAllowed(Class cls) { + for (DockBarTab tab : sManager.getSelectedTabs()) + if (tab.fragmentClass == cls) + return true; + for (DockBarTab tab : sManager.getDisabledTabs()) + if (tab.fragmentClass == cls) + return true; + return false; + } + + public static Class interceptClick(int id) { + for (DockBarTab tab : sManager.getSelectedTabs()) { + if (id == tab.id) + return tab.fragmentClass; + } + for (DockBarTab tab : sManager.getDisabledTabs()) { + if (id == tab.id) + return tab.fragmentClass; + } + return AppsFragment.class; + } +} diff --git a/app/src/main/java/ru/vtosters/lite/ui/fragments/dockbar/DockBarManager.java b/app/src/main/java/ru/vtosters/lite/ui/fragments/dockbar/DockBarManager.java new file mode 100644 index 000000000..2602c4a88 --- /dev/null +++ b/app/src/main/java/ru/vtosters/lite/ui/fragments/dockbar/DockBarManager.java @@ -0,0 +1,307 @@ +package ru.vtosters.lite.ui.fragments.dockbar; + +import android.util.Log; + +import androidx.recyclerview.widget.RecyclerView; + +import com.vk.apps.AppsFragment; +import com.vk.discover.DiscoverFeedFragment; +import com.vk.discover.DiscoverFragment; +import com.vk.fave.fragments.FaveTabFragment; +import com.vk.menu.MenuFragment; +import com.vk.newsfeed.Feed2049; +import com.vk.newsfeed.NewsfeedFragment; + +import org.json.JSONArray; +import org.json.JSONException; +import org.json.JSONObject; + +import java.io.ByteArrayOutputStream; +import java.io.File; +import java.io.FileInputStream; +import java.io.FileOutputStream; +import java.io.IOException; +import java.io.InputStream; +import java.nio.charset.StandardCharsets; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.Collections; +import java.util.List; +import java.util.stream.Collectors; + +import com.vk.notifications.NotificationsFragment; +import com.vtosters.lite.R; +import com.vtosters.lite.fragments.GamesFragment; +import com.vtosters.lite.fragments.PhotosFragment; +import com.vtosters.lite.fragments.d.DocumentsViewFragment; +import com.vtosters.lite.fragments.f.FriendsFragment; +import com.vtosters.lite.fragments.h.GroupsFragment; +import com.vtosters.lite.fragments.lives.LivesPostListFragment; +import com.vtosters.lite.fragments.m.VideosFragment; +import com.vtosters.lite.fragments.messages.dialogs.DialogsFragment; +import com.vtosters.lite.fragments.money.MoneyTransfersFragment; + +import ru.vtosters.lite.ui.fragments.MusicFragment; +import ru.vtosters.lite.utils.Helper; +import ru.vtosters.lite.utils.Prefs; + +public class DockBarManager { + static final int MIN_SELECTED_TABS_LIMIT = 3; + static final int MAX_SELECTED_TABS_LIMIT = 8; + + private static DockBarManager sInstance = new DockBarManager(); + + public static DockBarManager getInstance() { + if (sInstance == null) + sInstance = new DockBarManager(); + return sInstance; + } + + private List mSelectedTabs = new ArrayList<>(); + private List mDisabledTabs = new ArrayList<>(); + private List mGroups = Arrays.asList( + "Выбранные элементы докбара", + "Невыбранные элементы" + ); + + public DockBarManager() { + load(); + } + + private void load() { + File dockbar = new File(Helper.GetContext().getFilesDir(), "dockbar.json"); + + if (!dockbar.exists()) { + mSelectedTabs.add(new DockBarTab("tab_news", R.drawable.ic_menu_newsfeed_outline_28, R.string.newsfeed, R.id.tab_news, Prefs.isUseAlternativeFragments() ? Feed2049.b.c() : NewsfeedFragment.class)); + mSelectedTabs.add(new DockBarTab("tab_discover", R.drawable.ic_menu_search_outline_28, R.string.search, R.id.tab_discover, Prefs.isUseAlternativeFragments() ? DiscoverFragment.class : DiscoverFeedFragment.class)); + mSelectedTabs.add(new DockBarTab("tab_messages", R.drawable.ic_message_28_outline, R.string.messages, R.id.tab_messages, DialogsFragment.class)); + mSelectedTabs.add(new DockBarTab("tab_feedback", R.drawable.ic_menu_notification_outline_28, R.string.feedback, R.id.tab_feedback, NotificationsFragment.class)); + mSelectedTabs.add(new DockBarTab("tab_menu",R.drawable.ic_menu_more_outline_28, R.string.menu, R.id.tab_menu, MenuFragment.class)); + + mDisabledTabs.add(new DockBarTab("tab_friends", R.drawable.ic_user_24, R.string.friends, R.id.menu_friends, FriendsFragment.class)); + mDisabledTabs.add(new DockBarTab("tab_groups", R.drawable.ic_users_24, R.string.groups, R.id.menu_groups, GroupsFragment.class)); + mDisabledTabs.add(new DockBarTab("tab_photos", R.drawable.ic_camera_24, R.string.photos, R.id.menu_photos, PhotosFragment.class)); + mDisabledTabs.add(new DockBarTab("tab_audios", R.drawable.ic_music_24, R.string.music, R.id.menu_audios, MusicFragment.class)); + mDisabledTabs.add(new DockBarTab("tab_videos", R.drawable.ic_video_24, R.string.videos, R.id.menu_videos, VideosFragment.class)); + mDisabledTabs.add(new DockBarTab("tab_lives", R.drawable.ic_live_filter_24dp, R.string.sett_live, R.id.menu_lives, LivesPostListFragment.class)); + mDisabledTabs.add(new DockBarTab("tab_games", R.drawable.ic_games_24, R.string.games, R.id.menu_games, GamesFragment.class)); + mDisabledTabs.add(new DockBarTab("tab_fave", R.drawable.ic_favorite_24, R.string.fave_title, R.id.menu_fave, FaveTabFragment.class)); + mDisabledTabs.add(new DockBarTab("tab_documents", R.drawable.ic_document_24, R.string.docs, R.id.menu_documents, DocumentsViewFragment.class)); + mDisabledTabs.add(new DockBarTab("tab_payments", R.drawable.ic_money_transfer_24, R.string.money_transfer_money_transfers, R.id.menu_payments, MoneyTransfersFragment.class)); + mDisabledTabs.add(new DockBarTab("tab_vk_apps", R.drawable.ic_services_24, R.string.menu_apps, R.id.menu_vk_apps, AppsFragment.class)); + } else { + try { + JSONObject json = new JSONObject(readFully(new FileInputStream(dockbar))); + + JSONArray selected = json.getJSONArray("selected"); + for (int i = 0; i < selected.length(); i++) { + JSONObject item = selected.getJSONObject(i); + DockBarTab tab = new DockBarTab( + item.getString("tag"), + item.getInt("iconID"), + item.getInt("titleID"), + item.getInt("id"), + Class.forName(item.getString("fragmentClass")) + ); + if (Prefs.isUseAlternativeFragments()) { + if (tab.fragmentClass == NewsfeedFragment.class) { + tab.fragmentClass = Feed2049.b.c(); + } else if (tab.fragmentClass == DiscoverFeedFragment.class) { + tab.fragmentClass = DiscoverFragment.class; + } + } else { + if (tab.fragmentClass == Feed2049.b.c()) { + tab.fragmentClass = NewsfeedFragment.class; + } else if (tab.fragmentClass == DiscoverFragment.class) { + tab.fragmentClass = DiscoverFeedFragment.class; + } + } + mSelectedTabs.add(tab); + } + + JSONArray disabled = json.getJSONArray("disabled"); + for (int i = 0; i < disabled.length(); i++) { + JSONObject item = disabled.getJSONObject(i); + DockBarTab tab = new DockBarTab( + item.getString("tag"), + item.getInt("iconID"), + item.getInt("titleID"), + item.getInt("id"), + Class.forName(item.getString("fragmentClass")) + ); + if (Prefs.isUseAlternativeFragments()) { + if (tab.fragmentClass == NewsfeedFragment.class) { + tab.fragmentClass = Feed2049.b.c(); + } else if (tab.fragmentClass == DiscoverFeedFragment.class) { + tab.fragmentClass = DiscoverFragment.class; + } + } else { + if (tab.fragmentClass == Feed2049.b.c()) { + tab.fragmentClass = NewsfeedFragment.class; + } else if (tab.fragmentClass == DiscoverFragment.class) { + tab.fragmentClass = DiscoverFeedFragment.class; + } + } + mDisabledTabs.add(tab); + } + + } catch (JSONException | IOException | ClassNotFoundException e) { + e.printStackTrace(); + } + } + } + + private static String readFully(InputStream is) throws IOException { + ByteArrayOutputStream bos = new ByteArrayOutputStream(); + byte[] buffer = new byte[2048]; + int len; + while ((len = is.read(buffer)) > 0) { + bos.write(buffer, 0, len); + } + return bos.toString(); + } + + public void save() { + try { + File cache = new File(Helper.GetContext().getFilesDir(), "dockbar.json"); + + JSONArray selected = new JSONArray(); + for (DockBarTab tab : mSelectedTabs) { + + JSONObject item = new JSONObject() + .put("tag", tab.tag) + .put("iconID", tab.iconID) + .put("titleID", tab.titleID) + .put("id", tab.id) + .put("fragmentClass", tab.fragmentClass.getName()); + selected.put(item); + } + + JSONArray disabled = new JSONArray(); + for (DockBarTab tab : mDisabledTabs) { + JSONObject item = new JSONObject() + .put("tag", tab.tag) + .put("iconID", tab.iconID) + .put("titleID", tab.titleID) + .put("id", tab.id) + .put("fragmentClass", tab.fragmentClass.getName()); + disabled.put(item); + } + + JSONObject json = new JSONObject(); + json.put("selected", selected).put("disabled", disabled); + + FileOutputStream fos = new FileOutputStream(cache); + fos.write(json.toString().getBytes(StandardCharsets.UTF_8)); + } catch (JSONException | IOException e) { + e.printStackTrace(); + } + } + + public void swap(DockBarAdapter adapter, List list, int itemType, int fromPosition, int toPosition) { + int curr = adapter.getIndexByViewType(fromPosition, itemType); + int target = adapter.getIndexByViewType(toPosition, itemType); + if (fromPosition < toPosition) { + for (int i = curr; i < target; i++) { + Collections.swap(list, i, i + 1); + } + } else { + for (int i = curr; i > target; i--) { + Collections.swap(list, i, i - 1); + } + } + adapter.b(fromPosition, toPosition);// notifyItemMoved + } + + public void swapAndMigrate(DockBarAdapter adapter, int fromPosition, int toPosition) { + int curr = adapter.getIndexByViewType(fromPosition, adapter.getItemType(fromPosition)); + int target = adapter.getIndexByViewType(toPosition, adapter.getItemType(toPosition)); + if (fromPosition < toPosition) { + + if (mSelectedTabs.size() <= MIN_SELECTED_TABS_LIMIT || mSelectedTabs.get(curr).tag.equals("tab_menu")) return; + + DockBarTab tab = mSelectedTabs.get(curr); + mSelectedTabs.remove(tab); + mDisabledTabs.add(tab); + + for (int i = mDisabledTabs.size() - 1; i > target; i--) { + Collections.swap(mDisabledTabs, i, i - 1); + } + + for (int i = 0; i < target; i++) { + Collections.swap(mDisabledTabs, i, i + 1); + } + } else { + + if (mSelectedTabs.size() >= MAX_SELECTED_TABS_LIMIT) return; + + DockBarTab tab = mDisabledTabs.get(curr); + mDisabledTabs.remove(tab); + mSelectedTabs.add(tab); + } + adapter.b(fromPosition, toPosition);// notifyItemMoved + } + + public void move(DockBarAdapter adapter, int index) { + if (getItemType(index) == 1) { + DockBarTab item = mSelectedTabs.get(getIndexByViewType(index, 1)); + + mSelectedTabs.remove(item); + + mDisabledTabs.add(item); + + for (int i = mDisabledTabs.size() - 1; i > 0; i--) { + Collections.swap(mDisabledTabs, i, i - 1); + } + + adapter.e_(index); // notifyItemRemoved + adapter.d_(getItemCount() - mDisabledTabs.size()); // notifyItemInserted + } + } + + public int getItemCount() { + return mSelectedTabs.size() + mDisabledTabs.size() + mGroups.size(); + } + + public int getIndexByViewType(int position, int viewType) { + if (viewType == DockBarAdapter.SELECTED_TAB_TYPE) { + return position - 1; + } else if (viewType == DockBarAdapter.DISABLED_TAB_TYPE) { + return position - mSelectedTabs.size() - mGroups.size(); + } else if (viewType == RecyclerView.INVALID_TYPE){ + return position != 0 ? 1 : 0; + } else { + return -1; + } + } + + public int getItemType(int position) { + if (position == 0 || position == mSelectedTabs.size() + 1) { + return RecyclerView.INVALID_TYPE; + } else if (position - 1 < mSelectedTabs.size()) { + return DockBarAdapter.SELECTED_TAB_TYPE; + } else { + return DockBarAdapter.DISABLED_TAB_TYPE; + } + } + + public DockBarTab getSelectedTab(int pos) { + return mSelectedTabs.get(getIndexByViewType(pos, 1)); + } + + public DockBarTab getDisabledTab(int pos) { + return mDisabledTabs.get(getIndexByViewType(pos, 2)); + } + + public String getGroupTitle(int pos) { + return mGroups.get(getIndexByViewType(pos, -1)); + } + + public List getSelectedTabs() { + return mSelectedTabs; + } + + public List getDisabledTabs() { + return mDisabledTabs; + } +} diff --git a/app/src/main/java/ru/vtosters/lite/ui/fragments/dockbar/DockBarTab.java b/app/src/main/java/ru/vtosters/lite/ui/fragments/dockbar/DockBarTab.java new file mode 100644 index 000000000..512a5f9a4 --- /dev/null +++ b/app/src/main/java/ru/vtosters/lite/ui/fragments/dockbar/DockBarTab.java @@ -0,0 +1,20 @@ +package ru.vtosters.lite.ui.fragments.dockbar; + +import com.vk.core.fragments.FragmentImpl; + +public class DockBarTab { + + public String tag; + public int iconID; + public int titleID; + public int id; + public Class fragmentClass; + + public DockBarTab(String tag, int iconID, int titleID, int resID, Class fragmentClass) { + this.tag = tag; + this.iconID = iconID; + this.titleID = titleID; + this.id = resID; + this.fragmentClass = (Class) fragmentClass; + } +} diff --git a/app/src/main/java/ru/vtosters/lite/ui/fragments/dockbar/IItemTouchHelper.java b/app/src/main/java/ru/vtosters/lite/ui/fragments/dockbar/IItemTouchHelper.java new file mode 100644 index 000000000..285096134 --- /dev/null +++ b/app/src/main/java/ru/vtosters/lite/ui/fragments/dockbar/IItemTouchHelper.java @@ -0,0 +1,8 @@ +package ru.vtosters.lite.ui.fragments.dockbar; + +public interface IItemTouchHelper { + + void onItemDismiss(int index); + + boolean onItemMove(int fromPosition, int toPosition); +} diff --git a/app/src/main/java/ru/vtosters/lite/ui/fragments/dockbar/ItemTouchHelperCallback.java b/app/src/main/java/ru/vtosters/lite/ui/fragments/dockbar/ItemTouchHelperCallback.java new file mode 100644 index 000000000..245f29c65 --- /dev/null +++ b/app/src/main/java/ru/vtosters/lite/ui/fragments/dockbar/ItemTouchHelperCallback.java @@ -0,0 +1,45 @@ +package ru.vtosters.lite.ui.fragments.dockbar; + +import static androidx.recyclerview.widget.ItemTouchHelper.Callback.makeMovementFlags; + +import android.support.v7.widget.RecyclerView; +import android.support.v7.widget.a.ItemTouchHelper; + +public class ItemTouchHelperCallback extends ItemTouchHelper.a { + + private DockBarAdapter mAdapter; + + public ItemTouchHelperCallback(DockBarAdapter mAdapter) { + this.mAdapter = mAdapter; + } + + @Override // isItemViewSwipeEnabled + public boolean a() { + return true; + } + + @Override // isLongPressDragEnabled + public boolean b() { + return true; + } + + @Override + public int a(RecyclerView recyclerView, RecyclerView.x viewHolder) { + int pos = mAdapter.getItemType(viewHolder.d()); + int dragFlags = pos != androidx.recyclerview.widget.RecyclerView.INVALID_TYPE ? androidx.recyclerview.widget.ItemTouchHelper.UP | androidx.recyclerview.widget.ItemTouchHelper.DOWN : 0; + int swipeFlags = pos == 1 ? androidx.recyclerview.widget.ItemTouchHelper.START | androidx.recyclerview.widget.ItemTouchHelper.END : 0; + return makeMovementFlags(dragFlags, swipeFlags); + } + + @Override + public void a(RecyclerView.x viewHolder, int direction) { + mAdapter.onItemDismiss(viewHolder.d()); + } + + @Override + public boolean b(RecyclerView recyclerView, RecyclerView.x viewHolder, RecyclerView.x target) { + if (mAdapter.getItemType(viewHolder.d()) == androidx.recyclerview.widget.RecyclerView.INVALID_TYPE) + return false; + return mAdapter.onItemMove(viewHolder.d(), target.d()); + } +} diff --git a/app/src/main/java/ru/vtosters/lite/utils/Prefs.java b/app/src/main/java/ru/vtosters/lite/utils/Prefs.java index 4b100b161..ee6e2fc8d 100644 --- a/app/src/main/java/ru/vtosters/lite/utils/Prefs.java +++ b/app/src/main/java/ru/vtosters/lite/utils/Prefs.java @@ -56,6 +56,7 @@ import java.util.Locale; import java.util.Scanner; import kotlin.jvm.internal.Intrinsics; +import ru.vtosters.lite.ui.fragments.dockbar.DockBarManager; public class Prefs { public static String VERSIONNAME = "2.0 DEV"; @@ -747,8 +748,13 @@ public class Prefs { }); } + public static boolean isUseAlternativeFragments() { + return true; + } + public static Class getStartFragment() { - String string = ru.vtosters.lite.utils.Helper.GetPreferences().getString("start_value", ""); + return DockBarManager.getInstance().getSelectedTabs().get(0).fragmentClass; + /*String string = ru.vtosters.lite.utils.Helper.GetPreferences().getString("start_value", ""); if (string.equals("newsfeed")) { return Feed2049.b.c(); } @@ -803,7 +809,7 @@ public class Prefs { if (string.equals("docs")) { return DocumentsViewFragment.class; } - return string.equals("brtd") ? BirthdaysFragment.class : Feed2049.b.c(); + return string.equals("brtd") ? BirthdaysFragment.class : Feed2049.b.c();*/ } public static Context BaseContextLocale(Context context) { diff --git a/smali/AndroidManifest.xml b/smali/AndroidManifest.xml index dcddc3417..607ce9e18 100644 --- a/smali/AndroidManifest.xml +++ b/smali/AndroidManifest.xml @@ -66,7 +66,7 @@ - + diff --git a/smali/smali/com/vtosters/lite/ui/bottomnavigation/BottomNavigationMenu.smali b/smali/smali/com/vtosters/lite/ui/bottomnavigation/BottomNavigationMenu.smali index 089b6534b..c8bc21161 100644 --- a/smali/smali/com/vtosters/lite/ui/bottomnavigation/BottomNavigationMenu.smali +++ b/smali/smali/com/vtosters/lite/ui/bottomnavigation/BottomNavigationMenu.smali @@ -25,7 +25,11 @@ add-int/lit8 v0, v0, 0x1 - const/4 v1, 0x5 + invoke-static {}, Lru/vtosters/lite/ui/fragments/dockbar/DockBarInjector;->getItemCount()I + + move-result v1 + + #const/4 v1, 0x5 if-le v0, v1, :cond_0 diff --git a/smali/smali_classes2/com/vk/dto/menu/MenuResponse$b.smali b/smali/smali_classes2/com/vk/dto/menu/MenuResponse$b.smali index 91b3e8f10..6936c4860 100644 --- a/smali/smali_classes2/com/vk/dto/menu/MenuResponse$b.smali +++ b/smali/smali_classes2/com/vk/dto/menu/MenuResponse$b.smali @@ -55,6 +55,10 @@ if-eqz v0, :cond_1 + invoke-static {v0}, Lru/vtosters/lite/ui/fragments/dockbar/DockBarInjector;->injectMenuJSON(Lorg/json/JSONArray;)Lorg/json/JSONArray; + + move-result-object v0 + .line 38 new-instance v3, Ljava/util/ArrayList; diff --git a/smali/smali_classes2/com/vtosters/lite/fragments/SettingsListFragment$b.smali b/smali/smali_classes2/com/vtosters/lite/fragments/SettingsListFragment$b.smali index cd3f5131d..3cf9c3285 100644 --- a/smali/smali_classes2/com/vtosters/lite/fragments/SettingsListFragment$b.smali +++ b/smali/smali_classes2/com/vtosters/lite/fragments/SettingsListFragment$b.smali @@ -837,6 +837,32 @@ new-instance v5, Lcom/vtosters/lite/fragments/SettingsListFragment$a; + const v6, 0x7f0808cb + + iget-object v7, p0, Lcom/vtosters/lite/fragments/SettingsListFragment$b;->a:Lcom/vtosters/lite/fragments/SettingsListFragment; + + invoke-static {v7}, Lcom/vtosters/lite/fragments/SettingsListFragment;->a(Lcom/vtosters/lite/fragments/SettingsListFragment;)I + + move-result v7 + + const v8, 0x7f110fea + + invoke-static {v8}, Ljava/lang/Integer;->valueOf(I)Ljava/lang/Integer; + + move-result-object v8 + + const-class v9, Lru/vtosters/lite/ui/fragments/dockbar/DockBarFragment; + + invoke-direct {v5, v6, v7, v8, v9}, Lcom/vtosters/lite/fragments/SettingsListFragment$a;->(IILjava/lang/Object;Ljava/lang/Class;)V + + invoke-static {v4, v5}, Lcom/vtosters/lite/ui/holder/RecyclerSectionAdapter$a;->a(ILjava/lang/Object;)Lcom/vtosters/lite/ui/holder/RecyclerSectionAdapter$a; + + move-result-object v5 + + invoke-virtual {v0, v5}, Ljava/util/ArrayList;->add(Ljava/lang/Object;)Z + + new-instance v5, Lcom/vtosters/lite/fragments/SettingsListFragment$a; + const v6, 0x7f08067b iget-object v7, p0, Lcom/vtosters/lite/fragments/SettingsListFragment$b;->a:Lcom/vtosters/lite/fragments/SettingsListFragment; diff --git a/smali/smali_classes4/com/vk/menu/MenuCache.smali b/smali/smali_classes4/com/vk/menu/MenuCache.smali index 1894524d1..b376a2241 100644 --- a/smali/smali_classes4/com/vk/menu/MenuCache.smali +++ b/smali/smali_classes4/com/vk/menu/MenuCache.smali @@ -288,6 +288,15 @@ .method public final a(Ljava/lang/String;)I .locals 1 + invoke-static {p1}, Lru/vtosters/lite/ui/fragments/dockbar/DockBarInjector;->injectId(Ljava/lang/String;)I + + move-result v0 + + if-eqz v0, :cond_exterminatus + + return v0 + + :cond_exterminatus const-string v0, "key" invoke-static {p1, v0}, Lkotlin/jvm/internal/Intrinsics;->b(Ljava/lang/Object;Ljava/lang/String;)V diff --git a/smali/smali_classes4/com/vk/menu/MenuFragment.smali b/smali/smali_classes4/com/vk/menu/MenuFragment.smali index 79a18105f..c9aa05edd 100644 --- a/smali/smali_classes4/com/vk/menu/MenuFragment.smali +++ b/smali/smali_classes4/com/vk/menu/MenuFragment.smali @@ -1281,6 +1281,8 @@ invoke-virtual {v1, v5, v6}, Landroid/view/MenuInflater;->inflate(ILandroid/view/Menu;)V + invoke-static {v6}, Lru/vtosters/lite/ui/fragments/dockbar/DockBarInjector;->injectMenuFragment(Landroid/view/Menu;)V + .line 145 invoke-direct {p0, p1}, Lcom/vk/menu/MenuFragment;->a(Landroid/support/v7/view/menu/MenuBuilder;)Ljava/util/List; diff --git a/smali/smali_classes4/com/vk/navigation/NavigationDelegateBottom.smali b/smali/smali_classes4/com/vk/navigation/NavigationDelegateBottom.smali index a36e66b24..212881293 100644 --- a/smali/smali_classes4/com/vk/navigation/NavigationDelegateBottom.smali +++ b/smali/smali_classes4/com/vk/navigation/NavigationDelegateBottom.smali @@ -236,6 +236,10 @@ move-result-object v0 + invoke-static {}, Lru/vtosters/lite/ui/fragments/dockbar/DockBarInjector;->injectMap()Ljava/util/Map; + + move-result-object v0 + sput-object v0, Lcom/vk/navigation/NavigationDelegateBottom;->z:Ljava/util/Map; return-void @@ -520,6 +524,8 @@ iput-object v2, p0, Lcom/vk/navigation/NavigationDelegateBottom;->f:Lcom/vtosters/lite/ui/bottomnavigation/BottomNavigationView; + invoke-static {v2}, Lru/vtosters/lite/ui/fragments/dockbar/DockBarInjector;->inject(Lcom/vtosters/lite/ui/bottomnavigation/BottomNavigationView;)V + .line 439 invoke-virtual {p0}, Lcom/vk/navigation/NavigationDelegateBottom;->m()Landroid/app/Activity; @@ -845,14 +851,24 @@ .line 520 :catch_0 - sget-object v0, Lcom/vk/analytics/eventtracking/VkTracker;->b:Lcom/vk/analytics/eventtracking/VkTracker; + #sget-object v0, Lcom/vk/analytics/eventtracking/VkTracker;->b:Lcom/vk/analytics/eventtracking/VkTracker; - const-string v2, "ERROR.IM.IPC_REDIRECT_FAILED" + #const-string v2, "ERROR.IM.IPC_REDIRECT_FAILED" - invoke-virtual {v0, v2}, Lcom/vk/analytics/eventtracking/VkTracker;->a(Ljava/lang/String;)V + #invoke-virtual {v0, v2}, Lcom/vk/analytics/eventtracking/VkTracker;->a(Ljava/lang/String;)V .line 522 :cond_0 + invoke-static {p1}, Lru/vtosters/lite/ui/fragments/dockbar/DockBarInjector;->interceptClick(I)Ljava/lang/Class; + + move-result-object p1 + + const/4 v2, 0x0 + + const/4 v0, 0x0 + + goto :goto_0 + invoke-static {p1}, Ljava/lang/Integer;->valueOf(I)Ljava/lang/Integer; move-result-object v0 @@ -1413,6 +1429,12 @@ .method private final d(Lcom/vk/core/fragments/FragmentImpl;)Z .locals 1 + invoke-static {p1}, Lru/vtosters/lite/ui/fragments/dockbar/DockBarInjector;->isDockOpenAllowed(Lcom/vk/core/fragments/FragmentImpl;)Z + + move-result v0 + + return v0 + .line 686 sget-object v0, Lcom/vk/navigation/NavigationDelegateBottom;->z:Ljava/util/Map; @@ -2646,6 +2668,21 @@ .method public a(Lcom/vk/core/fragments/FragmentImpl;)Z .locals 1 + invoke-static {p1}, Lru/vtosters/lite/ui/fragments/dockbar/DockBarInjector;->isDockOpenAllowed(Lcom/vk/core/fragments/FragmentImpl;)Z + + move-result p1 + + if-nez p1, :cond_0 + + const/4 p1, 0x1 + + return p1 + + :cond_0 + const/4 p1, 0x0 + + return p1 + const-string v0, "fragment" invoke-static {p1, v0}, Lkotlin/jvm/internal/Intrinsics;->b(Ljava/lang/Object;Ljava/lang/String;)V diff --git a/smali/smali_classes4/com/vtosters/lite/ui/bottomnavigation/BottomNavigationMenuView.smali b/smali/smali_classes4/com/vtosters/lite/ui/bottomnavigation/BottomNavigationMenuView.smali index 08a885187..c81a41e1c 100644 --- a/smali/smali_classes4/com/vtosters/lite/ui/bottomnavigation/BottomNavigationMenuView.smali +++ b/smali/smali_classes4/com/vtosters/lite/ui/bottomnavigation/BottomNavigationMenuView.smali @@ -61,7 +61,9 @@ .line 32 new-instance v0, Landroid/support/v4/f/Pools$c; - const/4 v1, 0x5 + invoke-static {}, Lru/vtosters/lite/ui/fragments/dockbar/DockBarInjector;->getItemCount()I + + move-result v1 invoke-direct {v0, v1}, Landroid/support/v4/f/Pools$c;->(I)V @@ -186,7 +188,9 @@ iput-object p1, p0, Lcom/vtosters/lite/ui/bottomnavigation/BottomNavigationMenuView;->f:Landroid/view/View$OnClickListener; - const/4 p1, 0x5 + invoke-static {}, Lru/vtosters/lite/ui/fragments/dockbar/DockBarInjector;->getItemCount()I + + move-result v1 .line 73 new-array p1, p1, [I diff --git a/smali/smali_classes4/com/vtosters/lite/ui/bottomnavigation/BottomNavigationView.smali b/smali/smali_classes4/com/vtosters/lite/ui/bottomnavigation/BottomNavigationView.smali index 6bba0ffd9..6a737d0f2 100644 --- a/smali/smali_classes4/com/vtosters/lite/ui/bottomnavigation/BottomNavigationView.smali +++ b/smali/smali_classes4/com/vtosters/lite/ui/bottomnavigation/BottomNavigationView.smali @@ -772,6 +772,12 @@ .method public getMaxItemCount()I .locals 1 + invoke-static {}, Lru/vtosters/lite/ui/fragments/dockbar/DockBarInjector;->getItemCount()I + + move-result v0 + + return v0 + const/4 v0, 0x5 return v0 diff --git a/smali/smali_classes5/android/support/design/widget/BottomNavigationView.smali b/smali/smali_classes5/android/support/design/widget/BottomNavigationView.smali index a11de3d5d..76f7599ea 100644 --- a/smali/smali_classes5/android/support/design/widget/BottomNavigationView.smali +++ b/smali/smali_classes5/android/support/design/widget/BottomNavigationView.smali @@ -132,6 +132,12 @@ .method public getMaxItemCount()I .locals 1 + invoke-static {}, Lru/vtosters/lite/ui/fragments/dockbar/DockBarInjector;->getItemCount()I + + move-result v0 + + return v0 + const/4 v0, 0x5 return v0