stick intent into menu items to know which one was clicked

This commit is contained in:
Daniel Gultsch 2023-02-19 21:12:21 +01:00
parent 867db9d54c
commit cdcd323c36
No known key found for this signature in database
GPG key ID: F43D18AD2A0982C2
9 changed files with 158 additions and 11 deletions

View file

@ -9,6 +9,7 @@ import im.conversations.android.database.entity.ChatEntity;
import im.conversations.android.database.model.Account; import im.conversations.android.database.model.Account;
import im.conversations.android.database.model.ChatIdentifier; import im.conversations.android.database.model.ChatIdentifier;
import im.conversations.android.database.model.ChatType; import im.conversations.android.database.model.ChatType;
import im.conversations.android.database.model.GroupIdentifier;
import im.conversations.android.xmpp.model.stanza.Message; import im.conversations.android.xmpp.model.stanza.Message;
import java.util.Arrays; import java.util.Arrays;
import java.util.List; import java.util.List;
@ -55,6 +56,6 @@ public abstract class ChatDao {
@Insert @Insert
protected abstract long insert(ChatEntity chatEntity); protected abstract long insert(ChatEntity chatEntity);
@Query("SELECT name FROM `group` ORDER BY name") @Query("SELECT id,name FROM `group` ORDER BY name")
public abstract LiveData<List<String>> getGroups(); public abstract LiveData<List<GroupIdentifier>> getGroups();
} }

View file

@ -1,11 +1,13 @@
package im.conversations.android.database.model; package im.conversations.android.database.model;
import androidx.annotation.NonNull; import androidx.annotation.NonNull;
import com.google.common.base.MoreObjects;
import com.google.common.base.Objects; import com.google.common.base.Objects;
import com.google.common.base.Preconditions; import com.google.common.base.Preconditions;
import org.jxmpp.jid.BareJid; import org.jxmpp.jid.BareJid;
public class AccountIdentifier { public class AccountIdentifier implements ChatFilter {
public final long id; public final long id;
@NonNull public final BareJid address; @NonNull public final BareJid address;
@ -28,4 +30,12 @@ public class AccountIdentifier {
this.id = id; this.id = id;
this.address = address; this.address = address;
} }
@Override
public String toString() {
return MoreObjects.toStringHelper(this)
.add("id", id)
.add("address", address)
.toString();
}
} }

View file

@ -0,0 +1,3 @@
package im.conversations.android.database.model;
public interface ChatFilter {}

View file

@ -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;
}
}

View file

@ -2,6 +2,7 @@ package im.conversations.android.repository;
import android.content.Context; import android.content.Context;
import androidx.lifecycle.LiveData; import androidx.lifecycle.LiveData;
import im.conversations.android.database.model.GroupIdentifier;
import java.util.List; import java.util.List;
public class ChatRepository extends AbstractRepository { public class ChatRepository extends AbstractRepository {
@ -10,7 +11,7 @@ public class ChatRepository extends AbstractRepository {
super(context); super(context);
} }
public LiveData<List<String>> getGroups() { public LiveData<List<GroupIdentifier>> getGroups() {
return this.database.chatDao().getGroups(); return this.database.chatDao().getGroups();
} }
} }

View file

@ -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");
}
}

View file

@ -1,5 +1,6 @@
package im.conversations.android.ui.activity; package im.conversations.android.ui.activity;
import android.content.Intent;
import android.os.Bundle; import android.os.Bundle;
import androidx.appcompat.app.AppCompatActivity; import androidx.appcompat.app.AppCompatActivity;
import androidx.databinding.DataBindingUtil; import androidx.databinding.DataBindingUtil;
@ -42,7 +43,7 @@ public class SetupActivity extends AppCompatActivity {
navController.navigate(SetupNavigationDirections.enterPassword()); navController.navigate(SetupNavigationDirections.enterPassword());
break; break;
case DONE: case DONE:
// TODO open MainActivity startActivity(new Intent(this, MainActivity.class));
finish(); finish();
break; break;
default: default:

View file

@ -13,13 +13,20 @@ import com.google.android.material.elevation.SurfaceColors;
import com.google.android.material.search.SearchView; import com.google.android.material.search.SearchView;
import im.conversations.android.R; import im.conversations.android.R;
import im.conversations.android.database.model.AccountIdentifier; 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.databinding.FragmentOverviewBinding;
import im.conversations.android.ui.Intents;
import im.conversations.android.ui.activity.SetupActivity; import im.conversations.android.ui.activity.SetupActivity;
import im.conversations.android.ui.model.OverviewViewModel; import im.conversations.android.ui.model.OverviewViewModel;
import java.util.List; import java.util.List;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
public class OverviewFragment extends Fragment { public class OverviewFragment extends Fragment {
private static final Logger LOGGER = LoggerFactory.getLogger(OverviewViewModel.class);
private FragmentOverviewBinding binding; private FragmentOverviewBinding binding;
private OverviewViewModel overviewViewModel; private OverviewViewModel overviewViewModel;
@ -50,10 +57,20 @@ public class OverviewFragment extends Fragment {
}); });
binding.navigationView.setNavigationItemSelectedListener( binding.navigationView.setNavigationItemSelectedListener(
item -> { item -> {
if (item.getItemId() == R.id.chats) {
setChatFilter(null);
return true;
}
if (item.getItemId() == R.id.add_account) { if (item.getItemId() == R.id.add_account) {
startActivity(new Intent(requireContext(), SetupActivity.class)); startActivity(new Intent(requireContext(), SetupActivity.class));
binding.drawerLayout.close();
return false; return false;
} }
final var intent = item.getIntent();
if (intent == null) {
return false;
}
setChatFilter(Intents.toChatFilter(intent));
return true; return true;
}); });
binding.navigationView.setCheckedItem(R.id.chats); binding.navigationView.setCheckedItem(R.id.chats);
@ -67,6 +84,11 @@ public class OverviewFragment extends Fragment {
return binding.getRoot(); return binding.getRoot();
} }
private void setChatFilter(final ChatFilter chatFilter) {
overviewViewModel.setChatFilter(chatFilter);
binding.drawerLayout.close();
}
private void onChatFilterAvailable(final Boolean available) { private void onChatFilterAvailable(final Boolean available) {
final var menu = this.binding.navigationView.getMenu(); final var menu = this.binding.navigationView.getMenu();
final var chatsMenuItem = menu.findItem(R.id.chats); final var chatsMenuItem = menu.findItem(R.id.chats);
@ -77,7 +99,7 @@ public class OverviewFragment extends Fragment {
} }
} }
private void onGroupsUpdated(final List<String> groups) { private void onGroupsUpdated(final List<GroupIdentifier> groups) {
final var menu = this.binding.navigationView.getMenu(); final var menu = this.binding.navigationView.getMenu();
final var menuItemSpaces = menu.findItem(R.id.spaces); final var menuItemSpaces = menu.findItem(R.id.spaces);
if (groups.isEmpty()) { if (groups.isEmpty()) {
@ -87,10 +109,11 @@ public class OverviewFragment extends Fragment {
menuItemSpaces.setVisible(true); menuItemSpaces.setVisible(true);
final var subMenu = menuItemSpaces.getSubMenu(); final var subMenu = menuItemSpaces.getSubMenu();
subMenu.clear(); subMenu.clear();
for (final String group : groups) { for (final GroupIdentifier group : groups) {
final var menuItemSpace = subMenu.add(group); final var menuItemSpace = subMenu.add(group.name);
menuItemSpace.setCheckable(true); menuItemSpace.setCheckable(true);
menuItemSpace.setIcon(R.drawable.ic_workspaces_24dp); 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); final var menuItemAccount = subMenu.add(account.address);
menuItemAccount.setCheckable(true); menuItemAccount.setCheckable(true);
menuItemAccount.setIcon(R.drawable.ic_person_24dp); menuItemAccount.setIcon(R.drawable.ic_person_24dp);
menuItemAccount.setIntent(Intents.of(account));
} }
} }
} }

View file

@ -7,6 +7,8 @@ import androidx.lifecycle.LiveData;
import androidx.lifecycle.MediatorLiveData; import androidx.lifecycle.MediatorLiveData;
import androidx.lifecycle.Transformations; import androidx.lifecycle.Transformations;
import im.conversations.android.database.model.AccountIdentifier; 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.AccountRepository;
import im.conversations.android.repository.ChatRepository; import im.conversations.android.repository.ChatRepository;
import java.util.List; import java.util.List;
@ -18,11 +20,13 @@ public class OverviewViewModel extends AndroidViewModel {
private final AccountRepository accountRepository; private final AccountRepository accountRepository;
private final ChatRepository chatRepository; private final ChatRepository chatRepository;
private final LiveData<List<AccountIdentifier>> accounts; private final LiveData<List<AccountIdentifier>> accounts;
private final LiveData<List<String>> groups; private final LiveData<List<GroupIdentifier>> groups;
private final MediatorLiveData<Boolean> chatFilterAvailable = new MediatorLiveData<>(); private final MediatorLiveData<Boolean> chatFilterAvailable = new MediatorLiveData<>();
private static final Logger LOGGER = LoggerFactory.getLogger(OverviewViewModel.class); private static final Logger LOGGER = LoggerFactory.getLogger(OverviewViewModel.class);
private ChatFilter chatFilter;
public OverviewViewModel(@NonNull Application application) { public OverviewViewModel(@NonNull Application application) {
super(application); super(application);
this.accountRepository = new AccountRepository(application); this.accountRepository = new AccountRepository(application);
@ -36,7 +40,7 @@ public class OverviewViewModel extends AndroidViewModel {
} }
private void setChatFilterAvailable( private void setChatFilterAvailable(
final List<AccountIdentifier> accounts, final List<String> groups) { final List<AccountIdentifier> accounts, final List<GroupIdentifier> groups) {
this.chatFilterAvailable.setValue( this.chatFilterAvailable.setValue(
(accounts != null && accounts.size() > 1) || (groups != null && groups.size() > 0)); (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()); return Transformations.distinctUntilChanged(this.accountRepository.getAccounts());
} }
public LiveData<List<String>> getGroups() { // TODO change into GroupIdentifier
public LiveData<List<GroupIdentifier>> getGroups() {
return Transformations.distinctUntilChanged(this.chatRepository.getGroups()); return Transformations.distinctUntilChanged(this.chatRepository.getGroups());
} }
public LiveData<Boolean> getChatFilterAvailable() { public LiveData<Boolean> getChatFilterAvailable() {
return Transformations.distinctUntilChanged(this.chatFilterAvailable); 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);
}
} }