diff --git a/app/src/main/java/im/conversations/android/database/dao/ChatDao.java b/app/src/main/java/im/conversations/android/database/dao/ChatDao.java index 701e1dd2f..b7f6671c0 100644 --- a/app/src/main/java/im/conversations/android/database/dao/ChatDao.java +++ b/app/src/main/java/im/conversations/android/database/dao/ChatDao.java @@ -9,6 +9,7 @@ import im.conversations.android.database.entity.ChatEntity; import im.conversations.android.database.model.Account; import im.conversations.android.database.model.ChatIdentifier; import im.conversations.android.database.model.ChatType; +import im.conversations.android.database.model.GroupIdentifier; import im.conversations.android.xmpp.model.stanza.Message; import java.util.Arrays; import java.util.List; @@ -55,6 +56,6 @@ public abstract class ChatDao { @Insert protected abstract long insert(ChatEntity chatEntity); - @Query("SELECT name FROM `group` ORDER BY name") - public abstract LiveData> getGroups(); + @Query("SELECT id,name FROM `group` ORDER BY name") + public abstract LiveData> getGroups(); } diff --git a/app/src/main/java/im/conversations/android/database/model/AccountIdentifier.java b/app/src/main/java/im/conversations/android/database/model/AccountIdentifier.java index f1bb641f6..08ab3e664 100644 --- a/app/src/main/java/im/conversations/android/database/model/AccountIdentifier.java +++ b/app/src/main/java/im/conversations/android/database/model/AccountIdentifier.java @@ -1,11 +1,13 @@ package im.conversations.android.database.model; import androidx.annotation.NonNull; + +import com.google.common.base.MoreObjects; import com.google.common.base.Objects; import com.google.common.base.Preconditions; import org.jxmpp.jid.BareJid; -public class AccountIdentifier { +public class AccountIdentifier implements ChatFilter { public final long id; @NonNull public final BareJid address; @@ -28,4 +30,12 @@ public class AccountIdentifier { this.id = id; this.address = address; } + + @Override + public String toString() { + return MoreObjects.toStringHelper(this) + .add("id", id) + .add("address", address) + .toString(); + } } diff --git a/app/src/main/java/im/conversations/android/database/model/ChatFilter.java b/app/src/main/java/im/conversations/android/database/model/ChatFilter.java new file mode 100644 index 000000000..cc9ee1072 --- /dev/null +++ b/app/src/main/java/im/conversations/android/database/model/ChatFilter.java @@ -0,0 +1,3 @@ +package im.conversations.android.database.model; + +public interface ChatFilter {} diff --git a/app/src/main/java/im/conversations/android/database/model/GroupIdentifier.java b/app/src/main/java/im/conversations/android/database/model/GroupIdentifier.java new file mode 100644 index 000000000..c8e125f44 --- /dev/null +++ b/app/src/main/java/im/conversations/android/database/model/GroupIdentifier.java @@ -0,0 +1,26 @@ +package im.conversations.android.database.model; + +import com.google.common.base.MoreObjects; +import com.google.common.base.Objects; + +import java.util.StringJoiner; + +public class GroupIdentifier implements ChatFilter { + + public final long id; + public final String name; + + + @Override + public String toString() { + return MoreObjects.toStringHelper(this) + .add("id", id) + .add("name", name) + .toString(); + } + + public GroupIdentifier(long id, String name) { + this.id = id; + this.name = name; + } +} diff --git a/app/src/main/java/im/conversations/android/repository/ChatRepository.java b/app/src/main/java/im/conversations/android/repository/ChatRepository.java index 83d668a54..9050ed915 100644 --- a/app/src/main/java/im/conversations/android/repository/ChatRepository.java +++ b/app/src/main/java/im/conversations/android/repository/ChatRepository.java @@ -2,6 +2,7 @@ package im.conversations.android.repository; import android.content.Context; import androidx.lifecycle.LiveData; +import im.conversations.android.database.model.GroupIdentifier; import java.util.List; public class ChatRepository extends AbstractRepository { @@ -10,7 +11,7 @@ public class ChatRepository extends AbstractRepository { super(context); } - public LiveData> getGroups() { + public LiveData> getGroups() { return this.database.chatDao().getGroups(); } } diff --git a/app/src/main/java/im/conversations/android/ui/Intents.java b/app/src/main/java/im/conversations/android/ui/Intents.java new file mode 100644 index 000000000..2fcfc84b3 --- /dev/null +++ b/app/src/main/java/im/conversations/android/ui/Intents.java @@ -0,0 +1,67 @@ +package im.conversations.android.ui; + +import android.content.Intent; + +import com.google.common.base.Strings; + +import org.jxmpp.jid.BareJid; +import org.jxmpp.jid.impl.JidCreate; + +import im.conversations.android.database.model.AccountIdentifier; +import im.conversations.android.database.model.ChatFilter; +import im.conversations.android.database.model.GroupIdentifier; + +public final class Intents { + + public static final String ACTION_FILTER_CHATS_BY_ACCOUNT = "filter-chats-by-account"; + public static final String ACTION_FILTER_CHATS_BY_GROUP = "filter-chats-by-group"; + public static final String EXTRA_ACCOUNT_ID = "account-id"; + public static final String EXTRA_ACCOUNT_ADDRESS = "account-address"; + public static final String EXTRA_GROUP_ID = "group-id"; + public static final String EXTRA_GROUP_NAME = "group-name"; + + private Intents() {} + + public static Intent of(final ChatFilter chatFilter) { + if (chatFilter instanceof AccountIdentifier) { + final var account = (AccountIdentifier) chatFilter; + final var intent = new Intent(ACTION_FILTER_CHATS_BY_ACCOUNT); + intent.putExtra(EXTRA_ACCOUNT_ID, account.id); + intent.putExtra(EXTRA_ACCOUNT_ADDRESS, account.address.toString()); + return intent; + } + if (chatFilter instanceof GroupIdentifier) { + final var group = (GroupIdentifier) chatFilter; + final var intent = new Intent(ACTION_FILTER_CHATS_BY_GROUP); + intent.putExtra(EXTRA_GROUP_ID, group.id); + intent.putExtra(EXTRA_GROUP_NAME, group.name); + return intent; + } + throw new IllegalStateException( + String.format("%s is not implemented", chatFilter.getClass().getName())); + } + + public static ChatFilter toChatFilter(final Intent intent) { + final var action = intent == null ? null : intent.getAction(); + if (action == null) { + throw new IllegalArgumentException("Intent doe not specify an action"); + } + if (ACTION_FILTER_CHATS_BY_ACCOUNT.equals(action)) { + final var id = intent.getLongExtra(EXTRA_ACCOUNT_ID,-1); + final var address = intent.getStringExtra(EXTRA_ACCOUNT_ADDRESS); + if (id < 0 || Strings.isNullOrEmpty(address)) { + throw new IllegalArgumentException("account filter intent lacks extras"); + } + return new AccountIdentifier(id, JidCreate.bareFromOrThrowUnchecked(address)); + } + if (ACTION_FILTER_CHATS_BY_GROUP.equals(action)) { + final var id = intent.getLongExtra(EXTRA_GROUP_ID,-1); + final var name = intent.getStringExtra(EXTRA_GROUP_NAME); + if (id < 0 || Strings.isNullOrEmpty(name)) { + throw new IllegalArgumentException("group filter intent lack address"); + } + return new GroupIdentifier(id, name); + } + throw new IllegalArgumentException("Unsupported action"); + } +} diff --git a/app/src/main/java/im/conversations/android/ui/activity/SetupActivity.java b/app/src/main/java/im/conversations/android/ui/activity/SetupActivity.java index cb0565513..2c3fecdd2 100644 --- a/app/src/main/java/im/conversations/android/ui/activity/SetupActivity.java +++ b/app/src/main/java/im/conversations/android/ui/activity/SetupActivity.java @@ -1,5 +1,6 @@ package im.conversations.android.ui.activity; +import android.content.Intent; import android.os.Bundle; import androidx.appcompat.app.AppCompatActivity; import androidx.databinding.DataBindingUtil; @@ -42,7 +43,7 @@ public class SetupActivity extends AppCompatActivity { navController.navigate(SetupNavigationDirections.enterPassword()); break; case DONE: - // TODO open MainActivity + startActivity(new Intent(this, MainActivity.class)); finish(); break; default: diff --git a/app/src/main/java/im/conversations/android/ui/fragment/main/OverviewFragment.java b/app/src/main/java/im/conversations/android/ui/fragment/main/OverviewFragment.java index 5fdd9ece1..19b14c38d 100644 --- a/app/src/main/java/im/conversations/android/ui/fragment/main/OverviewFragment.java +++ b/app/src/main/java/im/conversations/android/ui/fragment/main/OverviewFragment.java @@ -13,13 +13,20 @@ import com.google.android.material.elevation.SurfaceColors; import com.google.android.material.search.SearchView; import im.conversations.android.R; import im.conversations.android.database.model.AccountIdentifier; +import im.conversations.android.database.model.ChatFilter; +import im.conversations.android.database.model.GroupIdentifier; import im.conversations.android.databinding.FragmentOverviewBinding; +import im.conversations.android.ui.Intents; import im.conversations.android.ui.activity.SetupActivity; import im.conversations.android.ui.model.OverviewViewModel; import java.util.List; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; public class OverviewFragment extends Fragment { + private static final Logger LOGGER = LoggerFactory.getLogger(OverviewViewModel.class); + private FragmentOverviewBinding binding; private OverviewViewModel overviewViewModel; @@ -50,10 +57,20 @@ public class OverviewFragment extends Fragment { }); binding.navigationView.setNavigationItemSelectedListener( item -> { + if (item.getItemId() == R.id.chats) { + setChatFilter(null); + return true; + } if (item.getItemId() == R.id.add_account) { startActivity(new Intent(requireContext(), SetupActivity.class)); + binding.drawerLayout.close(); return false; } + final var intent = item.getIntent(); + if (intent == null) { + return false; + } + setChatFilter(Intents.toChatFilter(intent)); return true; }); binding.navigationView.setCheckedItem(R.id.chats); @@ -67,6 +84,11 @@ public class OverviewFragment extends Fragment { return binding.getRoot(); } + private void setChatFilter(final ChatFilter chatFilter) { + overviewViewModel.setChatFilter(chatFilter); + binding.drawerLayout.close(); + } + private void onChatFilterAvailable(final Boolean available) { final var menu = this.binding.navigationView.getMenu(); final var chatsMenuItem = menu.findItem(R.id.chats); @@ -77,7 +99,7 @@ public class OverviewFragment extends Fragment { } } - private void onGroupsUpdated(final List groups) { + private void onGroupsUpdated(final List groups) { final var menu = this.binding.navigationView.getMenu(); final var menuItemSpaces = menu.findItem(R.id.spaces); if (groups.isEmpty()) { @@ -87,10 +109,11 @@ public class OverviewFragment extends Fragment { menuItemSpaces.setVisible(true); final var subMenu = menuItemSpaces.getSubMenu(); subMenu.clear(); - for (final String group : groups) { - final var menuItemSpace = subMenu.add(group); + for (final GroupIdentifier group : groups) { + final var menuItemSpace = subMenu.add(group.name); menuItemSpace.setCheckable(true); menuItemSpace.setIcon(R.drawable.ic_workspaces_24dp); + menuItemSpace.setIntent(Intents.of(group)); } } @@ -108,6 +131,7 @@ public class OverviewFragment extends Fragment { final var menuItemAccount = subMenu.add(account.address); menuItemAccount.setCheckable(true); menuItemAccount.setIcon(R.drawable.ic_person_24dp); + menuItemAccount.setIntent(Intents.of(account)); } } } diff --git a/app/src/main/java/im/conversations/android/ui/model/OverviewViewModel.java b/app/src/main/java/im/conversations/android/ui/model/OverviewViewModel.java index 58d123a40..85155b5d0 100644 --- a/app/src/main/java/im/conversations/android/ui/model/OverviewViewModel.java +++ b/app/src/main/java/im/conversations/android/ui/model/OverviewViewModel.java @@ -7,6 +7,8 @@ import androidx.lifecycle.LiveData; import androidx.lifecycle.MediatorLiveData; import androidx.lifecycle.Transformations; import im.conversations.android.database.model.AccountIdentifier; +import im.conversations.android.database.model.ChatFilter; +import im.conversations.android.database.model.GroupIdentifier; import im.conversations.android.repository.AccountRepository; import im.conversations.android.repository.ChatRepository; import java.util.List; @@ -18,11 +20,13 @@ public class OverviewViewModel extends AndroidViewModel { private final AccountRepository accountRepository; private final ChatRepository chatRepository; private final LiveData> accounts; - private final LiveData> groups; + private final LiveData> groups; private final MediatorLiveData chatFilterAvailable = new MediatorLiveData<>(); private static final Logger LOGGER = LoggerFactory.getLogger(OverviewViewModel.class); + private ChatFilter chatFilter; + public OverviewViewModel(@NonNull Application application) { super(application); this.accountRepository = new AccountRepository(application); @@ -36,7 +40,7 @@ public class OverviewViewModel extends AndroidViewModel { } private void setChatFilterAvailable( - final List accounts, final List groups) { + final List accounts, final List groups) { this.chatFilterAvailable.setValue( (accounts != null && accounts.size() > 1) || (groups != null && groups.size() > 0)); } @@ -45,11 +49,21 @@ public class OverviewViewModel extends AndroidViewModel { return Transformations.distinctUntilChanged(this.accountRepository.getAccounts()); } - public LiveData> getGroups() { + // TODO change into GroupIdentifier + public LiveData> getGroups() { return Transformations.distinctUntilChanged(this.chatRepository.getGroups()); } public LiveData getChatFilterAvailable() { return Transformations.distinctUntilChanged(this.chatFilterAvailable); } + + public ChatFilter getChatFilter() { + return this.chatFilter; + } + + public void setChatFilter(final ChatFilter chatFilter) { + this.chatFilter = chatFilter; + LOGGER.info("Setting chat filter to {}", chatFilter); + } }