summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--app/src/main/java/app/fedilab/android/BaseMainActivity.java3
-rw-r--r--app/src/main/java/app/fedilab/android/client/entities/BottomMenu.java334
-rw-r--r--app/src/main/java/app/fedilab/android/sqlite/Sqlite.java17
-rw-r--r--app/src/main/res/layout/activity_reorder_tabs.xml6
4 files changed, 357 insertions, 3 deletions
diff --git a/app/src/main/java/app/fedilab/android/BaseMainActivity.java b/app/src/main/java/app/fedilab/android/BaseMainActivity.java
index fc6825c3f..eae375ddd 100644
--- a/app/src/main/java/app/fedilab/android/BaseMainActivity.java
+++ b/app/src/main/java/app/fedilab/android/BaseMainActivity.java
@@ -96,6 +96,7 @@ import app.fedilab.android.activities.SearchResultTabActivity;
import app.fedilab.android.activities.SettingsActivity;
import app.fedilab.android.broadcastreceiver.NetworkStateReceiver;
import app.fedilab.android.client.entities.Account;
+import app.fedilab.android.client.entities.BottomMenu;
import app.fedilab.android.client.entities.Pinned;
import app.fedilab.android.client.entities.app.PinnedTimeline;
import app.fedilab.android.client.mastodon.entities.Filter;
@@ -250,7 +251,7 @@ public abstract class BaseMainActivity extends BaseActivity implements NetworkSt
binding.tabLayout.setTabIconTint(ThemeHelper.getColorStateList(BaseMainActivity.this));
binding.compose.setOnClickListener(v -> startActivity(new Intent(this, ComposeActivity.class)));
headerMenuOpen = false;
- binding.bottomNavView.inflateMenu(R.menu.bottom_nav_menu);
+ new BottomMenu(BaseMainActivity.this).hydrate(account, binding.bottomNavView);
binding.bottomNavView.setBackgroundDrawable(new ColorDrawable(ContextCompat.getColor(this, R.color.cyanea_primary)));
binding.navView.setBackgroundDrawable(new ColorDrawable(ContextCompat.getColor(this, R.color.cyanea_primary)));
diff --git a/app/src/main/java/app/fedilab/android/client/entities/BottomMenu.java b/app/src/main/java/app/fedilab/android/client/entities/BottomMenu.java
new file mode 100644
index 000000000..9ee4b3b97
--- /dev/null
+++ b/app/src/main/java/app/fedilab/android/client/entities/BottomMenu.java
@@ -0,0 +1,334 @@
+package app.fedilab.android.client.entities;
+/* 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 android.content.ContentValues;
+import android.content.Context;
+import android.database.Cursor;
+import android.database.sqlite.SQLiteDatabase;
+import android.view.Menu;
+
+import com.google.android.material.bottomnavigation.BottomNavigationView;
+import com.google.gson.Gson;
+import com.google.gson.annotations.SerializedName;
+import com.google.gson.reflect.TypeToken;
+
+import java.io.Serializable;
+import java.util.ArrayList;
+import java.util.List;
+
+import app.fedilab.android.BaseMainActivity;
+import app.fedilab.android.R;
+import app.fedilab.android.exception.DBException;
+import app.fedilab.android.sqlite.Sqlite;
+
+
+public class BottomMenu implements Serializable {
+ private final SQLiteDatabase db;
+
+ @SerializedName("id")
+ public long id = -1;
+ @SerializedName("instance")
+ public String instance;
+ @SerializedName("user_id")
+ public String user_id;
+ @SerializedName("bottom_menu")
+ public List<MenuItem> bottom_menu;
+ private Context context;
+
+ public BottomMenu() {
+ db = null;
+ }
+
+ public BottomMenu(Context context) {
+ //Creation of the DB with tables
+ this.context = context;
+ this.db = Sqlite.getInstance(context.getApplicationContext(), Sqlite.DB_NAME, null, Sqlite.DB_VERSION).open();
+ }
+
+ /**
+ * Serialized a list of MenuItem class
+ *
+ * @param menuItemList List of {@link MenuItem} to serialize
+ * @return String serialized menuItemList list
+ */
+ public static String menuItemListToStringStorage(List<MenuItem> menuItemList) {
+ Gson gson = new Gson();
+ try {
+ return gson.toJson(menuItemList);
+ } catch (Exception e) {
+ return null;
+ }
+ }
+
+ /**
+ * Unserialized a MenuItem List
+ *
+ * @param serializedMenuItem String serialized MenuItem list
+ * @return List of {@link MenuItem}
+ */
+ public static List<MenuItem> restoreMenuItemFromString(String serializedMenuItem) {
+ Gson gson = new Gson();
+ try {
+ return gson.fromJson(serializedMenuItem, new TypeToken<List<MenuItem>>() {
+ }.getType());
+ } catch (Exception e) {
+ return null;
+ }
+ }
+
+ public void hydrate(Account account, BottomNavigationView bottomNavigationView) {
+ bottomNavigationView.getMenu().clear();
+ BottomMenu bottomMenu;
+ try {
+ bottomMenu = getBottomMenu(account);
+ } catch (DBException e) {
+ bottomMenu = defaultBottomMenu();
+ }
+ for (BottomMenu.MenuItem menuItem : bottomMenu.bottom_menu) {
+ if (menuItem.visible) {
+ switch (menuItem.item_menu_type) {
+ case HOME:
+ bottomNavigationView.getMenu().add(Menu.NONE, R.id.nav_home, menuItem.position, context.getString(R.string.home_menu)).setIcon(R.drawable.ic_baseline_home_24);
+ break;
+ case LOCAL:
+ bottomNavigationView.getMenu().add(Menu.NONE, R.id.nav_local, menuItem.position, context.getString(R.string.local_menu)).setIcon(R.drawable.ic_baseline_people_alt_24);
+ break;
+ case PUBLIC:
+ bottomNavigationView.getMenu().add(Menu.NONE, R.id.nav_public, menuItem.position, context.getString(R.string.v_public)).setIcon(R.drawable.ic_baseline_public_24);
+ break;
+ case NOTIFICATION:
+ bottomNavigationView.getMenu().add(Menu.NONE, R.id.nav_notifications, menuItem.position, context.getString(R.string.notifications)).setIcon(R.drawable.ic_baseline_notifications_24);
+ break;
+ case DIRECT:
+ bottomNavigationView.getMenu().add(Menu.NONE, R.id.nav_privates, menuItem.position, context.getString(R.string.v_private)).setIcon(R.drawable.ic_baseline_mail_24);
+ break;
+ }
+ }
+ }
+ }
+
+ /**
+ * Insert or update instance
+ *
+ * @param bottomMenu {@link BottomMenu}
+ * @return long - db id
+ * @throws DBException exception with database
+ */
+ public long insertOrUpdate(BottomMenu bottomMenu) throws DBException {
+ if (db == null) {
+ throw new DBException("db is null. Wrong initialization.");
+ }
+ if (bottomMenu == null) {
+ return -1;
+ }
+ boolean exists = bottomMenuExists(bottomMenu);
+ long idReturned;
+ if (exists) {
+ idReturned = updateBottomMenu(bottomMenu);
+ } else {
+ idReturned = insertBottomMenu(bottomMenu);
+ }
+ return idReturned;
+ }
+
+ /**
+ * Insert BottomMenu in db
+ *
+ * @param bottomMenu {@link BottomMenu}
+ * @return long - db id
+ * @throws DBException exception with database
+ */
+ private long insertBottomMenu(BottomMenu bottomMenu) throws DBException {
+ if (db == null) {
+ throw new DBException("db is null. Wrong initialization.");
+ }
+ ContentValues values = new ContentValues();
+ values.put(Sqlite.COL_INSTANCE, BaseMainActivity.currentInstance);
+ values.put(Sqlite.COL_USER_ID, BaseMainActivity.currentUserID);
+ values.put(Sqlite.COL_BOTTOM_MENU, menuItemListToStringStorage(bottomMenu.bottom_menu));
+ //Inserts bottom
+ try {
+ return db.insertOrThrow(Sqlite.TABLE_BOTTOM_MENU, null, values);
+ } catch (Exception e) {
+ e.printStackTrace();
+ return -1;
+ }
+ }
+
+ /**
+ * update bottomMenu in db
+ *
+ * @param bottomMenu {@link BottomMenu}
+ * @return long - db id
+ * @throws DBException exception with database
+ */
+ private long updateBottomMenu(BottomMenu bottomMenu) throws DBException {
+ if (db == null) {
+ throw new DBException("db is null. Wrong initialization.");
+ }
+ ContentValues values = new ContentValues();
+ values.put(Sqlite.COL_BOTTOM_MENU, menuItemListToStringStorage(bottomMenu.bottom_menu));
+ //Inserts token
+ try {
+ return db.update(Sqlite.TABLE_BOTTOM_MENU,
+ values, Sqlite.COL_INSTANCE + " = ? AND " + Sqlite.COL_USER_ID + " = ?",
+ new String[]{bottomMenu.instance, bottomMenu.user_id});
+ } catch (Exception e) {
+ e.printStackTrace();
+ return -1;
+ }
+ }
+
+ /**
+ * Returns the bottom menu for an account
+ *
+ * @param account Account
+ * @return Pinned - {@link BottomMenu}
+ */
+ private BottomMenu getBottomMenu(Account account) throws DBException {
+ if (db == null) {
+ throw new DBException("db is null. Wrong initialization.");
+ }
+ try {
+ Cursor c = db.query(Sqlite.TABLE_BOTTOM_MENU, null, Sqlite.COL_INSTANCE + " = '" + account.instance + "' AND " + Sqlite.COL_USER_ID + " = '" + account.user_id + "'", null, null, null, Sqlite.COL_ID + " DESC", "1");
+ BottomMenu bottomMenu = cursorToBottomMenu(c);
+ List<MenuItem> menuItemList = new ArrayList<>();
+ if (bottomMenu != null) {
+ for (MenuItem menuItem : bottomMenu.bottom_menu) {
+ if (menuItem.visible) {
+ menuItemList.add(menuItem.position, menuItem);
+ }
+ }
+ bottomMenu.bottom_menu = menuItemList;
+ }
+ if (bottomMenu == null) {
+ bottomMenu = defaultBottomMenu();
+ }
+ return bottomMenu;
+ } catch (Exception e) {
+ return defaultBottomMenu();
+ }
+ }
+
+ private BottomMenu defaultBottomMenu() {
+ BottomMenu bottomMenu = new BottomMenu();
+ bottomMenu.bottom_menu = new ArrayList<>();
+ MenuItem menuItemHome = new MenuItem();
+ menuItemHome.position = 0;
+ menuItemHome.visible = true;
+ menuItemHome.item_menu_type = ItemMenuType.HOME;
+ bottomMenu.bottom_menu.add(menuItemHome);
+ MenuItem menuItemLocal = new MenuItem();
+ menuItemLocal.position = 1;
+ menuItemLocal.visible = true;
+ menuItemLocal.item_menu_type = ItemMenuType.LOCAL;
+ bottomMenu.bottom_menu.add(menuItemLocal);
+ MenuItem menuItemPublic = new MenuItem();
+ menuItemPublic.position = 2;
+ menuItemPublic.visible = true;
+ menuItemPublic.item_menu_type = ItemMenuType.PUBLIC;
+ bottomMenu.bottom_menu.add(menuItemPublic);
+ MenuItem menuItemNotification = new MenuItem();
+ menuItemNotification.position = 3;
+ menuItemNotification.visible = true;
+ menuItemNotification.item_menu_type = ItemMenuType.NOTIFICATION;
+ bottomMenu.bottom_menu.add(menuItemNotification);
+ MenuItem menuItemPrivate = new MenuItem();
+ menuItemPrivate.position = 4;
+ menuItemPrivate.visible = true;
+ menuItemPrivate.item_menu_type = ItemMenuType.DIRECT;
+ bottomMenu.bottom_menu.add(menuItemPrivate);
+ return bottomMenu;
+ }
+
+ public boolean bottomMenuExists(BottomMenu bottomMenu) throws DBException {
+ if (db == null) {
+ throw new DBException("db is null. Wrong initialization.");
+ }
+ Cursor mCount = db.rawQuery("select count(*) from " + Sqlite.TABLE_BOTTOM_MENU
+ + " where " + Sqlite.COL_INSTANCE + " = '" + bottomMenu.instance + "' AND " + Sqlite.COL_USER_ID + " = '" + bottomMenu.user_id + "'", null);
+ mCount.moveToFirst();
+ int count = mCount.getInt(0);
+ mCount.close();
+ return (count > 0);
+ }
+
+ /**
+ * Restore pinned from db
+ *
+ * @param c Cursor
+ * @return Pinned
+ */
+ private BottomMenu cursorToBottomMenu(Cursor c) {
+ //No element found
+ if (c.getCount() == 0) {
+ c.close();
+ return null;
+ }
+ //Take the first element
+ c.moveToFirst();
+ BottomMenu bottomMenu = convertCursorToBottomMenu(c);
+ //Close the cursor
+ c.close();
+ return bottomMenu;
+ }
+
+ /**
+ * Read cursor and hydrate without closing it
+ *
+ * @param c - Cursor
+ * @return BottomMenu
+ */
+ private BottomMenu convertCursorToBottomMenu(Cursor c) {
+ BottomMenu bottomMenu = new BottomMenu();
+ bottomMenu.id = c.getInt(c.getColumnIndexOrThrow(Sqlite.COL_ID));
+ bottomMenu.instance = c.getString(c.getColumnIndexOrThrow(Sqlite.COL_INSTANCE));
+ bottomMenu.user_id = c.getString(c.getColumnIndexOrThrow(Sqlite.COL_USER_ID));
+ bottomMenu.bottom_menu = restoreMenuItemFromString(c.getString(c.getColumnIndexOrThrow(Sqlite.COL_BOTTOM_MENU)));
+ return bottomMenu;
+ }
+
+ public enum ItemMenuType {
+ @SerializedName("HOME")
+ HOME("HOME"),
+ @SerializedName("DIRECT")
+ DIRECT("DIRECT"),
+ @SerializedName("NOTIFICATION")
+ NOTIFICATION("NOTIFICATION"),
+ @SerializedName("LOCAL")
+ LOCAL("LOCAL"),
+ @SerializedName("PUBLIC")
+ PUBLIC("PUBLIC");
+ private final String value;
+
+ ItemMenuType(String value) {
+ this.value = value;
+ }
+
+ public String getValue() {
+ return value;
+ }
+ }
+
+ public static class MenuItem {
+ @SerializedName("position")
+ int position;
+ @SerializedName("item_menu_type")
+ ItemMenuType item_menu_type;
+ @SerializedName("visible")
+ boolean visible;
+ }
+}
diff --git a/app/src/main/java/app/fedilab/android/sqlite/Sqlite.java b/app/src/main/java/app/fedilab/android/sqlite/Sqlite.java
index aef5e8048..5f650e686 100644
--- a/app/src/main/java/app/fedilab/android/sqlite/Sqlite.java
+++ b/app/src/main/java/app/fedilab/android/sqlite/Sqlite.java
@@ -23,7 +23,7 @@ import android.database.sqlite.SQLiteOpenHelper;
public class Sqlite extends SQLiteOpenHelper {
- public static final int DB_VERSION = 2;
+ public static final int DB_VERSION = 3;
public static final String DB_NAME = "fedilab_db";
//Table of owned accounts
@@ -77,6 +77,10 @@ public class Sqlite extends SQLiteOpenHelper {
public static final String TABLE_QUICK_LOAD = "QUICK_LOAD";
public static final String COL_SLUG = "SLUG";
public static final String COL_STATUSES = "STATUSES";
+ //Bottom menu
+ public static final String TABLE_BOTTOM_MENU = "TABLE_BOTTOM_MENU";
+ public static final String COL_BOTTOM_MENU = "BOTTOM_MENU";
+
private static final String CREATE_TABLE_USER_ACCOUNT = "CREATE TABLE " + TABLE_USER_ACCOUNT + " ("
+ COL_USER_ID + " TEXT NOT NULL, "
@@ -157,6 +161,13 @@ public class Sqlite extends SQLiteOpenHelper {
+ COL_POSITION + " INTEGER, "
+ COL_STATUSES + " TEXT NOT NULL)";
+
+ private static final String CREATE_TABLE_BOTTOM_MENU = "CREATE TABLE IF NOT EXISTS " + TABLE_BOTTOM_MENU + " ("
+ + COL_ID + " INTEGER PRIMARY KEY AUTOINCREMENT, "
+ + COL_INSTANCE + " TEXT NOT NULL, "
+ + COL_USER_ID + " TEXT NOT NULL, "
+ + COL_BOTTOM_MENU + " TEXT NOT NULL)";
+
public static SQLiteDatabase db;
private static Sqlite sInstance;
@@ -184,6 +195,7 @@ public class Sqlite extends SQLiteOpenHelper {
db.execSQL(CREATE_TABLE_PINNED_TIMELINES);
db.execSQL(CREATE_TABLE_SCHEDULE_BOOST);
db.execSQL(CREATE_TABLE_QUICK_LOAD);
+ db.execSQL(CREATE_TABLE_BOTTOM_MENU);
}
@Override
@@ -193,10 +205,11 @@ public class Sqlite extends SQLiteOpenHelper {
@Override
public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {
- //noinspection SwitchStatementWithTooFewBranches
switch (oldVersion) {
case 1:
db.execSQL(CREATE_TABLE_QUICK_LOAD);
+ case 2:
+ db.execSQL(CREATE_TABLE_BOTTOM_MENU);
default:
break;
}
diff --git a/app/src/main/res/layout/activity_reorder_tabs.xml b/app/src/main/res/layout/activity_reorder_tabs.xml
index a807eb470..9a0769258 100644
--- a/app/src/main/res/layout/activity_reorder_tabs.xml
+++ b/app/src/main/res/layout/activity_reorder_tabs.xml
@@ -19,6 +19,12 @@
android:layout_height="match_parent">
<androidx.recyclerview.widget.RecyclerView
+ android:id="@+id/lv_reorder_bottom"
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ android:scrollbars="none" />
+
+ <androidx.recyclerview.widget.RecyclerView
android:id="@+id/lv_reorder_tabs"
android:layout_width="match_parent"
android:layout_height="wrap_content"