From 4d5b561fd8c57def20b70a11167ea3d8c40d4e1e Mon Sep 17 00:00:00 2001 From: Johann Pluss Date: Sun, 1 Jan 2023 22:46:56 +0100 Subject: [PATCH 01/41] Add main menu MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Johann Plüss --- .../src/main/res/drawable/disconnect_icon.xml | 12 ++++++ .../app/src/main/res/drawable/invite_icon.xml | 15 +++++++ .../app/src/main/res/menu/main_menu.xml | 39 +++++++++++++++++++ .../app/src/main/res/values/strings.xml | 3 ++ 4 files changed, 69 insertions(+) create mode 100644 fe2-android/app/src/main/res/drawable/disconnect_icon.xml create mode 100644 fe2-android/app/src/main/res/drawable/invite_icon.xml create mode 100644 fe2-android/app/src/main/res/menu/main_menu.xml diff --git a/fe2-android/app/src/main/res/drawable/disconnect_icon.xml b/fe2-android/app/src/main/res/drawable/disconnect_icon.xml new file mode 100644 index 0000000000..2ef68a2f3c --- /dev/null +++ b/fe2-android/app/src/main/res/drawable/disconnect_icon.xml @@ -0,0 +1,12 @@ + + + + diff --git a/fe2-android/app/src/main/res/drawable/invite_icon.xml b/fe2-android/app/src/main/res/drawable/invite_icon.xml new file mode 100644 index 0000000000..237863e54f --- /dev/null +++ b/fe2-android/app/src/main/res/drawable/invite_icon.xml @@ -0,0 +1,15 @@ + + + + + diff --git a/fe2-android/app/src/main/res/menu/main_menu.xml b/fe2-android/app/src/main/res/menu/main_menu.xml new file mode 100644 index 0000000000..e6590284aa --- /dev/null +++ b/fe2-android/app/src/main/res/menu/main_menu.xml @@ -0,0 +1,39 @@ + + + + + + + + + + + + + + + + + + diff --git a/fe2-android/app/src/main/res/values/strings.xml b/fe2-android/app/src/main/res/values/strings.xml index ba56c3b7e0..add1097e31 100644 --- a/fe2-android/app/src/main/res/values/strings.xml +++ b/fe2-android/app/src/main/res/values/strings.xml @@ -18,6 +18,9 @@ Digital Cash Event List Witnessing + Invite + Tokens + Disconnect My LAOs From 8d2cde3d92f0eb0435b39cd9d6296a643c5d2b20 Mon Sep 17 00:00:00 2001 From: Johann Pluss Date: Sun, 1 Jan 2023 23:06:00 +0100 Subject: [PATCH 02/41] Add main menu enum MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Johann Plüss --- .../popstellar/ui/navigation/MainMenuTab.java | 45 +++++++++++++++++++ 1 file changed, 45 insertions(+) create mode 100644 fe2-android/app/src/main/java/com/github/dedis/popstellar/ui/navigation/MainMenuTab.java diff --git a/fe2-android/app/src/main/java/com/github/dedis/popstellar/ui/navigation/MainMenuTab.java b/fe2-android/app/src/main/java/com/github/dedis/popstellar/ui/navigation/MainMenuTab.java new file mode 100644 index 0000000000..78726ae1a4 --- /dev/null +++ b/fe2-android/app/src/main/java/com/github/dedis/popstellar/ui/navigation/MainMenuTab.java @@ -0,0 +1,45 @@ +package com.github.dedis.popstellar.ui.navigation; + +import androidx.annotation.IdRes; + +import com.github.dedis.popstellar.R; + +import java.util.Arrays; +import java.util.List; + +public enum MainMenuTab { + INVITE(R.id.main_menu_invite), + EVENTS(R.id.main_menu_event_list), + SOCIAL_MEDIA(R.id.main_menu_social_media), + DIGITAL_CASH(R.id.main_menu_digital_cash), + WITNESSING(R.id.main_menu_witnessing), + TOKENS(R.id.main_menu_tokens), + DISCONNECT(R.id.main_menu_disconnect); + + private static final List ALL = Arrays.asList(values()); + + public static MainMenuTab findByMenu(@IdRes int menuId) { + for (MainMenuTab tab : ALL) { + if (tab.menuId == menuId) { + return tab; + } + } + + throw new IllegalArgumentException("Unknown id : " + menuId); + } + + @IdRes private final int menuId; + + MainMenuTab(@IdRes int menuId) { + this.menuId = menuId; + } + + @IdRes + public int getMenuId() { + return menuId; + } + + public String getName() { + return toString(); + } +} From 36508a7717832f8b9b236e003d773a41675dd9d4 Mon Sep 17 00:00:00 2001 From: Johann Pluss Date: Mon, 2 Jan 2023 17:53:39 +0100 Subject: [PATCH 03/41] Remove unused injection MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Johann Plüss --- .../github/dedis/popstellar/ui/detail/LaoDetailFragment.java | 2 -- 1 file changed, 2 deletions(-) diff --git a/fe2-android/app/src/main/java/com/github/dedis/popstellar/ui/detail/LaoDetailFragment.java b/fe2-android/app/src/main/java/com/github/dedis/popstellar/ui/detail/LaoDetailFragment.java index 10d3cdb3c9..69bcf1c3c5 100644 --- a/fe2-android/app/src/main/java/com/github/dedis/popstellar/ui/detail/LaoDetailFragment.java +++ b/fe2-android/app/src/main/java/com/github/dedis/popstellar/ui/detail/LaoDetailFragment.java @@ -14,7 +14,6 @@ import com.github.dedis.popstellar.R; import com.github.dedis.popstellar.databinding.LaoDetailFragmentBinding; import com.github.dedis.popstellar.model.objects.event.EventType; -import com.github.dedis.popstellar.repository.remote.GlobalNetworkManager; import com.github.dedis.popstellar.ui.detail.event.*; import com.github.dedis.popstellar.ui.detail.event.election.fragments.ElectionSetupFragment; import com.github.dedis.popstellar.ui.detail.event.rollcall.RollCallCreationFragment; @@ -35,7 +34,6 @@ public class LaoDetailFragment extends Fragment { public static final String TAG = LaoDetailFragment.class.getSimpleName(); @Inject Gson gson; - @Inject GlobalNetworkManager networkManager; private LaoDetailFragmentBinding binding; private LaoDetailViewModel viewModel; From bef956b620aca4066de8ee69d3051ab3fc734d79 Mon Sep 17 00:00:00 2001 From: Johann Pluss Date: Mon, 2 Jan 2023 18:14:56 +0100 Subject: [PATCH 04/41] Convert lao properties view to fragment accessible from Drawer MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Johann Plüss --- .../popstellar/ui/detail/InviteFragment.java | 69 ++++++++++++ .../src/main/res/layout/invite_fragment.xml | 104 ++++++++++++++++++ 2 files changed, 173 insertions(+) create mode 100644 fe2-android/app/src/main/java/com/github/dedis/popstellar/ui/detail/InviteFragment.java create mode 100644 fe2-android/app/src/main/res/layout/invite_fragment.xml diff --git a/fe2-android/app/src/main/java/com/github/dedis/popstellar/ui/detail/InviteFragment.java b/fe2-android/app/src/main/java/com/github/dedis/popstellar/ui/detail/InviteFragment.java new file mode 100644 index 0000000000..dbd858c154 --- /dev/null +++ b/fe2-android/app/src/main/java/com/github/dedis/popstellar/ui/detail/InviteFragment.java @@ -0,0 +1,69 @@ +package com.github.dedis.popstellar.ui.detail; + +import android.graphics.Bitmap; +import android.os.Bundle; +import android.view.*; + +import androidx.annotation.NonNull; +import androidx.annotation.Nullable; +import androidx.fragment.app.Fragment; + +import com.github.dedis.popstellar.R; +import com.github.dedis.popstellar.databinding.InviteFragmentBinding; +import com.github.dedis.popstellar.model.qrcode.ConnectToLao; +import com.google.gson.Gson; + +import net.glxn.qrgen.android.QRCode; + +import javax.inject.Inject; + +import dagger.hilt.android.AndroidEntryPoint; + +@AndroidEntryPoint +public class InviteFragment extends Fragment { + + @Inject Gson gson; + + private static final int QR_SIDE = 800; + + private LaoDetailViewModel viewModel; + + public static InviteFragment newInstance() { + return new InviteFragment(); + } + + @Nullable + @Override + public View onCreateView( + @NonNull LayoutInflater inflater, + @Nullable ViewGroup container, + @Nullable Bundle savedInstanceState) { + InviteFragmentBinding binding = InviteFragmentBinding.inflate(inflater, container, false); + viewModel = LaoDetailActivity.obtainViewModel(requireActivity()); + + binding.laoPropertiesIdentifierText.setText(viewModel.getPublicKey().getEncoded()); + binding.laoPropertiesServerText.setText(viewModel.getCurrentUrl()); + + viewModel + .getCurrentLao() + .observe( + requireActivity(), + laoView -> { + // Set the QR code + ConnectToLao data = new ConnectToLao(viewModel.getCurrentUrl(), laoView.getId()); + Bitmap myBitmap = QRCode.from(gson.toJson(data)).withSize(QR_SIDE, QR_SIDE).bitmap(); + binding.channelQrCode.setImageBitmap(myBitmap); + + binding.laoPropertiesNameText.setText(laoView.getName()); + // binding.laoPropertiesRoleText.setText(getRole()); + }); + + return binding.getRoot(); + } + + @Override + public void onResume() { + super.onResume(); + viewModel.setPageTitle(getString(R.string.invite)); + } +} diff --git a/fe2-android/app/src/main/res/layout/invite_fragment.xml b/fe2-android/app/src/main/res/layout/invite_fragment.xml new file mode 100644 index 0000000000..fc4f785d18 --- /dev/null +++ b/fe2-android/app/src/main/res/layout/invite_fragment.xml @@ -0,0 +1,104 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + From 980ea5101715623dabc6a445a9f12bc5a5ee9f35 Mon Sep 17 00:00:00 2001 From: Johann Pluss Date: Tue, 10 Jan 2023 00:44:49 +0100 Subject: [PATCH 05/41] Add role enum MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Johann Plüss --- .../github/dedis/popstellar/model/Role.java | 23 +++++++++++++++++++ 1 file changed, 23 insertions(+) create mode 100644 fe2-android/app/src/main/java/com/github/dedis/popstellar/model/Role.java diff --git a/fe2-android/app/src/main/java/com/github/dedis/popstellar/model/Role.java b/fe2-android/app/src/main/java/com/github/dedis/popstellar/model/Role.java new file mode 100644 index 0000000000..4ba1eff812 --- /dev/null +++ b/fe2-android/app/src/main/java/com/github/dedis/popstellar/model/Role.java @@ -0,0 +1,23 @@ +package com.github.dedis.popstellar.model; + +import androidx.annotation.StringRes; + +import com.github.dedis.popstellar.R; + +public enum Role { + ORGANIZER(R.string.organizer), + WITNESS(R.string.witness), + ATTENDEE(R.string.attendee), + MEMBER(R.string.member); + + @StringRes private final int roleString; + + Role(@StringRes int role) { + this.roleString = role; + } + + @StringRes + public int getStringId() { + return roleString; + } +} From e50a001668afd258e91c13f2180b5e8cd773f108 Mon Sep 17 00:00:00 2001 From: Johann Pluss Date: Tue, 10 Jan 2023 00:46:38 +0100 Subject: [PATCH 06/41] Adapt NavigationActivity and add main menu MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Johann Plüss --- .../ui/navigation/NavigationActivity.java | 108 ++++++++++++------ .../ui/navigation/NavigationViewModel.java | 96 +++++++++++++++- .../main/res/drawable/menu_drawer_icon.xml | 15 +++ .../res/layout/header_navigation_drawer.xml | 31 +++++ .../app/src/main/res/menu/main_menu.xml | 4 +- .../app/src/main/res/values/dimens.xml | 3 + .../app/src/main/res/values/strings.xml | 1 + 7 files changed, 217 insertions(+), 41 deletions(-) create mode 100644 fe2-android/app/src/main/res/drawable/menu_drawer_icon.xml create mode 100644 fe2-android/app/src/main/res/layout/header_navigation_drawer.xml diff --git a/fe2-android/app/src/main/java/com/github/dedis/popstellar/ui/navigation/NavigationActivity.java b/fe2-android/app/src/main/java/com/github/dedis/popstellar/ui/navigation/NavigationActivity.java index c068adef06..8eb3c1cb44 100644 --- a/fe2-android/app/src/main/java/com/github/dedis/popstellar/ui/navigation/NavigationActivity.java +++ b/fe2-android/app/src/main/java/com/github/dedis/popstellar/ui/navigation/NavigationActivity.java @@ -1,22 +1,28 @@ package com.github.dedis.popstellar.ui.navigation; import android.util.Log; +import android.widget.TextView; import androidx.appcompat.app.AppCompatActivity; +import androidx.core.view.GravityCompat; +import androidx.drawerlayout.widget.DrawerLayout; -import com.google.android.material.navigation.NavigationBarView; +import com.github.dedis.popstellar.R; +import com.github.dedis.popstellar.model.Role; +import com.google.android.material.appbar.MaterialToolbar; +import com.google.android.material.navigation.NavigationView; /** * This abstract activity encapsulate the redundant behavior of an activity with a navigation bar * *

An activity extending this must instantiate the navigationViewModel in its onCreate and it - * should call setupNavigationBar with the navigationView as parameter. + * should call setupDrawer with the navigationView as parameter. */ -public abstract class NavigationActivity extends AppCompatActivity { +public abstract class NavigationActivity extends AppCompatActivity { private static final String TAG = NavigationActivity.class.getSimpleName(); - protected NavigationViewModel navigationViewModel; + protected NavigationViewModel navigationViewModel; /** * Setup the navigation bar listeners given the navigation bar view @@ -24,15 +30,47 @@ public abstract class NavigationActivity extends AppCompatActivit *

This function should be called in the activity's onCreate after the navigation view model * has been set * - * @param navbar the view + * @param navigationView the view */ - protected void setupNavigationBar(NavigationBarView navbar) { + protected void setupDrawer( + NavigationView navigationView, MaterialToolbar toolbar, DrawerLayout drawerLayout) { + + observeRoles(); + + // Listen to click on left icon of toolbar + toolbar.setNavigationOnClickListener( + view -> { + if (navigationViewModel.isTab().getValue()) { + // If it is a tab open menu + drawerLayout.openDrawer(GravityCompat.START); + } else { + // Press back arrow + onBackPressed(); + } + }); + + // Observe whether the menu icon or back arrow should be displayed + navigationViewModel + .isTab() + .observe( + this, + isTab -> + toolbar.setNavigationIcon( + isTab ? R.drawable.menu_drawer_icon : R.drawable.ic_back_arrow)); + + // Observe changes to the tab selected navigationViewModel .getCurrentTab() - .observe(this, tab -> navbar.setSelectedItemId(tab.getMenuId())); - navbar.setOnItemSelectedListener( + .observe( + this, + tab -> { + navigationViewModel.setIsTab(true); + navigationView.setCheckedItem(tab.getMenuId()); + }); + + navigationView.setNavigationItemSelectedListener( item -> { - T tab = findTabByMenu(item.getItemId()); + MainMenuTab tab = MainMenuTab.findByMenu(item.getItemId()); Log.i(TAG, "Opening tab : " + tab.getName()); boolean selected = openTab(tab); if (selected) { @@ -41,32 +79,41 @@ protected void setupNavigationBar(NavigationBarView navbar) { } else { Log.d(TAG, "The tab wasn't opened"); } + drawerLayout.close(); return selected; }); - // Set an empty reselect listener to disable the onSelectListener when pressing multiple times - navbar.setOnItemReselectedListener(item -> {}); - openDefaultTab(navbar); + // Update the name of the Lao in the drawer header when it changes + navigationViewModel + .getLaoName() + .observe(this, laoName -> setupHeaderLaoName(navigationView, laoName)); + + // Update the user's role in the drawer header when it changes + navigationViewModel.getRole().observe(this, role -> setupHeaderRole(navigationView, role)); } - private void openDefaultTab(NavigationBarView navbar) { - T defaultTab = getDefaultTab(); - navigationViewModel.setCurrentTab(defaultTab); + private void observeRoles() { + // Observe any change in the following variable to update the role + navigationViewModel.isOrganizer().observe(this, any -> navigationViewModel.updateRole()); + navigationViewModel.isWitness().observe(this, any -> navigationViewModel.updateRole()); + navigationViewModel.isAttendee().observe(this, any -> navigationViewModel.updateRole()); + } - // If the tab is already selected, the event will not be dispatched and we need to do it - // manually - if (defaultTab.getMenuId() == navbar.getSelectedItemId()) { - openTab(defaultTab); - } + private void setupHeaderLaoName(NavigationView navigationView, String laoName) { + TextView laoNameView = + navigationView + .getHeaderView(0) // We have only one header + .findViewById(R.id.drawer_header_lao_title); + laoNameView.setText(laoName); } - /** - * Returns a Tab instance given its menu id - * - * @param menuId of the tab - * @return the tab - */ - protected abstract T findTabByMenu(int menuId); + private void setupHeaderRole(NavigationView navigationView, Role role) { + TextView roleView = + navigationView + .getHeaderView(0) // We have only one header + .findViewById(R.id.drawer_header_role); + roleView.setText(role.getStringId()); + } /** * Open the provided tab @@ -74,10 +121,5 @@ private void openDefaultTab(NavigationBarView navbar) { * @param tab to pen * @return true if the tab was actually opened and the menu should be selected */ - protected abstract boolean openTab(T tab); - - /** - * @return the tab to open by default - */ - protected abstract T getDefaultTab(); + protected abstract boolean openTab(MainMenuTab tab); } diff --git a/fe2-android/app/src/main/java/com/github/dedis/popstellar/ui/navigation/NavigationViewModel.java b/fe2-android/app/src/main/java/com/github/dedis/popstellar/ui/navigation/NavigationViewModel.java index eb61d21422..f2f0bbdc5d 100644 --- a/fe2-android/app/src/main/java/com/github/dedis/popstellar/ui/navigation/NavigationViewModel.java +++ b/fe2-android/app/src/main/java/com/github/dedis/popstellar/ui/navigation/NavigationViewModel.java @@ -5,27 +5,111 @@ import androidx.annotation.NonNull; import androidx.lifecycle.*; +import com.github.dedis.popstellar.model.Role; + /** * Abstract view model that provides the components of the navigation bar * *

Any activity that uses a navigation bar should have its view model extends from the this * * class - * - * @param the type fo the Tab used */ -public abstract class NavigationViewModel extends AndroidViewModel { +public abstract class NavigationViewModel extends AndroidViewModel { + + private final MutableLiveData currentTab = new MutableLiveData<>(); + + private final MutableLiveData laoName = new MutableLiveData<>(); + + private final MutableLiveData isOrganizer = new MutableLiveData<>(Boolean.FALSE); - private final MutableLiveData currentTab = new MutableLiveData<>(); + private final MutableLiveData isWitness = new MutableLiveData<>(Boolean.FALSE); + + private final MutableLiveData isAttendee = new MutableLiveData<>(Boolean.FALSE); + + private final MutableLiveData role = new MutableLiveData<>(Role.MEMBER); + + private final MutableLiveData isTab = new MutableLiveData<>(Boolean.TRUE); protected NavigationViewModel(@NonNull Application application) { super(application); } - public LiveData getCurrentTab() { + public LiveData getCurrentTab() { return currentTab; } - public void setCurrentTab(T tab) { + public void setCurrentTab(MainMenuTab tab) { currentTab.postValue(tab); } + + public MutableLiveData getLaoName() { + return laoName; + } + + public void setLaoName(String laoName) { + this.laoName.setValue(laoName); + } + + public MutableLiveData isOrganizer() { + return isOrganizer; + } + + public MutableLiveData isWitness() { + return isWitness; + } + + public MutableLiveData isAttendee() { + return isAttendee; + } + + public MutableLiveData getRole() { + return role; + } + + public MutableLiveData isTab() { + return isTab; + } + + public void updateRole() { + Role role = determineRole(); + if (this.role.getValue() != role) { + this.role.setValue(role); + } + } + + public void setIsOrganizer(boolean isOrganizer) { + if (this.isOrganizer.getValue() != isOrganizer) { + this.isOrganizer.setValue(isOrganizer); + } + } + + public void setIsWitness(boolean isWitness) { + if (this.isWitness.getValue() != isWitness) { + this.isWitness.setValue(isWitness); + } + } + + public void setIsAttendee(boolean isAttendee) { + if (this.isAttendee.getValue() != isAttendee) { + this.isAttendee.setValue(isAttendee); + } + } + + public void setIsTab(boolean isTab) { + if (this.isTab.getValue() != isTab) { + this.isTab.setValue(isTab); + } + } + + private Role determineRole() { + if (isOrganizer.getValue()) { + return Role.ORGANIZER; + } + if (isWitness.getValue()) { + return Role.WITNESS; + } + if (isAttendee.getValue()) { + return Role.ATTENDEE; + } + return Role.MEMBER; + } } diff --git a/fe2-android/app/src/main/res/drawable/menu_drawer_icon.xml b/fe2-android/app/src/main/res/drawable/menu_drawer_icon.xml new file mode 100644 index 0000000000..fcc5a42f00 --- /dev/null +++ b/fe2-android/app/src/main/res/drawable/menu_drawer_icon.xml @@ -0,0 +1,15 @@ + + + + + diff --git a/fe2-android/app/src/main/res/layout/header_navigation_drawer.xml b/fe2-android/app/src/main/res/layout/header_navigation_drawer.xml new file mode 100644 index 0000000000..bda5375667 --- /dev/null +++ b/fe2-android/app/src/main/res/layout/header_navigation_drawer.xml @@ -0,0 +1,31 @@ + + + + + + + + + diff --git a/fe2-android/app/src/main/res/menu/main_menu.xml b/fe2-android/app/src/main/res/menu/main_menu.xml index e6590284aa..0bef3cd1c0 100644 --- a/fe2-android/app/src/main/res/menu/main_menu.xml +++ b/fe2-android/app/src/main/res/menu/main_menu.xml @@ -1,6 +1,6 @@

- + - + diff --git a/fe2-android/app/src/main/res/values/dimens.xml b/fe2-android/app/src/main/res/values/dimens.xml index a888d12774..c6dd7cbf62 100644 --- a/fe2-android/app/src/main/res/values/dimens.xml +++ b/fe2-android/app/src/main/res/values/dimens.xml @@ -169,4 +169,7 @@ 8dp 12dp 1dp + + + 16dp diff --git a/fe2-android/app/src/main/res/values/strings.xml b/fe2-android/app/src/main/res/values/strings.xml index add1097e31..6f7815354f 100644 --- a/fe2-android/app/src/main/res/values/strings.xml +++ b/fe2-android/app/src/main/res/values/strings.xml @@ -11,6 +11,7 @@ Organizer Attendee Witness + Member Identity From b1d25d4cb46680c39a28c0694a63d8409dc28ead Mon Sep 17 00:00:00 2001 From: Johann Pluss Date: Tue, 10 Jan 2023 00:47:56 +0100 Subject: [PATCH 07/41] Adapt LaoDetail MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Johann Plüss --- .../popstellar/ui/detail/InviteFragment.java | 12 +- .../ui/detail/LaoDetailActivity.java | 132 ++++--------- .../ui/detail/LaoDetailViewModel.java | 31 ++- .../WitnessMessageListViewAdapter.java | 11 +- .../main/res/layout/lao_detail_activity.xml | 183 ++++-------------- 5 files changed, 91 insertions(+), 278 deletions(-) diff --git a/fe2-android/app/src/main/java/com/github/dedis/popstellar/ui/detail/InviteFragment.java b/fe2-android/app/src/main/java/com/github/dedis/popstellar/ui/detail/InviteFragment.java index dbd858c154..48bf9ec93d 100644 --- a/fe2-android/app/src/main/java/com/github/dedis/popstellar/ui/detail/InviteFragment.java +++ b/fe2-android/app/src/main/java/com/github/dedis/popstellar/ui/detail/InviteFragment.java @@ -11,6 +11,7 @@ import com.github.dedis.popstellar.R; import com.github.dedis.popstellar.databinding.InviteFragmentBinding; import com.github.dedis.popstellar.model.qrcode.ConnectToLao; +import com.github.dedis.popstellar.repository.remote.GlobalNetworkManager; import com.google.gson.Gson; import net.glxn.qrgen.android.QRCode; @@ -23,6 +24,7 @@ public class InviteFragment extends Fragment { @Inject Gson gson; + @Inject GlobalNetworkManager networkManager; private static final int QR_SIDE = 800; @@ -42,7 +44,7 @@ public View onCreateView( viewModel = LaoDetailActivity.obtainViewModel(requireActivity()); binding.laoPropertiesIdentifierText.setText(viewModel.getPublicKey().getEncoded()); - binding.laoPropertiesServerText.setText(viewModel.getCurrentUrl()); + binding.laoPropertiesServerText.setText(networkManager.getCurrentUrl()); viewModel .getCurrentLao() @@ -50,14 +52,18 @@ public View onCreateView( requireActivity(), laoView -> { // Set the QR code - ConnectToLao data = new ConnectToLao(viewModel.getCurrentUrl(), laoView.getId()); + ConnectToLao data = new ConnectToLao(networkManager.getCurrentUrl(), laoView.getId()); Bitmap myBitmap = QRCode.from(gson.toJson(data)).withSize(QR_SIDE, QR_SIDE).bitmap(); binding.channelQrCode.setImageBitmap(myBitmap); binding.laoPropertiesNameText.setText(laoView.getName()); - // binding.laoPropertiesRoleText.setText(getRole()); }); + viewModel + .getRole() + .observe( + requireActivity(), role -> binding.laoPropertiesRoleText.setText(role.getStringId())); + return binding.getRoot(); } diff --git a/fe2-android/app/src/main/java/com/github/dedis/popstellar/ui/detail/LaoDetailActivity.java b/fe2-android/app/src/main/java/com/github/dedis/popstellar/ui/detail/LaoDetailActivity.java index 4613aadc2b..101a11e308 100644 --- a/fe2-android/app/src/main/java/com/github/dedis/popstellar/ui/detail/LaoDetailActivity.java +++ b/fe2-android/app/src/main/java/com/github/dedis/popstellar/ui/detail/LaoDetailActivity.java @@ -2,25 +2,23 @@ import android.content.Context; import android.content.Intent; -import android.graphics.Bitmap; import android.os.Bundle; import android.util.Log; -import android.view.View; import android.widget.Toast; -import androidx.annotation.*; +import androidx.annotation.IdRes; +import androidx.annotation.Nullable; import androidx.fragment.app.*; import androidx.lifecycle.ViewModelProvider; import com.github.dedis.popstellar.R; import com.github.dedis.popstellar.databinding.LaoDetailActivityBinding; import com.github.dedis.popstellar.model.objects.view.LaoView; -import com.github.dedis.popstellar.model.qrcode.ConnectToLao; import com.github.dedis.popstellar.repository.remote.GlobalNetworkManager; -import com.github.dedis.popstellar.ui.detail.event.LaoDetailAnimation; import com.github.dedis.popstellar.ui.detail.witness.WitnessingFragment; import com.github.dedis.popstellar.ui.digitalcash.DigitalCashActivity; import com.github.dedis.popstellar.ui.home.HomeActivity; +import com.github.dedis.popstellar.ui.navigation.MainMenuTab; import com.github.dedis.popstellar.ui.navigation.NavigationActivity; import com.github.dedis.popstellar.ui.socialmedia.SocialMediaActivity; import com.github.dedis.popstellar.ui.wallet.LaoWalletFragment; @@ -30,8 +28,6 @@ import com.github.dedis.popstellar.utility.error.UnknownLaoException; import com.google.gson.Gson; -import net.glxn.qrgen.android.QRCode; - import java.security.GeneralSecurityException; import java.util.Objects; import java.util.function.Supplier; @@ -41,13 +37,12 @@ import dagger.hilt.android.AndroidEntryPoint; @AndroidEntryPoint -public class LaoDetailActivity extends NavigationActivity { +public class LaoDetailActivity extends NavigationActivity { private static final String TAG = LaoDetailActivity.class.getSimpleName(); private LaoDetailViewModel viewModel; private LaoDetailActivityBinding binding; - private static final int QR_SIDE = 800; @Inject Gson gson; @Inject GlobalNetworkManager networkManager; @@ -58,10 +53,10 @@ protected void onCreate(@Nullable Bundle savedInstanceState) { binding = LaoDetailActivityBinding.inflate(getLayoutInflater()); setContentView(binding.getRoot()); navigationViewModel = viewModel = obtainViewModel(this); - - setupNavigationBar(findViewById(R.id.lao_detail_nav_bar)); + navigationViewModel.setCurrentTab(MainMenuTab.EVENTS); + setupDrawer( + binding.laoDetailNavigationDrawer, binding.laoTopAppBar, binding.laoDetailDrawerLayout); setupTopAppBar(); - setupProperties(); String laoId = Objects.requireNonNull(getIntent().getExtras()).getString(Constants.LAO_ID_EXTRA); @@ -74,6 +69,8 @@ protected void onCreate(@Nullable Bundle savedInstanceState) { .equals(Constants.LAO_DETAIL_EXTRA)) { setupLaoWalletFragment(); } + + openEventsTab(); } @Override @@ -92,107 +89,53 @@ public void onStop() { private void setupTopAppBar() { viewModel.getPageTitle().observe(this, binding.laoTopAppBar::setTitle); - binding.laoTopAppBar.setNavigationOnClickListener( - v -> { - Fragment fragment = - getSupportFragmentManager().findFragmentById(R.id.fragment_container_lao_detail); - if (fragment instanceof LaoDetailFragment) { - startActivity(HomeActivity.newIntent(this)); - } else { - if (viewModel.getCurrentTab().getValue() == LaoTab.EVENTS) { - // On reselection the navigation is supposed to do nothing to prevent loops, so we - // manually change the fragment - openEventsTab(); - } else { - viewModel.setCurrentTab(LaoTab.EVENTS); - } - } - }); - binding.laoTopAppBar.setOnMenuItemClickListener( - item -> { - if (item.getItemId() == R.id.lao_toolbar_qr_code) { - binding.laoDetailQrLayout.setVisibility(View.VISIBLE); - binding.laoDetailQrLayout.setAlpha(Constants.ENABLED_ALPHA); - binding.fragmentContainerLaoDetail.setAlpha(Constants.DISABLED_ALPHA); - binding.fragmentContainerLaoDetail.setEnabled(false); - return true; - } - return false; - }); - } - - private void setupProperties() { - binding.laoPropertiesIdentifierText.setText(viewModel.getPublicKey().getEncoded()); - binding.laoPropertiesServerText.setText(networkManager.getCurrentUrl()); - - viewModel - .getCurrentLao() - .observe( - this, - laoView -> { - // Set the QR code - ConnectToLao data = new ConnectToLao(networkManager.getCurrentUrl(), laoView.getId()); - Bitmap myBitmap = QRCode.from(gson.toJson(data)).withSize(QR_SIDE, QR_SIDE).bitmap(); - binding.channelQrCode.setImageBitmap(myBitmap); - - binding.laoPropertiesNameText.setText(laoView.getName()); - binding.laoPropertiesRoleText.setText(getRole()); - }); - - binding.qrIconClose.setOnClickListener( - v -> { - LaoDetailAnimation.fadeOut(binding.laoDetailQrLayout, 1.0f, 0.0f, 500); - binding.fragmentContainerLaoDetail.setAlpha(Constants.ENABLED_ALPHA); - binding.fragmentContainerLaoDetail.setEnabled(true); - }); - } - - @StringRes - private int getRole() { - if (Boolean.TRUE.equals(viewModel.isOrganizer().getValue())) { - return R.string.organizer; - } else { - try { - boolean isWitness = Boolean.TRUE.equals(viewModel.isWitness().getValue()); - return isWitness ? R.string.witness : R.string.attendee; - } catch (UnknownLaoException e) { - return 0; - } - } + // binding.laoTopAppBar.setOnMenuItemClickListener( + // item -> { + // if (item.getItemId() == R.id.lao_toolbar_qr_code) { + // binding.laoDetailQrLayout.setVisibility(View.VISIBLE); + // binding.laoDetailQrLayout.setAlpha(Constants.ENABLED_ALPHA); + // binding.fragmentContainerLaoDetail.setAlpha(Constants.DISABLED_ALPHA); + // binding.fragmentContainerLaoDetail.setEnabled(false); + // return true; + // } + // return false; + // }); } - @Override - protected LaoTab findTabByMenu(int menuId) { - return LaoTab.findByMenu(menuId); - } + // private void setupProperties() { @Override - protected boolean openTab(LaoTab tab) { + protected boolean openTab(MainMenuTab tab) { switch (tab) { + case INVITE: + openInviteTab(); + return true; case EVENTS: openEventsTab(); return true; - case IDENTITY: - openIdentityTab(); - return true; case WITNESSING: openWitnessTab(); return true; case DIGITAL_CASH: openDigitalCashTab(); return false; - case SOCIAL: + case SOCIAL_MEDIA: openSocialMediaTab(); return false; + case TOKENS: + return false; + case DISCONNECT: + startActivity(HomeActivity.newIntent(this)); + return false; default: Log.w(TAG, "Unhandled tab type : " + tab); return false; } } - @Override - protected LaoTab getDefaultTab() { - return LaoTab.EVENTS; + private void openInviteTab() { + setCurrentFragment( + getSupportFragmentManager(), R.id.fragment_invite, InviteFragment::newInstance); } private void openEventsTab() { @@ -200,13 +143,6 @@ private void openEventsTab() { getSupportFragmentManager(), R.id.fragment_lao_detail, LaoDetailFragment::newInstance); } - private void openIdentityTab() { - setCurrentFragment( - getSupportFragmentManager(), - R.id.fragment_identity, - () -> IdentityFragment.newInstance(viewModel.getPublicKey())); - } - private void openWitnessTab() { setCurrentFragment( getSupportFragmentManager(), R.id.fragment_witnessing, WitnessingFragment::newInstance); diff --git a/fe2-android/app/src/main/java/com/github/dedis/popstellar/ui/detail/LaoDetailViewModel.java b/fe2-android/app/src/main/java/com/github/dedis/popstellar/ui/detail/LaoDetailViewModel.java index 555b74d313..885e271e32 100644 --- a/fe2-android/app/src/main/java/com/github/dedis/popstellar/ui/detail/LaoDetailViewModel.java +++ b/fe2-android/app/src/main/java/com/github/dedis/popstellar/ui/detail/LaoDetailViewModel.java @@ -53,8 +53,7 @@ import io.reactivex.schedulers.Schedulers; @HiltViewModel -public class LaoDetailViewModel extends NavigationViewModel - implements QRCodeScanningViewModel { +public class LaoDetailViewModel extends NavigationViewModel implements QRCodeScanningViewModel { public static final String TAG = LaoDetailViewModel.class.getSimpleName(); private static final String LAO_FAILURE_MESSAGE = "failed to retrieve current lao"; @@ -73,7 +72,6 @@ public class LaoDetailViewModel extends NavigationViewModel */ private final MutableLiveData mCurrentLao = new MutableLiveData<>(); private final MutableLiveData mPageTitle = new MutableLiveData<>(); - private final MutableLiveData mIsOrganizer = new MutableLiveData<>(); private final MutableLiveData mIsWitness = new MutableLiveData<>(); private final MutableLiveData mIsSignedByCurrentWitness = new MutableLiveData<>(); private final MutableLiveData mNbAttendees = new MutableLiveData<>(); @@ -610,17 +608,6 @@ public void setPageTitle(String title) { mPageTitle.postValue(title); } - public LiveData isOrganizer() { - return mIsOrganizer; - } - - public LiveData isWitness() throws UnknownLaoException { - boolean isWitness = getLaoView().getWitnesses().contains(keyManager.getMainPublicKey()); - Log.d(TAG, "isWitness: " + isWitness); - mIsWitness.setValue(isWitness); - return mIsWitness; - } - public LiveData isSignedByCurrentWitness(Set witnesses) { boolean isSignedByCurrentWitness = witnesses.contains(keyManager.getMainPublicKey()); Log.d(TAG, "isSignedByCurrentWitness: " + isSignedByCurrentWitness); @@ -773,9 +760,13 @@ public void subscribeToLao(String laoId) { Log.d(TAG, "got an update for lao: " + laoView.getName()); mCurrentLao.postValue(laoView); + setLaoName(laoView.getName()); + boolean isOrganizer = laoView.getOrganizer().equals(keyManager.getMainPublicKey()); - mIsOrganizer.setValue(isOrganizer); + setIsOrganizer(isOrganizer); + setIsWitness(laoView.getWitnesses().contains(keyManager.getMainPublicKey())); + updateCurrentObjects(laoView); }, error -> Log.d(TAG, "error updating LAO :" + error))); @@ -804,10 +795,16 @@ public void subscribeToRollCalls(String laoId) { .collect(Collectors.toList()); mRollCalls.setValue(rollCallList); - mAttendedRollCalls.setValue( + + List attendedRollCall = rollCallList.stream() .filter(rollCall -> rollCall.isClosed() && attendedOrOrganized(rollCall)) - .collect(Collectors.toList())); + .collect(Collectors.toList()); + Log.d(TAG, "attended roll calls: " + attendedRollCall); + mAttendedRollCalls.setValue(attendedRollCall); + + setIsAttendee( + attendedRollCall.contains(rollCallRepo.getLastClosedRollCall(laoId))); }, error -> Log.d(TAG, "Error updating Roll Call : " + error))); } diff --git a/fe2-android/app/src/main/java/com/github/dedis/popstellar/ui/detail/witness/WitnessMessageListViewAdapter.java b/fe2-android/app/src/main/java/com/github/dedis/popstellar/ui/detail/witness/WitnessMessageListViewAdapter.java index 07d05ea6c1..23cb113882 100644 --- a/fe2-android/app/src/main/java/com/github/dedis/popstellar/ui/detail/witness/WitnessMessageListViewAdapter.java +++ b/fe2-android/app/src/main/java/com/github/dedis/popstellar/ui/detail/witness/WitnessMessageListViewAdapter.java @@ -13,7 +13,6 @@ import com.github.dedis.popstellar.model.objects.WitnessMessage; import com.github.dedis.popstellar.ui.detail.LaoDetailViewModel; import com.github.dedis.popstellar.utility.error.ErrorUtils; -import com.github.dedis.popstellar.utility.error.UnknownLaoException; import java.util.List; @@ -80,17 +79,9 @@ public View getView(int position, View convertView, ViewGroup parent) { Context context = parent.getContext(); View.OnClickListener listener = v -> { - boolean isWitness; - try { - isWitness = viewModel.isWitness().getValue(); - } catch (UnknownLaoException e) { - ErrorUtils.logAndShow(context, TAG, R.string.error_no_lao); - return; - } - AlertDialog.Builder adb = new AlertDialog.Builder(context); - if (isWitness) { + if (viewModel.isWitness().getValue()) { adb.setTitle("Sign Message"); adb.setMessage( " Are you sure you want to sign message with ID : " diff --git a/fe2-android/app/src/main/res/layout/lao_detail_activity.xml b/fe2-android/app/src/main/res/layout/lao_detail_activity.xml index 18bff7db4f..f4f45bd8d1 100644 --- a/fe2-android/app/src/main/res/layout/lao_detail_activity.xml +++ b/fe2-android/app/src/main/res/layout/lao_detail_activity.xml @@ -1,170 +1,53 @@ + xmlns:app="http://schemas.android.com/apk/res-auto" + xmlns:tools="http://schemas.android.com/tools"> - + android:layout_height="match_parent" + tools:openDrawer="start"> - + android:layout_height="match_parent" + android:fitsSystemWindows="true"> - - + android:layout_height="wrap_content" + style="@style/Widget.MaterialComponents.AppBarLayout.Primary" + android:fitsSystemWindows="true"> - - - - - + + - - - - - - - - - - - - - - - - - - - + app:layout_behavior="@string/appbar_scrolling_view_behavior" /> - + - + - + - - - - From 29e0dad82c144ce76f46a2647306e03578cf5910 Mon Sep 17 00:00:00 2001 From: Johann Pluss Date: Tue, 10 Jan 2023 00:55:16 +0100 Subject: [PATCH 08/41] Delete commented out code MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Johann Plüss --- .../popstellar/ui/detail/LaoDetailActivity.java | 13 ------------- 1 file changed, 13 deletions(-) diff --git a/fe2-android/app/src/main/java/com/github/dedis/popstellar/ui/detail/LaoDetailActivity.java b/fe2-android/app/src/main/java/com/github/dedis/popstellar/ui/detail/LaoDetailActivity.java index 101a11e308..8c987568d5 100644 --- a/fe2-android/app/src/main/java/com/github/dedis/popstellar/ui/detail/LaoDetailActivity.java +++ b/fe2-android/app/src/main/java/com/github/dedis/popstellar/ui/detail/LaoDetailActivity.java @@ -89,21 +89,8 @@ public void onStop() { private void setupTopAppBar() { viewModel.getPageTitle().observe(this, binding.laoTopAppBar::setTitle); - // binding.laoTopAppBar.setOnMenuItemClickListener( - // item -> { - // if (item.getItemId() == R.id.lao_toolbar_qr_code) { - // binding.laoDetailQrLayout.setVisibility(View.VISIBLE); - // binding.laoDetailQrLayout.setAlpha(Constants.ENABLED_ALPHA); - // binding.fragmentContainerLaoDetail.setAlpha(Constants.DISABLED_ALPHA); - // binding.fragmentContainerLaoDetail.setEnabled(false); - // return true; - // } - // return false; - // }); } - // private void setupProperties() { - @Override protected boolean openTab(MainMenuTab tab) { switch (tab) { From 5871199e01e83b7853fd2ae698e47420dd2fd053 Mon Sep 17 00:00:00 2001 From: Johann Pluss Date: Tue, 10 Jan 2023 01:06:05 +0100 Subject: [PATCH 09/41] Make the toolbar title listening part of the abstract activity MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Johann Plüss --- .../popstellar/ui/detail/IdentityFragment.java | 2 +- .../popstellar/ui/detail/InviteFragment.java | 2 +- .../popstellar/ui/detail/LaoDetailActivity.java | 6 ------ .../popstellar/ui/detail/LaoDetailFragment.java | 7 +------ .../popstellar/ui/detail/LaoDetailViewModel.java | 10 ---------- .../election/fragments/CastVoteFragment.java | 2 +- .../election/fragments/ElectionFragment.java | 2 +- .../fragments/ElectionResultFragment.java | 2 +- .../fragments/ElectionSetupFragment.java | 2 +- .../event/rollcall/RollCallCreationFragment.java | 16 +++++++--------- .../detail/event/rollcall/RollCallFragment.java | 2 +- .../ui/detail/witness/WitnessingFragment.java | 2 +- .../ui/navigation/NavigationActivity.java | 3 +++ .../ui/navigation/NavigationViewModel.java | 13 +++++++++++++ .../ui/qrcode/QRCodeScanningFragment.java | 4 ++-- 15 files changed, 34 insertions(+), 41 deletions(-) diff --git a/fe2-android/app/src/main/java/com/github/dedis/popstellar/ui/detail/IdentityFragment.java b/fe2-android/app/src/main/java/com/github/dedis/popstellar/ui/detail/IdentityFragment.java index bfe49b324e..1b29073c51 100644 --- a/fe2-android/app/src/main/java/com/github/dedis/popstellar/ui/detail/IdentityFragment.java +++ b/fe2-android/app/src/main/java/com/github/dedis/popstellar/ui/detail/IdentityFragment.java @@ -98,7 +98,7 @@ public View onCreateView( public void onResume() { super.onResume(); LaoDetailViewModel viewModel = LaoDetailActivity.obtainViewModel(requireActivity()); - viewModel.setPageTitle(getString(R.string.tab_identity)); + viewModel.setPageTitle(R.string.tab_identity); } /** Hide fields when user wants to be anonymous */ diff --git a/fe2-android/app/src/main/java/com/github/dedis/popstellar/ui/detail/InviteFragment.java b/fe2-android/app/src/main/java/com/github/dedis/popstellar/ui/detail/InviteFragment.java index 48bf9ec93d..9fc491753e 100644 --- a/fe2-android/app/src/main/java/com/github/dedis/popstellar/ui/detail/InviteFragment.java +++ b/fe2-android/app/src/main/java/com/github/dedis/popstellar/ui/detail/InviteFragment.java @@ -70,6 +70,6 @@ public View onCreateView( @Override public void onResume() { super.onResume(); - viewModel.setPageTitle(getString(R.string.invite)); + viewModel.setPageTitle(R.string.invite); } } diff --git a/fe2-android/app/src/main/java/com/github/dedis/popstellar/ui/detail/LaoDetailActivity.java b/fe2-android/app/src/main/java/com/github/dedis/popstellar/ui/detail/LaoDetailActivity.java index 8c987568d5..7006f56dd3 100644 --- a/fe2-android/app/src/main/java/com/github/dedis/popstellar/ui/detail/LaoDetailActivity.java +++ b/fe2-android/app/src/main/java/com/github/dedis/popstellar/ui/detail/LaoDetailActivity.java @@ -56,7 +56,6 @@ protected void onCreate(@Nullable Bundle savedInstanceState) { navigationViewModel.setCurrentTab(MainMenuTab.EVENTS); setupDrawer( binding.laoDetailNavigationDrawer, binding.laoTopAppBar, binding.laoDetailDrawerLayout); - setupTopAppBar(); String laoId = Objects.requireNonNull(getIntent().getExtras()).getString(Constants.LAO_ID_EXTRA); @@ -86,11 +85,6 @@ public void onStop() { } } - private void setupTopAppBar() { - viewModel.getPageTitle().observe(this, binding.laoTopAppBar::setTitle); - - } - @Override protected boolean openTab(MainMenuTab tab) { switch (tab) { diff --git a/fe2-android/app/src/main/java/com/github/dedis/popstellar/ui/detail/LaoDetailFragment.java b/fe2-android/app/src/main/java/com/github/dedis/popstellar/ui/detail/LaoDetailFragment.java index 69bcf1c3c5..749323c26b 100644 --- a/fe2-android/app/src/main/java/com/github/dedis/popstellar/ui/detail/LaoDetailFragment.java +++ b/fe2-android/app/src/main/java/com/github/dedis/popstellar/ui/detail/LaoDetailFragment.java @@ -17,7 +17,6 @@ import com.github.dedis.popstellar.ui.detail.event.*; import com.github.dedis.popstellar.ui.detail.event.election.fragments.ElectionSetupFragment; import com.github.dedis.popstellar.ui.detail.event.rollcall.RollCallCreationFragment; -import com.github.dedis.popstellar.utility.error.UnknownLaoException; import com.google.android.material.floatingactionbutton.FloatingActionButton; import com.google.gson.Gson; @@ -117,11 +116,7 @@ public void onViewCreated(@NonNull View view, @Nullable Bundle savedInstanceStat @Override public void onResume() { super.onResume(); - try { - viewModel.setPageTitle(viewModel.getLaoView().getName()); - } catch (UnknownLaoException e) { - Log.d(TAG, "Lao name could not be retrieved"); - } + viewModel.setPageTitle(R.string.event_list); } private void setupEventListAdapter() { diff --git a/fe2-android/app/src/main/java/com/github/dedis/popstellar/ui/detail/LaoDetailViewModel.java b/fe2-android/app/src/main/java/com/github/dedis/popstellar/ui/detail/LaoDetailViewModel.java index 885e271e32..4ba7363f86 100644 --- a/fe2-android/app/src/main/java/com/github/dedis/popstellar/ui/detail/LaoDetailViewModel.java +++ b/fe2-android/app/src/main/java/com/github/dedis/popstellar/ui/detail/LaoDetailViewModel.java @@ -71,8 +71,6 @@ public class LaoDetailViewModel extends NavigationViewModel implements QRCodeSca * LiveData objects that represent the state in a fragment */ private final MutableLiveData mCurrentLao = new MutableLiveData<>(); - private final MutableLiveData mPageTitle = new MutableLiveData<>(); - private final MutableLiveData mIsWitness = new MutableLiveData<>(); private final MutableLiveData mIsSignedByCurrentWitness = new MutableLiveData<>(); private final MutableLiveData mNbAttendees = new MutableLiveData<>(); private final MutableLiveData showProperties = new MutableLiveData<>(false); @@ -600,14 +598,6 @@ public LiveData getCurrentLaoName() { return mCurrentLaoName; } - public MutableLiveData getPageTitle() { - return mPageTitle; - } - - public void setPageTitle(String title) { - mPageTitle.postValue(title); - } - public LiveData isSignedByCurrentWitness(Set witnesses) { boolean isSignedByCurrentWitness = witnesses.contains(keyManager.getMainPublicKey()); Log.d(TAG, "isSignedByCurrentWitness: " + isSignedByCurrentWitness); diff --git a/fe2-android/app/src/main/java/com/github/dedis/popstellar/ui/detail/event/election/fragments/CastVoteFragment.java b/fe2-android/app/src/main/java/com/github/dedis/popstellar/ui/detail/event/election/fragments/CastVoteFragment.java index 74268d85b8..340c330ea7 100644 --- a/fe2-android/app/src/main/java/com/github/dedis/popstellar/ui/detail/event/election/fragments/CastVoteFragment.java +++ b/fe2-android/app/src/main/java/com/github/dedis/popstellar/ui/detail/event/election/fragments/CastVoteFragment.java @@ -150,7 +150,7 @@ public View onCreateView( @Override public void onResume() { super.onResume(); - viewModel.setPageTitle(getString(R.string.vote)); + viewModel.setPageTitle(R.string.vote); } private List setEmptyVoteList() { diff --git a/fe2-android/app/src/main/java/com/github/dedis/popstellar/ui/detail/event/election/fragments/ElectionFragment.java b/fe2-android/app/src/main/java/com/github/dedis/popstellar/ui/detail/event/election/fragments/ElectionFragment.java index 3ff19983cb..448012345e 100644 --- a/fe2-android/app/src/main/java/com/github/dedis/popstellar/ui/detail/event/election/fragments/ElectionFragment.java +++ b/fe2-android/app/src/main/java/com/github/dedis/popstellar/ui/detail/event/election/fragments/ElectionFragment.java @@ -165,7 +165,7 @@ public View onCreateView( @Override public void onResume() { super.onResume(); - viewModel.setPageTitle(getString(R.string.election_title)); + viewModel.setPageTitle(R.string.election_title); } private void setupElectionContent() { diff --git a/fe2-android/app/src/main/java/com/github/dedis/popstellar/ui/detail/event/election/fragments/ElectionResultFragment.java b/fe2-android/app/src/main/java/com/github/dedis/popstellar/ui/detail/event/election/fragments/ElectionResultFragment.java index e5118e8d8e..769a40b392 100644 --- a/fe2-android/app/src/main/java/com/github/dedis/popstellar/ui/detail/event/election/fragments/ElectionResultFragment.java +++ b/fe2-android/app/src/main/java/com/github/dedis/popstellar/ui/detail/event/election/fragments/ElectionResultFragment.java @@ -83,6 +83,6 @@ public View onCreateView( public void onResume() { super.onResume(); LaoDetailViewModel viewModel = LaoDetailActivity.obtainViewModel(requireActivity()); - viewModel.setPageTitle(getString(R.string.election_result_title)); + viewModel.setPageTitle(R.string.election_result_title); } } diff --git a/fe2-android/app/src/main/java/com/github/dedis/popstellar/ui/detail/event/election/fragments/ElectionSetupFragment.java b/fe2-android/app/src/main/java/com/github/dedis/popstellar/ui/detail/event/election/fragments/ElectionSetupFragment.java index 9391796f6f..fce99b8b4d 100644 --- a/fe2-android/app/src/main/java/com/github/dedis/popstellar/ui/detail/event/election/fragments/ElectionSetupFragment.java +++ b/fe2-android/app/src/main/java/com/github/dedis/popstellar/ui/detail/event/election/fragments/ElectionSetupFragment.java @@ -184,7 +184,7 @@ public void onViewCreated(@NonNull View view, @Nullable Bundle savedInstanceStat @Override public void onResume() { super.onResume(); - viewModel.setPageTitle(getString(R.string.election_setup_title)); + viewModel.setPageTitle(R.string.election_setup_title); } /** Setups the submit button that creates the new election */ diff --git a/fe2-android/app/src/main/java/com/github/dedis/popstellar/ui/detail/event/rollcall/RollCallCreationFragment.java b/fe2-android/app/src/main/java/com/github/dedis/popstellar/ui/detail/event/rollcall/RollCallCreationFragment.java index 12f537e310..05ca724f07 100644 --- a/fe2-android/app/src/main/java/com/github/dedis/popstellar/ui/detail/event/rollcall/RollCallCreationFragment.java +++ b/fe2-android/app/src/main/java/com/github/dedis/popstellar/ui/detail/event/rollcall/RollCallCreationFragment.java @@ -104,7 +104,7 @@ public void onViewCreated(@NonNull View view, @Nullable Bundle savedInstanceStat @Override public void onResume() { super.onResume(); - viewModel.setPageTitle(getString(R.string.roll_call_setup_title)); + viewModel.setPageTitle(R.string.roll_call_setup_title); } private void setupConfirmButton() { @@ -145,7 +145,7 @@ private void createRollCall(boolean open) { getParentFragmentManager(), R.id.add_attendee_layout, QRCodeScanningFragment::new); - viewModel.setPageTitle(getString(R.string.add_attendee_title)); + viewModel.setPageTitle(R.string.add_attendee_title); }, error -> ErrorUtils.logAndShow( @@ -153,13 +153,11 @@ private void createRollCall(boolean open) { } else { viewModel.addDisposable( createRollCall.subscribe( - id -> { - setCurrentFragment( - getParentFragmentManager(), - R.id.fragment_lao_detail, - LaoDetailFragment::newInstance); - viewModel.setPageTitle(viewModel.getLaoView().getName()); - }, + id -> + setCurrentFragment( + getParentFragmentManager(), + R.id.fragment_lao_detail, + LaoDetailFragment::newInstance), error -> ErrorUtils.logAndShow( requireContext(), TAG, error, R.string.error_create_rollcall))); diff --git a/fe2-android/app/src/main/java/com/github/dedis/popstellar/ui/detail/event/rollcall/RollCallFragment.java b/fe2-android/app/src/main/java/com/github/dedis/popstellar/ui/detail/event/rollcall/RollCallFragment.java index e79d493cfe..6d15a79b39 100644 --- a/fe2-android/app/src/main/java/com/github/dedis/popstellar/ui/detail/event/rollcall/RollCallFragment.java +++ b/fe2-android/app/src/main/java/com/github/dedis/popstellar/ui/detail/event/rollcall/RollCallFragment.java @@ -155,7 +155,7 @@ public View onCreateView( @Override public void onResume() { super.onResume(); - viewModel.setPageTitle(getString(R.string.roll_call_title)); + viewModel.setPageTitle(R.string.roll_call_title); try { rollCall = viewModel.getRollCall(requireArguments().getString(ROLL_CALL_ID)); } catch (UnknownRollCallException e) { diff --git a/fe2-android/app/src/main/java/com/github/dedis/popstellar/ui/detail/witness/WitnessingFragment.java b/fe2-android/app/src/main/java/com/github/dedis/popstellar/ui/detail/witness/WitnessingFragment.java index 321a6fb3dd..26b3faa11c 100644 --- a/fe2-android/app/src/main/java/com/github/dedis/popstellar/ui/detail/witness/WitnessingFragment.java +++ b/fe2-android/app/src/main/java/com/github/dedis/popstellar/ui/detail/witness/WitnessingFragment.java @@ -46,6 +46,6 @@ public View onCreateView( public void onResume() { super.onResume(); LaoDetailViewModel viewModel = LaoDetailActivity.obtainViewModel(requireActivity()); - viewModel.setPageTitle(getString(R.string.witnessing)); + viewModel.setPageTitle(R.string.witnessing); } } diff --git a/fe2-android/app/src/main/java/com/github/dedis/popstellar/ui/navigation/NavigationActivity.java b/fe2-android/app/src/main/java/com/github/dedis/popstellar/ui/navigation/NavigationActivity.java index 8eb3c1cb44..102084238b 100644 --- a/fe2-android/app/src/main/java/com/github/dedis/popstellar/ui/navigation/NavigationActivity.java +++ b/fe2-android/app/src/main/java/com/github/dedis/popstellar/ui/navigation/NavigationActivity.java @@ -90,6 +90,9 @@ protected void setupDrawer( // Update the user's role in the drawer header when it changes navigationViewModel.getRole().observe(this, role -> setupHeaderRole(navigationView, role)); + + // Observe the toolbar title to display + navigationViewModel.getPageTitle().observe(this, toolbar::setTitle); } private void observeRoles() { diff --git a/fe2-android/app/src/main/java/com/github/dedis/popstellar/ui/navigation/NavigationViewModel.java b/fe2-android/app/src/main/java/com/github/dedis/popstellar/ui/navigation/NavigationViewModel.java index f2f0bbdc5d..c703c7186e 100644 --- a/fe2-android/app/src/main/java/com/github/dedis/popstellar/ui/navigation/NavigationViewModel.java +++ b/fe2-android/app/src/main/java/com/github/dedis/popstellar/ui/navigation/NavigationViewModel.java @@ -3,6 +3,7 @@ import android.app.Application; import androidx.annotation.NonNull; +import androidx.annotation.StringRes; import androidx.lifecycle.*; import com.github.dedis.popstellar.model.Role; @@ -29,6 +30,8 @@ public abstract class NavigationViewModel extends AndroidViewModel { private final MutableLiveData isTab = new MutableLiveData<>(Boolean.TRUE); + private final MutableLiveData pageTitle = new MutableLiveData<>(0); + protected NavigationViewModel(@NonNull Application application) { super(application); } @@ -69,6 +72,10 @@ public MutableLiveData isTab() { return isTab; } + public MutableLiveData getPageTitle() { + return pageTitle; + } + public void updateRole() { Role role = determineRole(); if (this.role.getValue() != role) { @@ -100,6 +107,12 @@ public void setIsTab(boolean isTab) { } } + public void setPageTitle(@StringRes Integer pageTitle) { + if (!this.pageTitle.getValue().equals(pageTitle)) { + this.pageTitle.setValue(pageTitle); + } + } + private Role determineRole() { if (isOrganizer.getValue()) { return Role.ORGANIZER; diff --git a/fe2-android/app/src/main/java/com/github/dedis/popstellar/ui/qrcode/QRCodeScanningFragment.java b/fe2-android/app/src/main/java/com/github/dedis/popstellar/ui/qrcode/QRCodeScanningFragment.java index e77ab7ea4c..c8b0b59182 100644 --- a/fe2-android/app/src/main/java/com/github/dedis/popstellar/ui/qrcode/QRCodeScanningFragment.java +++ b/fe2-android/app/src/main/java/com/github/dedis/popstellar/ui/qrcode/QRCodeScanningFragment.java @@ -103,7 +103,7 @@ public View onCreateView( binding.addAttendeeConfirm.setVisibility(View.VISIBLE); LaoDetailViewModel laoDetailViewModel = (LaoDetailViewModel) viewModel; - laoDetailViewModel.setPageTitle(getString(R.string.add_attendee_title)); + laoDetailViewModel.setPageTitle(R.string.add_attendee_title); // Subscribe to " Nb of attendees" event observeNbAttendeesEvent(); @@ -117,7 +117,7 @@ public View onCreateView( if (viewModel.getScanningAction() == ScanningAction.ADD_WITNESS) { LaoDetailViewModel laoDetailViewModel = (LaoDetailViewModel) viewModel; - laoDetailViewModel.setPageTitle(getString(R.string.add_witness_description)); + laoDetailViewModel.setPageTitle(R.string.add_witness_description); // Subscribe to " Witness scan confirm " event observeWitnessScanConfirmEvent(); From d7aa7567ab1560d54673c66fe84a24f82d8115f2 Mon Sep 17 00:00:00 2001 From: Johann Pluss Date: Tue, 10 Jan 2023 14:22:36 +0100 Subject: [PATCH 10/41] Handle drawer navigation in LaoDetailActivity MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Johann Plüss --- .../popstellar/ui/detail/LaoDetailActivity.java | 14 ++++++++++++-- .../ui/detail/witness/WitnessListAdapter.java | 11 ++++++++--- 2 files changed, 20 insertions(+), 5 deletions(-) diff --git a/fe2-android/app/src/main/java/com/github/dedis/popstellar/ui/detail/LaoDetailActivity.java b/fe2-android/app/src/main/java/com/github/dedis/popstellar/ui/detail/LaoDetailActivity.java index 7006f56dd3..6d81a9ce83 100644 --- a/fe2-android/app/src/main/java/com/github/dedis/popstellar/ui/detail/LaoDetailActivity.java +++ b/fe2-android/app/src/main/java/com/github/dedis/popstellar/ui/detail/LaoDetailActivity.java @@ -53,7 +53,6 @@ protected void onCreate(@Nullable Bundle savedInstanceState) { binding = LaoDetailActivityBinding.inflate(getLayoutInflater()); setContentView(binding.getRoot()); navigationViewModel = viewModel = obtainViewModel(this); - navigationViewModel.setCurrentTab(MainMenuTab.EVENTS); setupDrawer( binding.laoDetailNavigationDrawer, binding.laoTopAppBar, binding.laoDetailDrawerLayout); @@ -69,7 +68,12 @@ protected void onCreate(@Nullable Bundle savedInstanceState) { setupLaoWalletFragment(); } - openEventsTab(); + MainMenuTab tab = (MainMenuTab) getIntent().getExtras().get(Constants.TAB_EXTRA); + if (tab == null) { + tab = MainMenuTab.EVENTS; + } + navigationViewModel.setCurrentTab(tab); + openTab(tab); } @Override @@ -170,6 +174,12 @@ public static Intent newIntentForLao(Context ctx, String laoId) { return intent; } + public static Intent newIntentWithTab(Context ctx, String laoId, MainMenuTab tab) { + Intent intent = LaoDetailActivity.newIntentForLao(ctx, laoId); + intent.putExtra(Constants.TAB_EXTRA, tab); + return intent; + } + public static Intent newIntentForWallet(Context ctx, String laoId) { Intent intent = new Intent(ctx, LaoDetailActivity.class); intent.putExtra(Constants.LAO_ID_EXTRA, laoId); diff --git a/fe2-android/app/src/main/java/com/github/dedis/popstellar/ui/detail/witness/WitnessListAdapter.java b/fe2-android/app/src/main/java/com/github/dedis/popstellar/ui/detail/witness/WitnessListAdapter.java index de8d3682a7..c7e2f3afde 100644 --- a/fe2-android/app/src/main/java/com/github/dedis/popstellar/ui/detail/witness/WitnessListAdapter.java +++ b/fe2-android/app/src/main/java/com/github/dedis/popstellar/ui/detail/witness/WitnessListAdapter.java @@ -1,5 +1,6 @@ package com.github.dedis.popstellar.ui.detail.witness; +import android.annotation.SuppressLint; import android.view.*; import android.widget.TextView; @@ -9,12 +10,13 @@ import com.github.dedis.popstellar.R; import com.github.dedis.popstellar.model.objects.security.PublicKey; +import java.util.ArrayList; import java.util.List; /** Adapter to show witnesses of an Event */ public class WitnessListAdapter extends RecyclerView.Adapter { - private List witnesses; + private List witnesses = new ArrayList<>(); public WitnessListAdapter(List witness) { setList(witness); @@ -24,9 +26,12 @@ public void replaceList(List witnesses) { setList(witnesses); } + @SuppressLint("NotifyDataSetChanged") private void setList(List witnesses) { - this.witnesses = witnesses; - notifyDataSetChanged(); + if (witnesses != null) { + this.witnesses = witnesses; + notifyDataSetChanged(); + } } @NonNull From 0c826cda6072e71a341bbc92dbd406817f56d946 Mon Sep 17 00:00:00 2001 From: Johann Pluss Date: Tue, 10 Jan 2023 14:24:28 +0100 Subject: [PATCH 11/41] Small fixes in navigation parent class MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Johann Plüss --- .../popstellar/ui/navigation/NavigationActivity.java | 10 +++++++++- .../popstellar/ui/navigation/NavigationViewModel.java | 2 +- 2 files changed, 10 insertions(+), 2 deletions(-) diff --git a/fe2-android/app/src/main/java/com/github/dedis/popstellar/ui/navigation/NavigationActivity.java b/fe2-android/app/src/main/java/com/github/dedis/popstellar/ui/navigation/NavigationActivity.java index 102084238b..d9e4f8696a 100644 --- a/fe2-android/app/src/main/java/com/github/dedis/popstellar/ui/navigation/NavigationActivity.java +++ b/fe2-android/app/src/main/java/com/github/dedis/popstellar/ui/navigation/NavigationActivity.java @@ -92,7 +92,15 @@ protected void setupDrawer( navigationViewModel.getRole().observe(this, role -> setupHeaderRole(navigationView, role)); // Observe the toolbar title to display - navigationViewModel.getPageTitle().observe(this, toolbar::setTitle); + navigationViewModel + .getPageTitle() + .observe( + this, + resId -> { + if (resId != 0) { + toolbar.setTitle(resId); + } + }); } private void observeRoles() { diff --git a/fe2-android/app/src/main/java/com/github/dedis/popstellar/ui/navigation/NavigationViewModel.java b/fe2-android/app/src/main/java/com/github/dedis/popstellar/ui/navigation/NavigationViewModel.java index c703c7186e..c633b8b07a 100644 --- a/fe2-android/app/src/main/java/com/github/dedis/popstellar/ui/navigation/NavigationViewModel.java +++ b/fe2-android/app/src/main/java/com/github/dedis/popstellar/ui/navigation/NavigationViewModel.java @@ -41,7 +41,7 @@ public LiveData getCurrentTab() { } public void setCurrentTab(MainMenuTab tab) { - currentTab.postValue(tab); + currentTab.setValue(tab); } public MutableLiveData getLaoName() { From 6e20d38806f70ac9858001d8f228fb5b8e18187f Mon Sep 17 00:00:00 2001 From: Johann Pluss Date: Tue, 10 Jan 2023 14:28:49 +0100 Subject: [PATCH 12/41] Adapt DigitalCashActivity to drawer MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Johann Plüss --- .../ui/digitalcash/DigitalCashActivity.java | 118 ++++++++++++------ .../digitalcash/DigitalCashIssueFragment.java | 2 +- .../digitalcash/DigitalCashSendFragment.java | 2 +- .../ui/digitalcash/DigitalCashViewModel.java | 22 ++-- .../res/layout/digital_cash_main_activity.xml | 84 ++++++++----- 5 files changed, 150 insertions(+), 78 deletions(-) diff --git a/fe2-android/app/src/main/java/com/github/dedis/popstellar/ui/digitalcash/DigitalCashActivity.java b/fe2-android/app/src/main/java/com/github/dedis/popstellar/ui/digitalcash/DigitalCashActivity.java index 45bd682aa4..5629880e56 100644 --- a/fe2-android/app/src/main/java/com/github/dedis/popstellar/ui/digitalcash/DigitalCashActivity.java +++ b/fe2-android/app/src/main/java/com/github/dedis/popstellar/ui/digitalcash/DigitalCashActivity.java @@ -13,8 +13,12 @@ import com.github.dedis.popstellar.R; import com.github.dedis.popstellar.databinding.DigitalCashMainActivityBinding; import com.github.dedis.popstellar.model.objects.security.PublicKey; +import com.github.dedis.popstellar.model.objects.view.LaoView; import com.github.dedis.popstellar.ui.detail.LaoDetailActivity; +import com.github.dedis.popstellar.ui.home.HomeActivity; +import com.github.dedis.popstellar.ui.navigation.MainMenuTab; import com.github.dedis.popstellar.ui.navigation.NavigationActivity; +import com.github.dedis.popstellar.ui.socialmedia.SocialMediaActivity; import com.github.dedis.popstellar.utility.ActivityUtils; import com.github.dedis.popstellar.utility.Constants; import com.github.dedis.popstellar.utility.error.ErrorUtils; @@ -27,7 +31,7 @@ /** Activity for the digital cash */ @AndroidEntryPoint -public class DigitalCashActivity extends NavigationActivity { +public class DigitalCashActivity extends NavigationActivity { private DigitalCashViewModel viewModel; private DigitalCashMainActivityBinding binding; public static final String TAG = DigitalCashActivity.class.getSimpleName(); @@ -38,8 +42,14 @@ protected void onCreate(Bundle savedInstanceState) { binding = DigitalCashMainActivityBinding.inflate(getLayoutInflater()); setContentView(binding.getRoot()); navigationViewModel = viewModel = obtainViewModel(this); - setupNavigationBar(findViewById(R.id.digital_cash_nav_bar)); - setupTopAppBar(); + + navigationViewModel.setCurrentTab(MainMenuTab.DIGITAL_CASH); + setupDrawer( + binding.digitalCashNavigationDrawer, + binding.digitalCashAppBar, + binding.digitalCashDrawerLayout); + setupBottomNavBar(); + openHomeTab(); loadIntentData(); } @@ -66,47 +76,73 @@ public void loadIntentData() { } } - public void openLao() { - startActivity( - LaoDetailActivity.newIntentForLao( - this, Objects.requireNonNull(viewModel.getCurrentLao().getValue()).getId())); - } - public static DigitalCashViewModel obtainViewModel(FragmentActivity activity) { return new ViewModelProvider(activity).get(DigitalCashViewModel.class); } - @Override - protected DigitalCashTab findTabByMenu(int menuId) { - return DigitalCashTab.findByMenu(menuId); + private void setupBottomNavBar() { + viewModel + .getBottomNavigationTab() + .observe(this, tab -> binding.digitalCashNavBar.setSelectedItemId(tab.getMenuId())); + + binding.digitalCashNavBar.setOnItemSelectedListener( + item -> { + DigitalCashTab tab = DigitalCashTab.findByMenu(item.getItemId()); + Log.i(TAG, "Opening tab : " + tab.getName()); + openBottomTab(tab); + return true; + }); + binding.digitalCashNavBar.setOnItemReselectedListener(item -> {}); + viewModel.setBottomNavigationTab(DigitalCashTab.HOME); } - @Override - protected boolean openTab(DigitalCashTab tab) { + private void openBottomTab(DigitalCashTab tab) { switch (tab) { case HOME: openHomeTab(); - break; + return; case HISTORY: openHistoryTab(); - break; + return; case SEND: openSendTab(); - break; + return; case RECEIVE: openReceiveTab(); - break; + return; case ISSUE: - return openIssueTab(); - default: - Log.w(TAG, "Unhandled tab type : " + tab); + openIssueTab(); } - return true; } @Override - protected DigitalCashTab getDefaultTab() { - return DigitalCashTab.HOME; + protected boolean openTab(MainMenuTab tab) { + Log.d(TAG, "opening drawer tab: " + tab); + switch (tab) { + case INVITE: + openInviteTab(); + return false; + case EVENTS: + openEventsTab(); + return false; + case SOCIAL_MEDIA: + openSocialMediaTab(); + return false; + case DIGITAL_CASH: + return false; + case WITNESSING: + openWitnessingTab(); + return false; + case TOKENS: + openTokensTab(); + return false; + case DISCONNECT: + startActivity(HomeActivity.newIntent(this)); + return false; + default: + Log.w(TAG, "Unhandled tab type : " + tab); + return false; + } } private void openHomeTab() { @@ -156,19 +192,29 @@ private boolean openIssueTab() { return true; } - private void setupTopAppBar() { - viewModel.getPageTitle().observe(this, binding.digitalCashAppBar::setTitle); + private void openSocialMediaTab() { + LaoView laoView = viewModel.getCurrentLaoValue(); + startActivity(SocialMediaActivity.newIntent(this, viewModel.getLaoId(), laoView.getName())); + } - binding.digitalCashAppBar.setNavigationOnClickListener( - v -> { - Fragment fragment = - getSupportFragmentManager().findFragmentById(R.id.fragment_container_digital_cash); - if (fragment instanceof DigitalCashHomeFragment) { - openLao(); - } else { - viewModel.setCurrentTab(DigitalCashTab.HOME); - } - }); + private void openInviteTab() { + startActivity( + LaoDetailActivity.newIntentWithTab(this, viewModel.getLaoId(), MainMenuTab.INVITE)); + } + + private void openWitnessingTab() { + startActivity( + LaoDetailActivity.newIntentWithTab(this, viewModel.getLaoId(), MainMenuTab.WITNESSING)); + } + + private void openTokensTab() { + startActivity( + LaoDetailActivity.newIntentWithTab(this, viewModel.getLaoId(), MainMenuTab.TOKENS)); + } + + private void openEventsTab() { + startActivity( + LaoDetailActivity.newIntentWithTab(this, viewModel.getLaoId(), MainMenuTab.EVENTS)); } public static Intent newIntent(Context ctx, String laoId) { diff --git a/fe2-android/app/src/main/java/com/github/dedis/popstellar/ui/digitalcash/DigitalCashIssueFragment.java b/fe2-android/app/src/main/java/com/github/dedis/popstellar/ui/digitalcash/DigitalCashIssueFragment.java index 997db4f5b9..e497332243 100644 --- a/fe2-android/app/src/main/java/com/github/dedis/popstellar/ui/digitalcash/DigitalCashIssueFragment.java +++ b/fe2-android/app/src/main/java/com/github/dedis/popstellar/ui/digitalcash/DigitalCashIssueFragment.java @@ -167,7 +167,7 @@ public void setTheAdapterRollCallAttendee() { try { myArray = viewModel.getAttendeesFromTheRollCallList(); } catch (NoRollCallException e) { - viewModel.setCurrentTab(DigitalCashTab.HOME); + // viewModel.setCurrentTab(DigitalCashTab.HOME); Log.d(TAG, getString(R.string.error_no_rollcall_closed_in_LAO)); Toast.makeText( requireContext(), diff --git a/fe2-android/app/src/main/java/com/github/dedis/popstellar/ui/digitalcash/DigitalCashSendFragment.java b/fe2-android/app/src/main/java/com/github/dedis/popstellar/ui/digitalcash/DigitalCashSendFragment.java index 0b6e9a9983..ff5ea93097 100644 --- a/fe2-android/app/src/main/java/com/github/dedis/popstellar/ui/digitalcash/DigitalCashSendFragment.java +++ b/fe2-android/app/src/main/java/com/github/dedis/popstellar/ui/digitalcash/DigitalCashSendFragment.java @@ -151,7 +151,7 @@ private void setUpTheAdapter() throws KeyException { try { myArray = viewModel.getAttendeesFromTheRollCallList(); } catch (NoRollCallException e) { - viewModel.setCurrentTab(DigitalCashTab.HOME); + // viewModel.setCurrentTab(DigitalCashTab.HOME); Toast.makeText( requireContext(), R.string.digital_cash_please_enter_roll_call, Toast.LENGTH_SHORT) .show(); diff --git a/fe2-android/app/src/main/java/com/github/dedis/popstellar/ui/digitalcash/DigitalCashViewModel.java b/fe2-android/app/src/main/java/com/github/dedis/popstellar/ui/digitalcash/DigitalCashViewModel.java index 8b7c2c7a9d..384e051c11 100644 --- a/fe2-android/app/src/main/java/com/github/dedis/popstellar/ui/digitalcash/DigitalCashViewModel.java +++ b/fe2-android/app/src/main/java/com/github/dedis/popstellar/ui/digitalcash/DigitalCashViewModel.java @@ -43,7 +43,7 @@ import io.reactivex.schedulers.Schedulers; @HiltViewModel -public class DigitalCashViewModel extends NavigationViewModel { +public class DigitalCashViewModel extends NavigationViewModel { public static final String TAG = DigitalCashViewModel.class.getSimpleName(); private static final String LAO_FAILURE_MESSAGE = "failed to retrieve lao"; @@ -79,6 +79,8 @@ public class DigitalCashViewModel extends NavigationViewModel { private final MutableLiveData> mTokens = new MutableLiveData<>(new HashSet<>()); private final LiveData> mTransactionHistory; + private final MutableLiveData bottomNavigationTab = + new MutableLiveData<>(DigitalCashTab.HOME); /* * Dependencies for this class @@ -133,14 +135,6 @@ protected void onCleared() { disposables.dispose(); } - public LiveData getPageTitle() { - return mPageTitle; - } - - public void setPageTitle(int titleId) { - mPageTitle.postValue(titleId); - } - public LiveData> getPostTransactionEvent() { return postTransactionEvent; } @@ -157,6 +151,16 @@ public LiveData> getUpdateReceiptAddressEvent() { return updateReceiptAddressEvent; } + public LiveData getBottomNavigationTab() { + return bottomNavigationTab; + } + + public void setBottomNavigationTab(DigitalCashTab tab) { + if (tab != bottomNavigationTab.getValue()) { + bottomNavigationTab.setValue(tab); + } + } + public void updateReceiptAddressEvent(String address) { updateReceiptAddressEvent.postValue(new SingleEvent<>(address)); } diff --git a/fe2-android/app/src/main/res/layout/digital_cash_main_activity.xml b/fe2-android/app/src/main/res/layout/digital_cash_main_activity.xml index 397b61664c..ca0533866c 100644 --- a/fe2-android/app/src/main/res/layout/digital_cash_main_activity.xml +++ b/fe2-android/app/src/main/res/layout/digital_cash_main_activity.xml @@ -1,43 +1,65 @@ + xmlns:app="http://schemas.android.com/apk/res-auto" + xmlns:tools="http://schemas.android.com/tools"> - + android:layout_height="match_parent" + tools:openDrawer="start"> - + android:layout_height="match_parent" + android:fitsSystemWindows="true"> - - + android:layout_height="match_parent" + app:layout_behavior="@string/appbar_scrolling_view_behavior"> - - - + + + + + + + + + + + + + - + From 241817f777874b7af217573e6a3e040ec7734178 Mon Sep 17 00:00:00 2001 From: Johann Pluss Date: Tue, 10 Jan 2023 15:12:49 +0100 Subject: [PATCH 13/41] Adapt social media to drawer MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Johann Plüss --- .../ui/socialmedia/SocialMediaActivity.java | 112 ++++++++++++------ .../socialmedia/SocialMediaSendFragment.java | 2 +- .../ui/socialmedia/SocialMediaViewModel.java | 24 ++-- .../main/res/layout/social_media_activity.xml | 84 +++++++------ 4 files changed, 134 insertions(+), 88 deletions(-) diff --git a/fe2-android/app/src/main/java/com/github/dedis/popstellar/ui/socialmedia/SocialMediaActivity.java b/fe2-android/app/src/main/java/com/github/dedis/popstellar/ui/socialmedia/SocialMediaActivity.java index d44313671d..181b124800 100644 --- a/fe2-android/app/src/main/java/com/github/dedis/popstellar/ui/socialmedia/SocialMediaActivity.java +++ b/fe2-android/app/src/main/java/com/github/dedis/popstellar/ui/socialmedia/SocialMediaActivity.java @@ -13,6 +13,9 @@ import com.github.dedis.popstellar.R; import com.github.dedis.popstellar.databinding.SocialMediaActivityBinding; import com.github.dedis.popstellar.ui.detail.LaoDetailActivity; +import com.github.dedis.popstellar.ui.digitalcash.DigitalCashActivity; +import com.github.dedis.popstellar.ui.home.HomeActivity; +import com.github.dedis.popstellar.ui.navigation.MainMenuTab; import com.github.dedis.popstellar.ui.navigation.NavigationActivity; import com.github.dedis.popstellar.utility.ActivityUtils; @@ -23,7 +26,7 @@ /** Activity for the social media */ @AndroidEntryPoint -public class SocialMediaActivity extends NavigationActivity { +public class SocialMediaActivity extends NavigationActivity { private SocialMediaViewModel viewModel; private SocialMediaActivityBinding binding; @@ -52,9 +55,13 @@ protected void onCreate(Bundle savedInstanceState) { viewModel.setLaoName(laoName); } } - - setupNavigationBar(binding.socialMediaNavBar); - setupTopAppBar(); + navigationViewModel.setCurrentTab(MainMenuTab.SOCIAL_MEDIA); + setupDrawer( + binding.socialMediaNavigationDrawer, + binding.socialMediaAppBar, + binding.socialMediaDrawerLayout); + setupBottomNavBar(); + openHomeTab(); } @Override @@ -74,13 +81,24 @@ public static SocialMediaViewModel obtainViewModel(FragmentActivity activity) { return new ViewModelProvider(activity).get(SocialMediaViewModel.class); } - @Override - protected SocialMediaTab findTabByMenu(int menuId) { - return SocialMediaTab.findByMenu(menuId); + private void setupBottomNavBar() { + viewModel + .getBottomNavigationTab() + .observe(this, tab -> binding.socialMediaNavBar.setSelectedItemId(tab.getMenuId())); + + binding.socialMediaNavBar.setOnItemSelectedListener( + item -> { + SocialMediaTab tab = SocialMediaTab.findByMenu(item.getItemId()); + Log.i(TAG, "Opening tab : " + tab.getName()); + openBottomTab(tab); + return true; + }); + + binding.socialMediaNavBar.setOnItemReselectedListener(item -> {}); + viewModel.setBottomNavigationTab(SocialMediaTab.HOME); } - @Override - protected boolean openTab(SocialMediaTab tab) { + private void openBottomTab(SocialMediaTab tab) { switch (tab) { case HOME: openHomeTab(); @@ -94,15 +112,36 @@ protected boolean openTab(SocialMediaTab tab) { case PROFILE: openProfileTab(); break; - default: - Log.w(TAG, "Unhandled tab type : " + tab); } - return true; } @Override - protected SocialMediaTab getDefaultTab() { - return SocialMediaTab.HOME; + protected boolean openTab(MainMenuTab tab) { + switch (tab) { + case INVITE: + openInviteTab(); + return false; + case EVENTS: + openEventsTab(); + return false; + case SOCIAL_MEDIA: + return false; + case DIGITAL_CASH: + openDigitalCash(); + return false; + case WITNESSING: + openWitnessingTab(); + return false; + case TOKENS: + openTokensTab(); + return false; + case DISCONNECT: + startActivity(HomeActivity.newIntent(this)); + return false; + default: + Log.w(TAG, "Unhandled tab type : " + tab); + return false; + } } private void openHomeTab() { @@ -126,10 +165,6 @@ private void openFollowingTab() { SocialMediaFollowingFragment::newInstance); } - public void openLao() { - startActivity(LaoDetailActivity.newIntentForLao(this, viewModel.getLaoId())); - } - private void openProfileTab() { setCurrentFragment( getSupportFragmentManager(), @@ -137,25 +172,28 @@ private void openProfileTab() { SocialMediaProfileFragment::newInstance); } - private void setupTopAppBar() { - viewModel.getPageTitle().observe(this, binding.socialMediaAppBar::setTitle); - - binding.socialMediaAppBar.setNavigationOnClickListener( - v -> { - Fragment fragment = - getSupportFragmentManager().findFragmentById(R.id.fragment_container_social_media); - if (fragment instanceof SocialMediaHomeFragment) { - openLao(); - } else { - if (viewModel.getCurrentTab().getValue() == SocialMediaTab.HOME) { - // On reselection the navigation is supposed to do nothing to prevent loops, so we - // manually change the fragment - openHomeTab(); - } else { - viewModel.setCurrentTab(SocialMediaTab.HOME); - } - } - }); + private void openInviteTab() { + startActivity( + LaoDetailActivity.newIntentWithTab(this, viewModel.getLaoId(), MainMenuTab.INVITE)); + } + + private void openWitnessingTab() { + startActivity( + LaoDetailActivity.newIntentWithTab(this, viewModel.getLaoId(), MainMenuTab.WITNESSING)); + } + + private void openTokensTab() { + startActivity( + LaoDetailActivity.newIntentWithTab(this, viewModel.getLaoId(), MainMenuTab.TOKENS)); + } + + private void openEventsTab() { + startActivity( + LaoDetailActivity.newIntentWithTab(this, viewModel.getLaoId(), MainMenuTab.EVENTS)); + } + + private void openDigitalCash() { + startActivity(DigitalCashActivity.newIntent(this, viewModel.getLaoId())); } public static Intent newIntent(Context ctx, String laoId, String laoName) { diff --git a/fe2-android/app/src/main/java/com/github/dedis/popstellar/ui/socialmedia/SocialMediaSendFragment.java b/fe2-android/app/src/main/java/com/github/dedis/popstellar/ui/socialmedia/SocialMediaSendFragment.java index f45d4a0335..b5bcc94ed7 100644 --- a/fe2-android/app/src/main/java/com/github/dedis/popstellar/ui/socialmedia/SocialMediaSendFragment.java +++ b/fe2-android/app/src/main/java/com/github/dedis/popstellar/ui/socialmedia/SocialMediaSendFragment.java @@ -93,7 +93,7 @@ private void sendNewChirp() { requireContext(), TAG, error, R.string.error_sending_chirp); } })); - viewModel.setCurrentTab(SocialMediaTab.HOME); + // viewModel.setCurrentTab(SocialMediaTab.HOME); } } } diff --git a/fe2-android/app/src/main/java/com/github/dedis/popstellar/ui/socialmedia/SocialMediaViewModel.java b/fe2-android/app/src/main/java/com/github/dedis/popstellar/ui/socialmedia/SocialMediaViewModel.java index cd0bf6f676..e7a470765d 100644 --- a/fe2-android/app/src/main/java/com/github/dedis/popstellar/ui/socialmedia/SocialMediaViewModel.java +++ b/fe2-android/app/src/main/java/com/github/dedis/popstellar/ui/socialmedia/SocialMediaViewModel.java @@ -40,7 +40,7 @@ import io.reactivex.disposables.Disposable; @HiltViewModel -public class SocialMediaViewModel extends NavigationViewModel { +public class SocialMediaViewModel extends NavigationViewModel { public static final String TAG = SocialMediaViewModel.class.getSimpleName(); private static final String LAO_FAILURE_MESSAGE = "failed to retrieve lao"; private static final String SOCIAL = "social"; @@ -52,7 +52,8 @@ public class SocialMediaViewModel extends NavigationViewModel { */ private final MutableLiveData mNumberCharsLeft = new MutableLiveData<>(); private final MutableLiveData mLaoName = new MutableLiveData<>(); - private final MutableLiveData mPageTitle = new MutableLiveData<>(); + private final MutableLiveData bottomNavigationTab = + new MutableLiveData<>(SocialMediaTab.HOME); /* * Dependencies for this class @@ -104,14 +105,6 @@ public LiveData getNumberCharsLeft() { return mNumberCharsLeft; } - public LiveData getLaoName() { - return mLaoName; - } - - public LiveData getPageTitle() { - return mPageTitle; - } - /* * Methods that modify the state or post an Event to update the UI. */ @@ -124,14 +117,15 @@ public void setLaoId(String laoId) { this.laoId = laoId; } - public void setLaoName(String laoName) { - mLaoName.setValue(laoName); + public LiveData getBottomNavigationTab() { + return bottomNavigationTab; } - public void setPageTitle(int titleId) { - mPageTitle.postValue(titleId); + public void setBottomNavigationTab(SocialMediaTab tab) { + if (tab != bottomNavigationTab.getValue()) { + bottomNavigationTab.setValue(tab); + } } - /** * Send a chirp to your own channel. * diff --git a/fe2-android/app/src/main/res/layout/social_media_activity.xml b/fe2-android/app/src/main/res/layout/social_media_activity.xml index cd0cf38ca1..c0090f339b 100644 --- a/fe2-android/app/src/main/res/layout/social_media_activity.xml +++ b/fe2-android/app/src/main/res/layout/social_media_activity.xml @@ -3,49 +3,63 @@ xmlns:app="http://schemas.android.com/apk/res-auto" xmlns:tools="http://schemas.android.com/tools"> - + android:layout_height="match_parent" + tools:openDrawer="start"> - + android:layout_height="match_parent" + android:fitsSystemWindows="true"> - - + android:layout_height="match_parent" + app:layout_behavior="@string/appbar_scrolling_view_behavior"> - - - + + + + + + android:layout_height="wrap_content" + android:fitsSystemWindows="true"> - + + - - + + + + + From 40a5dd0c90b79191db023cac6bf97bf80f030edf Mon Sep 17 00:00:00 2001 From: Johann Pluss Date: Tue, 10 Jan 2023 15:13:27 +0100 Subject: [PATCH 14/41] Slight fixes in digital cash MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Johann Plüss --- .../popstellar/ui/digitalcash/DigitalCashActivity.java | 8 ++++---- .../popstellar/ui/digitalcash/DigitalCashViewModel.java | 2 -- 2 files changed, 4 insertions(+), 6 deletions(-) diff --git a/fe2-android/app/src/main/java/com/github/dedis/popstellar/ui/digitalcash/DigitalCashActivity.java b/fe2-android/app/src/main/java/com/github/dedis/popstellar/ui/digitalcash/DigitalCashActivity.java index 5629880e56..a4f134e3f8 100644 --- a/fe2-android/app/src/main/java/com/github/dedis/popstellar/ui/digitalcash/DigitalCashActivity.java +++ b/fe2-android/app/src/main/java/com/github/dedis/popstellar/ui/digitalcash/DigitalCashActivity.java @@ -100,16 +100,16 @@ private void openBottomTab(DigitalCashTab tab) { switch (tab) { case HOME: openHomeTab(); - return; + break; case HISTORY: openHistoryTab(); - return; + break; case SEND: openSendTab(); - return; + break; case RECEIVE: openReceiveTab(); - return; + break; case ISSUE: openIssueTab(); } diff --git a/fe2-android/app/src/main/java/com/github/dedis/popstellar/ui/digitalcash/DigitalCashViewModel.java b/fe2-android/app/src/main/java/com/github/dedis/popstellar/ui/digitalcash/DigitalCashViewModel.java index 384e051c11..949aee0ade 100644 --- a/fe2-android/app/src/main/java/com/github/dedis/popstellar/ui/digitalcash/DigitalCashViewModel.java +++ b/fe2-android/app/src/main/java/com/github/dedis/popstellar/ui/digitalcash/DigitalCashViewModel.java @@ -75,8 +75,6 @@ public class DigitalCashViewModel extends NavigationViewModel { new MutableLiveData<>(); private final MutableLiveData mCurrentLao = new MutableLiveData<>(); - private final MutableLiveData mPageTitle = new MutableLiveData<>(); - private final MutableLiveData> mTokens = new MutableLiveData<>(new HashSet<>()); private final LiveData> mTransactionHistory; private final MutableLiveData bottomNavigationTab = From 6b59e5308af23a4b56ad6cb2463b60129a451d40 Mon Sep 17 00:00:00 2001 From: Johann Pluss Date: Tue, 10 Jan 2023 15:13:55 +0100 Subject: [PATCH 15/41] Add EXTRA key MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Johann Plüss --- .../java/com/github/dedis/popstellar/utility/Constants.java | 3 +++ 1 file changed, 3 insertions(+) diff --git a/fe2-android/app/src/main/java/com/github/dedis/popstellar/utility/Constants.java b/fe2-android/app/src/main/java/com/github/dedis/popstellar/utility/Constants.java index 8be2955328..f6a5e71ac7 100644 --- a/fe2-android/app/src/main/java/com/github/dedis/popstellar/utility/Constants.java +++ b/fe2-android/app/src/main/java/com/github/dedis/popstellar/utility/Constants.java @@ -23,6 +23,9 @@ public class Constants { /** The extra value given to the LaoDetailActivity when the wallet content is to be opened */ public static final String CONTENT_WALLET_EXTRA = "content_wallet"; + /** The tab to open in LaoDetailActivity */ + public static final String TAB_EXTRA = "tab_extra"; + /** The extra value given to the RollCallFragment when opened */ public static final String RC_PK_EXTRA = "pk"; From fc7d2ac1a38d94d2ec622376208ae908788de6a9 Mon Sep 17 00:00:00 2001 From: Johann Pluss Date: Tue, 10 Jan 2023 15:56:50 +0100 Subject: [PATCH 16/41] Temporary removal of tests MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Johann Plüss --- .../detail/LaoDetailActivityPageObject.java | 29 +- .../detail/LaoDetailFragmentPageObject.java | 2 +- .../ui/detail/LaoDetailActivityTest.java | 270 +++++++++--------- .../ui/detail/LaoDetailFragmentTest.java | 11 - 4 files changed, 146 insertions(+), 166 deletions(-) diff --git a/fe2-android/app/src/test/framework/common/java/com/github/dedis/popstellar/testutils/pages/detail/LaoDetailActivityPageObject.java b/fe2-android/app/src/test/framework/common/java/com/github/dedis/popstellar/testutils/pages/detail/LaoDetailActivityPageObject.java index b0bd0b2888..25d79a1cf4 100644 --- a/fe2-android/app/src/test/framework/common/java/com/github/dedis/popstellar/testutils/pages/detail/LaoDetailActivityPageObject.java +++ b/fe2-android/app/src/test/framework/common/java/com/github/dedis/popstellar/testutils/pages/detail/LaoDetailActivityPageObject.java @@ -8,7 +8,6 @@ import com.github.dedis.popstellar.utility.Constants; import static androidx.test.espresso.Espresso.onView; -import static androidx.test.espresso.matcher.ViewMatchers.withContentDescription; import static androidx.test.espresso.matcher.ViewMatchers.withId; /** @@ -26,34 +25,34 @@ public static ViewInteraction fragmentContainer() { return onView(withId(R.id.fragment_container_lao_detail)); } - public static ViewInteraction identityButton() { - return onView(withId(R.id.lao_detail_identity_menu)); - } - public static ViewInteraction socialMediaButton() { - return onView(withId(R.id.lao_detail_social_media_menu)); + return onView(withId(R.id.main_menu_digital_cash)); } public static ViewInteraction digitalCashButton() { - return onView(withId(R.id.lao_detail_digital_cash_menu)); + return onView(withId(R.id.main_menu_digital_cash)); + } + + @IdRes + public static int digitalCashMenu() { + return R.id.main_menu_digital_cash; } public static ViewInteraction witnessButton() { - return onView(withId(R.id.lao_detail_witnessing_menu)); + return onView(withId(R.id.main_menu_witnessing)); } - public static ViewInteraction toolBarBackButton() { - return onView(withContentDescription("Navigate up")); + public static ViewInteraction drawerLayout() { + return onView(withId(R.id.lao_detail_drawer_layout)); } - @IdRes - public static int laoDetailFragmentId() { - return R.id.fragment_lao_detail; + public static ViewInteraction navigationDrawer() { + return onView(withId(R.id.lao_detail_navigation_drawer)); } @IdRes - public static int identityFragmentId() { - return R.id.fragment_identity; + public static int laoDetailFragmentId() { + return R.id.fragment_lao_detail; } @IdRes diff --git a/fe2-android/app/src/test/framework/common/java/com/github/dedis/popstellar/testutils/pages/detail/LaoDetailFragmentPageObject.java b/fe2-android/app/src/test/framework/common/java/com/github/dedis/popstellar/testutils/pages/detail/LaoDetailFragmentPageObject.java index 6d1dea9b7c..dd921f0f8c 100644 --- a/fe2-android/app/src/test/framework/common/java/com/github/dedis/popstellar/testutils/pages/detail/LaoDetailFragmentPageObject.java +++ b/fe2-android/app/src/test/framework/common/java/com/github/dedis/popstellar/testutils/pages/detail/LaoDetailFragmentPageObject.java @@ -14,7 +14,7 @@ private LaoDetailFragmentPageObject() { } public static ViewInteraction qrCodeLayout() { - return onView(withId(R.id.lao_detail_qr_layout)); + return null; // onView(withId(R.id.lao_detail_qr_layout)); } public static ViewInteraction connectQrCode() { diff --git a/fe2-android/app/src/test/ui/robolectric/com/github/dedis/popstellar/ui/detail/LaoDetailActivityTest.java b/fe2-android/app/src/test/ui/robolectric/com/github/dedis/popstellar/ui/detail/LaoDetailActivityTest.java index ea43ab80e1..0ed2b098e7 100644 --- a/fe2-android/app/src/test/ui/robolectric/com/github/dedis/popstellar/ui/detail/LaoDetailActivityTest.java +++ b/fe2-android/app/src/test/ui/robolectric/com/github/dedis/popstellar/ui/detail/LaoDetailActivityTest.java @@ -1,139 +1,131 @@ -package com.github.dedis.popstellar.ui.detail; - -import androidx.test.espresso.intent.Intents; -import androidx.test.ext.junit.rules.ActivityScenarioRule; -import androidx.test.ext.junit.runners.AndroidJUnit4; - -import com.github.dedis.popstellar.model.objects.Lao; -import com.github.dedis.popstellar.model.objects.Wallet; -import com.github.dedis.popstellar.model.objects.view.LaoView; -import com.github.dedis.popstellar.repository.LAORepository; -import com.github.dedis.popstellar.repository.remote.GlobalNetworkManager; -import com.github.dedis.popstellar.testutils.*; -import com.github.dedis.popstellar.ui.digitalcash.DigitalCashActivity; -import com.github.dedis.popstellar.ui.socialmedia.SocialMediaActivity; -import com.github.dedis.popstellar.utility.error.UnknownLaoException; -import com.google.gson.Gson; - -import org.junit.Rule; -import org.junit.Test; -import org.junit.rules.*; -import org.junit.runner.RunWith; -import org.mockito.Mock; -import org.mockito.junit.MockitoJUnit; - -import java.security.GeneralSecurityException; - -import javax.inject.Inject; - -import dagger.hilt.android.testing.*; -import io.reactivex.subjects.BehaviorSubject; - -import static androidx.test.espresso.action.ViewActions.click; -import static androidx.test.espresso.assertion.ViewAssertions.matches; -import static androidx.test.espresso.intent.Intents.intended; -import static androidx.test.espresso.intent.matcher.IntentMatchers.hasComponent; -import static androidx.test.espresso.matcher.ViewMatchers.withChild; -import static androidx.test.espresso.matcher.ViewMatchers.withId; -import static com.github.dedis.popstellar.testutils.pages.detail.LaoDetailActivityPageObject.*; -import static org.mockito.ArgumentMatchers.any; -import static org.mockito.ArgumentMatchers.anyString; -import static org.mockito.Mockito.when; - -@HiltAndroidTest -@RunWith(AndroidJUnit4.class) -public class LaoDetailActivityTest { - - private static final Lao LAO = new Lao("LAO", Base64DataUtils.generatePublicKey(), 10223421); - private static final String LAO_ID = LAO.getId(); - - @Inject GlobalNetworkManager networkManager; - @Inject Gson gson; - - @BindValue @Mock LAORepository laoRepository; - @BindValue @Mock Wallet wallet; - - // Hilt rule - private final HiltAndroidRule hiltAndroidRule = new HiltAndroidRule(this); - // Setup rule, used to setup things before the activity is started - private final TestRule setupRule = - new ExternalResource() { - @Override - protected void before() throws UnknownLaoException, GeneralSecurityException { - hiltAndroidRule.inject(); - when(laoRepository.getLaoView(any())).thenAnswer(invocation -> new LaoView(LAO)); - - when(laoRepository.getLaoObservable(anyString())) - .thenReturn(BehaviorSubject.createDefault(new LaoView(LAO))); - - when(wallet.exportSeed()) - .thenReturn( - new String[] { - "jar", - "together", - "minor", - "alley", - "glow", - "hybrid", - "village", - "creek", - "meadow", - "atom", - "travel", - "bracket" - }); - } - }; - // Activity scenario rule that starts the activity. - // It creates a LaoDetailActivity with set extras such that the LAO is used - public ActivityScenarioRule activityScenarioRule = - new ActivityScenarioRule<>( - IntentUtils.createIntent( - LaoDetailActivity.class, - new BundleBuilder() - .putString(laoIdExtra(), LAO_ID) - .putString(fragmentToOpenExtra(), laoDetailValue()) - .build())); - - @Rule - public final RuleChain rule = - RuleChain.outerRule(MockitoJUnit.testRule(this)) - .around(hiltAndroidRule) - .around(setupRule) - .around(activityScenarioRule); - - @Test - public void identityTabOpensIdentityTab() { - identityButton().perform(click()); - fragmentContainer().check(matches(withChild(withId(identityFragmentId())))); - } - - @Test - public void witnessingTabShowsWitnessTab() { - witnessButton().perform(click()); - fragmentContainer().check(matches(withChild(withId(witnessingFragmentId())))); - } - - @Test - public void cancelGoesBackToEventList() { - identityButton().perform(click()); - toolBarBackButton().perform(click()); - fragmentContainer().check(matches(withChild(withId(laoDetailFragmentId())))); - } - - @Test - public void socialMediaNavOpensSocialMediaActivity() { - Intents.init(); - socialMediaButton().perform(click()); - intended(hasComponent(SocialMediaActivity.class.getName())); - Intents.release(); - } - - @Test - public void digitalCashNavOpensActivity() { - Intents.init(); - digitalCashButton().perform(click()); - intended(hasComponent(DigitalCashActivity.class.getName())); - Intents.release(); - } -} +// package com.github.dedis.popstellar.ui.detail; +// +// import androidx.test.espresso.contrib.DrawerActions; +// import androidx.test.espresso.contrib.NavigationViewActions; +// import androidx.test.espresso.intent.Intents; +// import androidx.test.ext.junit.rules.ActivityScenarioRule; +// import androidx.test.ext.junit.runners.AndroidJUnit4; +// +// import com.github.dedis.popstellar.model.objects.Lao; +// import com.github.dedis.popstellar.model.objects.Wallet; +// import com.github.dedis.popstellar.model.objects.view.LaoView; +// import com.github.dedis.popstellar.repository.LAORepository; +// import com.github.dedis.popstellar.repository.remote.GlobalNetworkManager; +// import com.github.dedis.popstellar.testutils.*; +// import com.github.dedis.popstellar.ui.digitalcash.DigitalCashActivity; +// import com.github.dedis.popstellar.ui.socialmedia.SocialMediaActivity; +// import com.github.dedis.popstellar.utility.error.UnknownLaoException; +// import com.google.gson.Gson; +// +// import org.junit.Rule; +// import org.junit.Test; +// import org.junit.rules.ExternalResource; +// import org.junit.runner.RunWith; +// import org.mockito.Mock; +// import org.mockito.junit.MockitoJUnit; +// import org.mockito.junit.MockitoTestRule; +// +// import java.security.GeneralSecurityException; +// +// import javax.inject.Inject; +// +// import dagger.hilt.android.testing.*; +// import io.reactivex.subjects.BehaviorSubject; +// +// import static androidx.test.espresso.action.ViewActions.click; +// import static androidx.test.espresso.assertion.ViewAssertions.matches; +// import static androidx.test.espresso.intent.Intents.intended; +// import static androidx.test.espresso.intent.matcher.IntentMatchers.hasComponent; +// import static androidx.test.espresso.matcher.ViewMatchers.withChild; +// import static androidx.test.espresso.matcher.ViewMatchers.withId; +// import static com.github.dedis.popstellar.testutils.pages.detail.LaoDetailActivityPageObject.*; +// import static org.mockito.ArgumentMatchers.any; +// import static org.mockito.ArgumentMatchers.anyString; +// import static org.mockito.Mockito.when; +// +// @HiltAndroidTest +// @RunWith(AndroidJUnit4.class) +// public class LaoDetailActivityTest { +// +// private static final Lao LAO = new Lao("LAO", Base64DataUtils.generatePublicKey(), 10223421); +// private static final String LAO_ID = LAO.getId(); +// +// @Inject GlobalNetworkManager networkManager; +// @Inject Gson gson; +// +// @BindValue @Mock LAORepository laoRepository; +// @BindValue @Mock Wallet wallet; +// +// @Rule(order = 0) +// public final MockitoTestRule mockitoRule = MockitoJUnit.testRule(this); +// +// @Rule(order = 1) +// public final HiltAndroidRule hiltAndroidRule = new HiltAndroidRule(this); +// +// @Rule(order = 2) +// public final ExternalResource setupRule = +// new ExternalResource() { +// @Override +// protected void before() throws UnknownLaoException, GeneralSecurityException { +// hiltAndroidRule.inject(); +// when(laoRepository.getLaoView(any())).thenAnswer(invocation -> new LaoView(LAO)); +// +// when(laoRepository.getLaoObservable(anyString())) +// .thenReturn(BehaviorSubject.createDefault(new LaoView(LAO))); +// +// when(wallet.exportSeed()) +// .thenReturn( +// new String[] { +// "jar", +// "together", +// "minor", +// "alley", +// "glow", +// "hybrid", +// "village", +// "creek", +// "meadow", +// "atom", +// "travel", +// "bracket" +// }); +// } +// }; +// +// @Rule(order = 3) +// public ActivityScenarioRule activityScenarioRule = +// new ActivityScenarioRule<>( +// IntentUtils.createIntent( +// LaoDetailActivity.class, +// new BundleBuilder() +// .putString(laoIdExtra(), LAO_ID) +// .putString(fragmentToOpenExtra(), laoDetailValue()) +// .build())); +// +// +// @Test +// public void witnessingTabShowsWitnessTab() { +// witnessButton().perform(click()); +// fragmentContainer().check(matches(withChild(withId(witnessingFragmentId())))); +// } +// +// @Test +// public void socialMediaNavOpensSocialMediaActivity() { +// Intents.init(); +// socialMediaButton().perform(click()); +// intended(hasComponent(SocialMediaActivity.class.getName())); +// Intents.release(); +// } +// +// @Test +// public void digitalCashNavOpensActivity() { +// drawerLayout().perform(DrawerActions.open()); +// Intents.init(); +// navigationDrawer().perform(NavigationViewActions.navigateTo(digitalCashMenu())); +// intended(hasComponent(DigitalCashActivity.class.getName())); +// Intents.release(); +// } +// +// private void openDrawer(){ +// } +// } diff --git a/fe2-android/app/src/test/ui/robolectric/com/github/dedis/popstellar/ui/detail/LaoDetailFragmentTest.java b/fe2-android/app/src/test/ui/robolectric/com/github/dedis/popstellar/ui/detail/LaoDetailFragmentTest.java index 8597d3543b..d3a532bc91 100644 --- a/fe2-android/app/src/test/ui/robolectric/com/github/dedis/popstellar/ui/detail/LaoDetailFragmentTest.java +++ b/fe2-android/app/src/test/ui/robolectric/com/github/dedis/popstellar/ui/detail/LaoDetailFragmentTest.java @@ -17,7 +17,6 @@ import com.github.dedis.popstellar.model.objects.event.EventState; import com.github.dedis.popstellar.model.objects.security.*; import com.github.dedis.popstellar.model.objects.view.LaoView; -import com.github.dedis.popstellar.model.qrcode.ConnectToLao; import com.github.dedis.popstellar.repository.LAORepository; import com.github.dedis.popstellar.repository.RollCallRepository; import com.github.dedis.popstellar.repository.remote.GlobalNetworkManager; @@ -133,16 +132,6 @@ protected void before() throws KeyException, UnknownLaoException, UnknownRollCal .putString(fragmentToOpenExtra(), laoDetailValue()) .build())); - @Test - public void showPropertyButtonShowsConnectQRCode() { - qrCodeIcon().perform(click()); - - qrCodeLayout().check(matches(isDisplayed())); - - String expectedQRCode = gson.toJson(new ConnectToLao(networkManager.getCurrentUrl(), LAO_ID)); - connectQrCode().check(matches(withQrCode(expectedQRCode))); - } - @Test public void addEventButtonIsDisplayedForOrganizer() { when(keyManager.getMainPublicKey()).thenReturn(PK); From 92086b3f99e96a2f305346d6d3a4159e178b57d7 Mon Sep 17 00:00:00 2001 From: Johann Pluss Date: Sat, 14 Jan 2023 13:12:16 +0100 Subject: [PATCH 17/41] Fix merge MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Johann Plüss --- .../github/dedis/popstellar/ui/detail/LaoDetailActivity.java | 3 --- 1 file changed, 3 deletions(-) diff --git a/fe2-android/app/src/main/java/com/github/dedis/popstellar/ui/detail/LaoDetailActivity.java b/fe2-android/app/src/main/java/com/github/dedis/popstellar/ui/detail/LaoDetailActivity.java index c976cb845c..d7129f6dd2 100644 --- a/fe2-android/app/src/main/java/com/github/dedis/popstellar/ui/detail/LaoDetailActivity.java +++ b/fe2-android/app/src/main/java/com/github/dedis/popstellar/ui/detail/LaoDetailActivity.java @@ -15,7 +15,6 @@ import com.github.dedis.popstellar.databinding.LaoDetailActivityBinding; import com.github.dedis.popstellar.model.objects.view.LaoView; import com.github.dedis.popstellar.repository.remote.GlobalNetworkManager; -import com.github.dedis.popstellar.ui.detail.event.LaoDetailAnimation; import com.github.dedis.popstellar.ui.detail.token.TokenListFragment; import com.github.dedis.popstellar.ui.detail.witness.WitnessingFragment; import com.github.dedis.popstellar.ui.digitalcash.DigitalCashActivity; @@ -60,8 +59,6 @@ protected void onCreate(@Nullable Bundle savedInstanceState) { String laoId = Objects.requireNonNull(getIntent().getExtras()).getString(Constants.LAO_ID_EXTRA); viewModel.subscribeToLao(laoId); - viewModel.subscribeToRollCalls(laoId); - viewModel.subscribeToElections(laoId); MainMenuTab tab = (MainMenuTab) getIntent().getExtras().get(Constants.TAB_EXTRA); if (tab == null) { From 60fe38d832f6a0b2ccefa94705d4d62014bebc54 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Johann=20Pl=C3=BCss?= Date: Sat, 14 Jan 2023 19:19:03 +0100 Subject: [PATCH 18/41] Merge branch 'work-fe2-jpluss-drawer' of C:\Users\johan\Documents\popstellar with conflicts. --- .../repository/ElectionRepository.java | 2 +- .../ui/detail/LaoDetailActivity.java | 5 + .../ui/detail/LaoDetailViewModel.java | 100 ++++++++++++++---- .../ui/detail/token/TokenFragment.java | 2 +- .../ui/detail/token/TokenListFragment.java | 2 +- .../ui/digitalcash/DigitalCashActivity.java | 9 +- .../ui/navigation/NavigationActivity.java | 69 ++++++++++++ .../ui/navigation/NavigationViewModel.java | 15 +++ 8 files changed, 180 insertions(+), 24 deletions(-) diff --git a/fe2-android/app/src/main/java/com/github/dedis/popstellar/repository/ElectionRepository.java b/fe2-android/app/src/main/java/com/github/dedis/popstellar/repository/ElectionRepository.java index 717f8ef3dd..405f617a77 100644 --- a/fe2-android/app/src/main/java/com/github/dedis/popstellar/repository/ElectionRepository.java +++ b/fe2-android/app/src/main/java/com/github/dedis/popstellar/repository/ElectionRepository.java @@ -50,7 +50,7 @@ public void updateElection(@NonNull Election election) { * @throws UnknownElectionException if no election with this id exist in this lao */ @NonNull - public Election getElection(@NonNull String laoId, @NonNull String electionId) + public com.github.dedis.popstellar.model.objects.Election getElection(@NonNull String laoId, @NonNull String electionId) throws UnknownElectionException { return getLaoElections(laoId).getElection(electionId); } diff --git a/fe2-android/app/src/main/java/com/github/dedis/popstellar/ui/detail/LaoDetailActivity.java b/fe2-android/app/src/main/java/com/github/dedis/popstellar/ui/detail/LaoDetailActivity.java index d7129f6dd2..e0260154e7 100644 --- a/fe2-android/app/src/main/java/com/github/dedis/popstellar/ui/detail/LaoDetailActivity.java +++ b/fe2-android/app/src/main/java/com/github/dedis/popstellar/ui/detail/LaoDetailActivity.java @@ -14,6 +14,7 @@ import com.github.dedis.popstellar.R; import com.github.dedis.popstellar.databinding.LaoDetailActivityBinding; import com.github.dedis.popstellar.model.objects.view.LaoView; +import com.github.dedis.popstellar.repository.RollCallRepository; import com.github.dedis.popstellar.repository.remote.GlobalNetworkManager; import com.github.dedis.popstellar.ui.detail.token.TokenListFragment; import com.github.dedis.popstellar.ui.detail.witness.WitnessingFragment; @@ -46,6 +47,8 @@ public class LaoDetailActivity extends NavigationActivity { @Inject Gson gson; @Inject GlobalNetworkManager networkManager; + @Inject + RollCallRepository rollCallRepository; @Override protected void onCreate(@Nullable Bundle savedInstanceState) { @@ -66,6 +69,8 @@ protected void onCreate(@Nullable Bundle savedInstanceState) { } navigationViewModel.setCurrentTab(tab); openTab(tab); + + viewModel.addDisposable(); } @Override diff --git a/fe2-android/app/src/main/java/com/github/dedis/popstellar/ui/detail/LaoDetailViewModel.java b/fe2-android/app/src/main/java/com/github/dedis/popstellar/ui/detail/LaoDetailViewModel.java index 1fd7dfefbe..f9557ecc96 100644 --- a/fe2-android/app/src/main/java/com/github/dedis/popstellar/ui/detail/LaoDetailViewModel.java +++ b/fe2-android/app/src/main/java/com/github/dedis/popstellar/ui/detail/LaoDetailViewModel.java @@ -232,11 +232,12 @@ public Completable endElection(Election election) { * * @param votes the corresponding votes for that election */ - public Completable sendVote(String electionId, List votes) { + public Completable sendVote(List votes) { Election election; try { - election = electionRepo.getElection(laoId, electionId); + election = electionRepo.getElection(laoId, currentElection); } catch (UnknownElectionException e) { + Log.d(TAG, "failed to retrieve current election"); return Completable.error(e); } @@ -573,8 +574,11 @@ public LiveData getNbAttendees() { return mNbAttendees; } - public Observable> getNodes() throws UnknownLaoException { - return laoRepository.getNodesByChannel(getLaoView().getChannel()); + public LiveData> getNodes() throws UnknownLaoException { + return LiveDataReactiveStreams.fromPublisher( + laoRepository + .getNodesByChannel(getLaoView().getChannel()) + .toFlowable(BackpressureStrategy.LATEST)); } public LiveData> getAttendeeScanConfirmEvent() { @@ -683,29 +687,89 @@ public void subscribeToLao(String laoId) { .throttleLatest(50, TimeUnit.MILLISECONDS) .subscribeOn(Schedulers.io()) .observeOn(AndroidSchedulers.mainThread()); + } + public void subscribeToRollCalls(String laoId) { disposables.add( - laoRepository - .getLaoObservable(laoId) + rollCallRepo + .getRollCallsObservableInLao(laoId) .subscribeOn(Schedulers.io()) .observeOn(AndroidSchedulers.mainThread()) .subscribe( - laoView -> { - Log.d(TAG, "got an update for lao: " + laoView.getName()); + idSet -> { + List rollCallList = + idSet.stream() + .map( + id -> { + try { + return rollCallRepo.getRollCallWithPersistentId(laoId, id); + } catch (UnknownRollCallException e) { + // Roll calls whose ids are in that list may not be absent + throw new IllegalStateException( + "Could not fetch roll call with id " + id); + } + }) + .collect(Collectors.toList()); + + mRollCalls.setValue(rollCallList); + + List attendedRollCall = + rollCallList.stream() + .filter(this::attendedOrOrganized) + .collect(Collectors.toList()); + Log.d(TAG, "attended roll calls: " + attendedRollCall); + + setIsAttendee( + attendedRollCall.contains(rollCallRepo.getLastClosedRollCall(laoId))); + }, + error -> Log.d(TAG, "Error updating Roll Call : " + error))); + } + + public void subscribeToElections(String laoId) { - mCurrentLao.postValue(laoView); - setLaoName(laoView.getName()); + disposables.add( + electionRepo + .getElectionsObservable(laoId) + .subscribeOn(Schedulers.io()) + .map( + ids -> + ids.stream() + .map( + id -> { + try { + return electionRepo.getElectionObservable(laoId, id); + } catch (UnknownElectionException e) { + // Election whose ids are in that list may not be absent + throw new IllegalStateException( + "Could not fetch election with id " + id); + } + }) + .collect(Collectors.toList())) + .flatMap( + subjects -> + Observable.combineLatest( + subjects, + elections -> + // Sort the election list. That way it stays somewhat consistent over + // the updates + Arrays.stream(elections) + .map(Election.class::cast) + .sorted(Comparator.comparing(Election::getCreation).reversed()) + .collect(Collectors.toList()))) + .lift(suppressErrors(err -> Log.e(TAG, "Error creating election list : ", err))) + .observeOn(AndroidSchedulers.mainThread()) + .subscribe(mElections::setValue)); + } - boolean isOrganizer = - laoView.getOrganizer().equals(keyManager.getMainPublicKey()); - setIsOrganizer(isOrganizer); - setIsWitness(laoView.getWitnesses().contains(keyManager.getMainPublicKey())); - }, - error -> Log.d(TAG, "error updating LAO :" + error))); + private void updateCurrentObjects() throws UnknownRollCallException { + if (currentRollCall != null) { + currentRollCall = + rollCallRepo.getRollCallWithPersistentId(laoId, currentRollCall.getPersistentId()); + } } - public PoPToken getCurrentPopToken(RollCall rollCall) throws KeyException, UnknownLaoException { - return keyManager.getPoPToken(getLaoView(), rollCall); + public PoPToken getCurrentPopToken() throws KeyException, UnknownLaoException { + return keyManager.getPoPToken(getLaoView(), currentRollCall); } public boolean isWalletSetup() { diff --git a/fe2-android/app/src/main/java/com/github/dedis/popstellar/ui/detail/token/TokenFragment.java b/fe2-android/app/src/main/java/com/github/dedis/popstellar/ui/detail/token/TokenFragment.java index 565f18ea10..b1a9638c0b 100644 --- a/fe2-android/app/src/main/java/com/github/dedis/popstellar/ui/detail/token/TokenFragment.java +++ b/fe2-android/app/src/main/java/com/github/dedis/popstellar/ui/detail/token/TokenFragment.java @@ -58,7 +58,7 @@ public static TokenFragment newInstance(String rcId) { @Override public void onResume() { super.onResume(); - viewModel.setPageTitle(getString(R.string.token)); + viewModel.setPageTitle(R.string.token); } @Override diff --git a/fe2-android/app/src/main/java/com/github/dedis/popstellar/ui/detail/token/TokenListFragment.java b/fe2-android/app/src/main/java/com/github/dedis/popstellar/ui/detail/token/TokenListFragment.java index fb04985185..4711c003c1 100644 --- a/fe2-android/app/src/main/java/com/github/dedis/popstellar/ui/detail/token/TokenListFragment.java +++ b/fe2-android/app/src/main/java/com/github/dedis/popstellar/ui/detail/token/TokenListFragment.java @@ -41,7 +41,7 @@ public TokenListFragment() { @Override public void onResume() { super.onResume(); - viewModel.setPageTitle(getString(R.string.tokens)); + viewModel.setPageTitle(R.string.tokens); } @Nullable diff --git a/fe2-android/app/src/main/java/com/github/dedis/popstellar/ui/digitalcash/DigitalCashActivity.java b/fe2-android/app/src/main/java/com/github/dedis/popstellar/ui/digitalcash/DigitalCashActivity.java index 994c89058a..fc9d81076f 100644 --- a/fe2-android/app/src/main/java/com/github/dedis/popstellar/ui/digitalcash/DigitalCashActivity.java +++ b/fe2-android/app/src/main/java/com/github/dedis/popstellar/ui/digitalcash/DigitalCashActivity.java @@ -25,7 +25,6 @@ import com.github.dedis.popstellar.utility.error.UnknownLaoException; import java.security.GeneralSecurityException; -import java.util.Objects; import java.util.function.Supplier; import dagger.hilt.android.AndroidEntryPoint; @@ -195,8 +194,12 @@ private boolean openIssueTab() { } private void openSocialMediaTab() { - LaoView laoView = viewModel.getCurrentLaoValue(); - startActivity(SocialMediaActivity.newIntent(this, viewModel.getLaoId(), laoView.getName())); + try { + LaoView laoView = viewModel.getCurrentLao(); + startActivity(SocialMediaActivity.newIntent(this, viewModel.getLaoId(), laoView.getName())); + } catch (UnknownLaoException e) { + ErrorUtils.logAndShow(this, TAG, e, R.string.unknown_lao_exception); + } } private void openInviteTab() { diff --git a/fe2-android/app/src/main/java/com/github/dedis/popstellar/ui/navigation/NavigationActivity.java b/fe2-android/app/src/main/java/com/github/dedis/popstellar/ui/navigation/NavigationActivity.java index d9e4f8696a..b1cdf5b846 100644 --- a/fe2-android/app/src/main/java/com/github/dedis/popstellar/ui/navigation/NavigationActivity.java +++ b/fe2-android/app/src/main/java/com/github/dedis/popstellar/ui/navigation/NavigationActivity.java @@ -9,21 +9,42 @@ import com.github.dedis.popstellar.R; import com.github.dedis.popstellar.model.Role; +import com.github.dedis.popstellar.model.objects.RollCall; +import com.github.dedis.popstellar.model.objects.Wallet; +import com.github.dedis.popstellar.model.objects.security.PublicKey; +import com.github.dedis.popstellar.repository.RollCallRepository; +import com.github.dedis.popstellar.utility.error.UnknownRollCallException; +import com.github.dedis.popstellar.utility.error.keys.KeyGenerationException; +import com.github.dedis.popstellar.utility.error.keys.UninitializedWalletException; import com.google.android.material.appbar.MaterialToolbar; import com.google.android.material.navigation.NavigationView; +import java.util.List; +import java.util.stream.Collectors; + +import javax.inject.Inject; + +import dagger.hilt.android.AndroidEntryPoint; +import io.reactivex.android.schedulers.AndroidSchedulers; +import io.reactivex.schedulers.Schedulers; + /** * This abstract activity encapsulate the redundant behavior of an activity with a navigation bar * *

An activity extending this must instantiate the navigationViewModel in its onCreate and it * should call setupDrawer with the navigationView as parameter. */ +@AndroidEntryPoint public abstract class NavigationActivity extends AppCompatActivity { private static final String TAG = NavigationActivity.class.getSimpleName(); protected NavigationViewModel navigationViewModel; + @Inject RollCallRepository rollCallRepo; + + @Inject Wallet wallet; + /** * Setup the navigation bar listeners given the navigation bar view * @@ -110,6 +131,34 @@ private void observeRoles() { navigationViewModel.isAttendee().observe(this, any -> navigationViewModel.updateRole()); } + public void observeRollCalls(String laoId) { + navigationViewModel.addDisposable( + rollCallRepo + .getRollCallsObservableInLao(laoId) + .subscribeOn(Schedulers.io()) + .observeOn(AndroidSchedulers.mainThread()) + .subscribe( + idSet -> { + List attendedRollCalls = + idSet.stream() + .map( + id -> { + try { + return rollCallRepo.getRollCallWithPersistentId(laoId, id); + } catch (UnknownRollCallException e) { + // Roll calls whose ids are in that list may not be absent + throw new IllegalStateException( + "Could not fetch roll call with id " + id); + } + }) + .filter(rollCall -> isRollCallAttended(rollCall, laoId)) + .collect(Collectors.toList()); + boolean hasUserAttendedLastRoll = + attendedRollCalls.contains(rollCallRepo.getLastClosedRollCall(laoId)); + navigationViewModel.isAttendee().setValue(hasUserAttendedLastRoll); + })); + } + private void setupHeaderLaoName(NavigationView navigationView, String laoName) { TextView laoNameView = navigationView @@ -126,6 +175,26 @@ private void setupHeaderRole(NavigationView navigationView, Role role) { roleView.setText(role.getStringId()); } + /** + * Predicate used for filtering rollcalls to make sure that the user either attended the rollcall + * or was the organizer + * + * @param rollcall the roll-call considered + * @return boolean saying whether user attended or organized the given roll call + */ + private boolean isRollCallAttended(RollCall rollcall, String laoId) { + // find out if user has attended the rollcall + try { + PublicKey pk = wallet.generatePoPToken(laoId, rollcall.getPersistentId()).getPublicKey(); + return rollcall.isClosed() + && (rollcall.getAttendees().contains(pk) + || Boolean.TRUE.equals(isOrganizer().getValue())); + } catch (KeyGenerationException | UninitializedWalletException e) { + Log.e(TAG, "failed to retrieve public key from wallet", e); + return false; + } + } + /** * Open the provided tab * diff --git a/fe2-android/app/src/main/java/com/github/dedis/popstellar/ui/navigation/NavigationViewModel.java b/fe2-android/app/src/main/java/com/github/dedis/popstellar/ui/navigation/NavigationViewModel.java index c633b8b07a..6db19ff90f 100644 --- a/fe2-android/app/src/main/java/com/github/dedis/popstellar/ui/navigation/NavigationViewModel.java +++ b/fe2-android/app/src/main/java/com/github/dedis/popstellar/ui/navigation/NavigationViewModel.java @@ -8,6 +8,9 @@ import com.github.dedis.popstellar.model.Role; +import io.reactivex.disposables.CompositeDisposable; +import io.reactivex.disposables.Disposable; + /** * Abstract view model that provides the components of the navigation bar * @@ -32,6 +35,8 @@ public abstract class NavigationViewModel extends AndroidViewModel { private final MutableLiveData pageTitle = new MutableLiveData<>(0); + private final CompositeDisposable disposables = new CompositeDisposable(); + protected NavigationViewModel(@NonNull Application application) { super(application); } @@ -113,6 +118,16 @@ public void setPageTitle(@StringRes Integer pageTitle) { } } + protected void addDisposable (Disposable disposable){ + this.disposables.add(disposable); + } + + @Override + protected void onCleared() { + super.onCleared(); + disposables.dispose(); + } + private Role determineRole() { if (isOrganizer.getValue()) { return Role.ORGANIZER; From 7692f27a0bbb106b413c5b64d162bac291ea790f Mon Sep 17 00:00:00 2001 From: Johann Pluss Date: Sat, 14 Jan 2023 19:44:09 +0100 Subject: [PATCH 19/41] Extend API of parent activity and viewmodel MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Johann Plüss --- .../ui/navigation/NavigationActivity.java | 106 +++++++++++------- .../ui/navigation/NavigationViewModel.java | 64 +++++++---- .../ui/detail/LaoDetailActivityTest.java | 2 +- 3 files changed, 107 insertions(+), 65 deletions(-) diff --git a/fe2-android/app/src/main/java/com/github/dedis/popstellar/ui/navigation/NavigationActivity.java b/fe2-android/app/src/main/java/com/github/dedis/popstellar/ui/navigation/NavigationActivity.java index b1cdf5b846..261a1616c2 100644 --- a/fe2-android/app/src/main/java/com/github/dedis/popstellar/ui/navigation/NavigationActivity.java +++ b/fe2-android/app/src/main/java/com/github/dedis/popstellar/ui/navigation/NavigationActivity.java @@ -12,21 +12,22 @@ import com.github.dedis.popstellar.model.objects.RollCall; import com.github.dedis.popstellar.model.objects.Wallet; import com.github.dedis.popstellar.model.objects.security.PublicKey; +import com.github.dedis.popstellar.repository.LAORepository; import com.github.dedis.popstellar.repository.RollCallRepository; -import com.github.dedis.popstellar.utility.error.UnknownRollCallException; -import com.github.dedis.popstellar.utility.error.keys.KeyGenerationException; -import com.github.dedis.popstellar.utility.error.keys.UninitializedWalletException; +import com.github.dedis.popstellar.ui.home.HomeActivity; +import com.github.dedis.popstellar.utility.error.ErrorUtils; +import com.github.dedis.popstellar.utility.error.UnknownLaoException; +import com.github.dedis.popstellar.utility.error.keys.*; +import com.github.dedis.popstellar.utility.security.KeyManager; import com.google.android.material.appbar.MaterialToolbar; import com.google.android.material.navigation.NavigationView; -import java.util.List; -import java.util.stream.Collectors; +import java.util.ArrayList; import javax.inject.Inject; import dagger.hilt.android.AndroidEntryPoint; import io.reactivex.android.schedulers.AndroidSchedulers; -import io.reactivex.schedulers.Schedulers; /** * This abstract activity encapsulate the redundant behavior of an activity with a navigation bar @@ -42,7 +43,8 @@ public abstract class NavigationActivity extends AppCompatActivity { protected NavigationViewModel navigationViewModel; @Inject RollCallRepository rollCallRepo; - + @Inject LAORepository laoRepo; + @Inject KeyManager keyManager; @Inject Wallet wallet; /** @@ -54,8 +56,12 @@ public abstract class NavigationActivity extends AppCompatActivity { * @param navigationView the view */ protected void setupDrawer( - NavigationView navigationView, MaterialToolbar toolbar, DrawerLayout drawerLayout) { + String laoId, + NavigationView navigationView, + MaterialToolbar toolbar, + DrawerLayout drawerLayout) { + navigationViewModel.setLaoId(laoId); observeRoles(); // Listen to click on left icon of toolbar @@ -104,10 +110,13 @@ protected void setupDrawer( return selected; }); - // Update the name of the Lao in the drawer header when it changes - navigationViewModel - .getLaoName() - .observe(this, laoName -> setupHeaderLaoName(navigationView, laoName)); + observeLao(laoId); + try { + setupHeaderLaoName(navigationView, navigationViewModel.getLao().getName()); + } catch (UnknownLaoException e) { + ErrorUtils.logAndShow(this, TAG, e, R.string.unknown_lao_exception); + startActivity(HomeActivity.newIntent(this)); + } // Update the user's role in the drawer header when it changes navigationViewModel.getRole().observe(this, role -> setupHeaderRole(navigationView, role)); @@ -122,41 +131,62 @@ protected void setupDrawer( toolbar.setTitle(resId); } }); + + observeRollCalls(laoId); } private void observeRoles() { // Observe any change in the following variable to update the role - navigationViewModel.isOrganizer().observe(this, any -> navigationViewModel.updateRole()); navigationViewModel.isWitness().observe(this, any -> navigationViewModel.updateRole()); navigationViewModel.isAttendee().observe(this, any -> navigationViewModel.updateRole()); } - public void observeRollCalls(String laoId) { + private void observeRollCalls(String laoId) { navigationViewModel.addDisposable( rollCallRepo .getRollCallsObservableInLao(laoId) - .subscribeOn(Schedulers.io()) .observeOn(AndroidSchedulers.mainThread()) .subscribe( - idSet -> { - List attendedRollCalls = - idSet.stream() - .map( - id -> { + rollCalls -> { + boolean isLastRollCallAttended = + rollCalls.stream() + .filter(rc -> isRollCallAttended(rc, laoId)) + .anyMatch( + rc -> { try { - return rollCallRepo.getRollCallWithPersistentId(laoId, id); - } catch (UnknownRollCallException e) { - // Roll calls whose ids are in that list may not be absent - throw new IllegalStateException( - "Could not fetch roll call with id " + id); + return rc.equals(rollCallRepo.getLastClosedRollCall(laoId)); + } catch (NoRollCallException e) { + return false; } - }) - .filter(rollCall -> isRollCallAttended(rollCall, laoId)) - .collect(Collectors.toList()); - boolean hasUserAttendedLastRoll = - attendedRollCalls.contains(rollCallRepo.getLastClosedRollCall(laoId)); - navigationViewModel.isAttendee().setValue(hasUserAttendedLastRoll); - })); + }); + navigationViewModel.setIsAttendee(isLastRollCallAttended); + }, + error -> + ErrorUtils.logAndShow(this, TAG, error, R.string.unknown_roll_call_exception))); + } + + private void observeLao(String laoId) { + navigationViewModel.addDisposable( + laoRepo + .getLaoObservable(laoId) + .observeOn(AndroidSchedulers.mainThread()) + .subscribe( + laoView -> { + Log.d(TAG, "got an update for lao: " + laoView); + + navigationViewModel.setWitnessMessages( + new ArrayList<>(laoView.getWitnessMessages().values())); + navigationViewModel.setWitnesses(new ArrayList<>(laoView.getWitnesses())); + + boolean isOrganizer = + laoView.getOrganizer().equals(keyManager.getMainPublicKey()); + navigationViewModel.setIsOrganizer(isOrganizer); + navigationViewModel.setIsWitness( + laoView.getWitnesses().contains(keyManager.getMainPublicKey())); + + navigationViewModel.updateRole(); + }, + error -> Log.d(TAG, "error updating LAO :" + error))); } private void setupHeaderLaoName(NavigationView navigationView, String laoName) { @@ -175,20 +205,10 @@ private void setupHeaderRole(NavigationView navigationView, Role role) { roleView.setText(role.getStringId()); } - /** - * Predicate used for filtering rollcalls to make sure that the user either attended the rollcall - * or was the organizer - * - * @param rollcall the roll-call considered - * @return boolean saying whether user attended or organized the given roll call - */ private boolean isRollCallAttended(RollCall rollcall, String laoId) { - // find out if user has attended the rollcall try { PublicKey pk = wallet.generatePoPToken(laoId, rollcall.getPersistentId()).getPublicKey(); - return rollcall.isClosed() - && (rollcall.getAttendees().contains(pk) - || Boolean.TRUE.equals(isOrganizer().getValue())); + return rollcall.isClosed() && rollcall.getAttendees().contains(pk); } catch (KeyGenerationException | UninitializedWalletException e) { Log.e(TAG, "failed to retrieve public key from wallet", e); return false; diff --git a/fe2-android/app/src/main/java/com/github/dedis/popstellar/ui/navigation/NavigationViewModel.java b/fe2-android/app/src/main/java/com/github/dedis/popstellar/ui/navigation/NavigationViewModel.java index 6db19ff90f..a4298c1836 100644 --- a/fe2-android/app/src/main/java/com/github/dedis/popstellar/ui/navigation/NavigationViewModel.java +++ b/fe2-android/app/src/main/java/com/github/dedis/popstellar/ui/navigation/NavigationViewModel.java @@ -7,6 +7,13 @@ import androidx.lifecycle.*; import com.github.dedis.popstellar.model.Role; +import com.github.dedis.popstellar.model.objects.WitnessMessage; +import com.github.dedis.popstellar.model.objects.security.PublicKey; +import com.github.dedis.popstellar.model.objects.view.LaoView; +import com.github.dedis.popstellar.utility.error.UnknownLaoException; + +import java.util.ArrayList; +import java.util.List; import io.reactivex.disposables.CompositeDisposable; import io.reactivex.disposables.Disposable; @@ -21,19 +28,18 @@ public abstract class NavigationViewModel extends AndroidViewModel { private final MutableLiveData currentTab = new MutableLiveData<>(); - private final MutableLiveData laoName = new MutableLiveData<>(); - - private final MutableLiveData isOrganizer = new MutableLiveData<>(Boolean.FALSE); + private boolean isOrganizer = false; + private String laoId; private final MutableLiveData isWitness = new MutableLiveData<>(Boolean.FALSE); - private final MutableLiveData isAttendee = new MutableLiveData<>(Boolean.FALSE); - private final MutableLiveData role = new MutableLiveData<>(Role.MEMBER); - private final MutableLiveData isTab = new MutableLiveData<>(Boolean.TRUE); - private final MutableLiveData pageTitle = new MutableLiveData<>(0); + private final MutableLiveData> witnesses = + new MutableLiveData<>(new ArrayList<>()); + private final MutableLiveData> witnessMessages = + new MutableLiveData<>(new ArrayList<>()); private final CompositeDisposable disposables = new CompositeDisposable(); @@ -41,6 +47,10 @@ protected NavigationViewModel(@NonNull Application application) { super(application); } + public String getLaoId() { + return laoId; + } + public LiveData getCurrentTab() { return currentTab; } @@ -49,15 +59,7 @@ public void setCurrentTab(MainMenuTab tab) { currentTab.setValue(tab); } - public MutableLiveData getLaoName() { - return laoName; - } - - public void setLaoName(String laoName) { - this.laoName.setValue(laoName); - } - - public MutableLiveData isOrganizer() { + public boolean isOrganizer() { return isOrganizer; } @@ -81,6 +83,16 @@ public MutableLiveData getPageTitle() { return pageTitle; } + public abstract LaoView getLao() throws UnknownLaoException; + + public LiveData> getWitnesses() { + return witnesses; + } + + public LiveData> getWitnessMessages() { + return witnessMessages; + } + public void updateRole() { Role role = determineRole(); if (this.role.getValue() != role) { @@ -88,10 +100,12 @@ public void updateRole() { } } + public void setLaoId(String laoId) { + this.laoId = laoId; + } + public void setIsOrganizer(boolean isOrganizer) { - if (this.isOrganizer.getValue() != isOrganizer) { - this.isOrganizer.setValue(isOrganizer); - } + this.isOrganizer = isOrganizer; } public void setIsWitness(boolean isWitness) { @@ -118,7 +132,15 @@ public void setPageTitle(@StringRes Integer pageTitle) { } } - protected void addDisposable (Disposable disposable){ + public void setWitnesses(List witnesses) { + this.witnesses.setValue(witnesses); + } + + public void setWitnessMessages(List messages) { + this.witnessMessages.setValue(messages); + } + + public void addDisposable(Disposable disposable) { this.disposables.add(disposable); } @@ -129,7 +151,7 @@ protected void onCleared() { } private Role determineRole() { - if (isOrganizer.getValue()) { + if (isOrganizer) { return Role.ORGANIZER; } if (isWitness.getValue()) { diff --git a/fe2-android/app/src/test/ui/robolectric/com/github/dedis/popstellar/ui/detail/LaoDetailActivityTest.java b/fe2-android/app/src/test/ui/robolectric/com/github/dedis/popstellar/ui/detail/LaoDetailActivityTest.java index 0ed2b098e7..f66d42b255 100644 --- a/fe2-android/app/src/test/ui/robolectric/com/github/dedis/popstellar/ui/detail/LaoDetailActivityTest.java +++ b/fe2-android/app/src/test/ui/robolectric/com/github/dedis/popstellar/ui/detail/LaoDetailActivityTest.java @@ -68,7 +68,7 @@ // @Override // protected void before() throws UnknownLaoException, GeneralSecurityException { // hiltAndroidRule.inject(); -// when(laoRepository.getLaoView(any())).thenAnswer(invocation -> new LaoView(LAO)); +// when(laoRepository.getLao(any())).thenAnswer(invocation -> new LaoView(LAO)); // // when(laoRepository.getLaoObservable(anyString())) // .thenReturn(BehaviorSubject.createDefault(new LaoView(LAO))); From 81a65a4b33b430ca2aec353c8219757490f074b5 Mon Sep 17 00:00:00 2001 From: Johann Pluss Date: Sat, 14 Jan 2023 19:44:51 +0100 Subject: [PATCH 20/41] Adapt Digital cash MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Johann Plüss --- .../popstellar/repository/LAORepository.java | 2 + .../ui/digitalcash/DigitalCashActivity.java | 28 ++++---------- .../digitalcash/DigitalCashIssueFragment.java | 2 +- .../ui/digitalcash/DigitalCashViewModel.java | 38 ++++++------------- 4 files changed, 23 insertions(+), 47 deletions(-) diff --git a/fe2-android/app/src/main/java/com/github/dedis/popstellar/repository/LAORepository.java b/fe2-android/app/src/main/java/com/github/dedis/popstellar/repository/LAORepository.java index c00b4caa60..6f83426ecc 100644 --- a/fe2-android/app/src/main/java/com/github/dedis/popstellar/repository/LAORepository.java +++ b/fe2-android/app/src/main/java/com/github/dedis/popstellar/repository/LAORepository.java @@ -56,6 +56,8 @@ public Observable getLaoObservable(String laoId) { } public LaoView getLaoView(String id) throws UnknownLaoException { + Log.d(TAG, "id:" + id); + Log.d(TAG, "laos:" + laoById.values()); Lao lao = laoById.get(id); if (lao == null) { throw new UnknownLaoException(id); diff --git a/fe2-android/app/src/main/java/com/github/dedis/popstellar/ui/digitalcash/DigitalCashActivity.java b/fe2-android/app/src/main/java/com/github/dedis/popstellar/ui/digitalcash/DigitalCashActivity.java index fc9d81076f..71c3a57524 100644 --- a/fe2-android/app/src/main/java/com/github/dedis/popstellar/ui/digitalcash/DigitalCashActivity.java +++ b/fe2-android/app/src/main/java/com/github/dedis/popstellar/ui/digitalcash/DigitalCashActivity.java @@ -13,7 +13,6 @@ import com.github.dedis.popstellar.R; import com.github.dedis.popstellar.databinding.DigitalCashMainActivityBinding; import com.github.dedis.popstellar.model.objects.security.PublicKey; -import com.github.dedis.popstellar.model.objects.view.LaoView; import com.github.dedis.popstellar.ui.detail.LaoDetailActivity; import com.github.dedis.popstellar.ui.home.HomeActivity; import com.github.dedis.popstellar.ui.navigation.MainMenuTab; @@ -25,6 +24,7 @@ import com.github.dedis.popstellar.utility.error.UnknownLaoException; import java.security.GeneralSecurityException; +import java.util.Objects; import java.util.function.Supplier; import dagger.hilt.android.AndroidEntryPoint; @@ -42,16 +42,17 @@ protected void onCreate(Bundle savedInstanceState) { binding = DigitalCashMainActivityBinding.inflate(getLayoutInflater()); setContentView(binding.getRoot()); navigationViewModel = viewModel = obtainViewModel(this); - - navigationViewModel.setCurrentTab(MainMenuTab.DIGITAL_CASH); + String laoId = Objects.requireNonNull(getIntent().getStringExtra(Constants.LAO_ID_EXTRA)); + Log.d(TAG, "Opening digitalCash with id " + laoId); setupDrawer( + laoId, binding.digitalCashNavigationDrawer, binding.digitalCashAppBar, binding.digitalCashDrawerLayout); + + navigationViewModel.setCurrentTab(MainMenuTab.DIGITAL_CASH); setupBottomNavBar(); openHomeTab(); - - loadIntentData(); } @Override @@ -67,14 +68,6 @@ public void onStop() { } } - public void loadIntentData() { - if (getIntent().getExtras() != null) { - String id = getIntent().getExtras().getString(Constants.LAO_ID_EXTRA, ""); - viewModel.setLaoId(id); - viewModel.setRollCallId(getIntent().getExtras().getString(Constants.ROLL_CALL_ID, "")); - } - } - public static DigitalCashViewModel obtainViewModel(FragmentActivity activity) { return new ViewModelProvider(activity).get(DigitalCashViewModel.class); } @@ -174,7 +167,7 @@ private void openReceiveTab() { private boolean openIssueTab() { try { - PublicKey organizerKey = viewModel.getCurrentLao().getOrganizer(); + PublicKey organizerKey = viewModel.getLao().getOrganizer(); if (!viewModel.getOwnKey().equals(organizerKey)) { ErrorUtils.logAndShow(this, TAG, R.string.digital_cash_non_organizer_error_issue); return false; @@ -194,12 +187,7 @@ private boolean openIssueTab() { } private void openSocialMediaTab() { - try { - LaoView laoView = viewModel.getCurrentLao(); - startActivity(SocialMediaActivity.newIntent(this, viewModel.getLaoId(), laoView.getName())); - } catch (UnknownLaoException e) { - ErrorUtils.logAndShow(this, TAG, e, R.string.unknown_lao_exception); - } + startActivity(SocialMediaActivity.newIntent(this, viewModel.getLaoId())); } private void openInviteTab() { diff --git a/fe2-android/app/src/main/java/com/github/dedis/popstellar/ui/digitalcash/DigitalCashIssueFragment.java b/fe2-android/app/src/main/java/com/github/dedis/popstellar/ui/digitalcash/DigitalCashIssueFragment.java index f93ebec180..6c1f659098 100644 --- a/fe2-android/app/src/main/java/com/github/dedis/popstellar/ui/digitalcash/DigitalCashIssueFragment.java +++ b/fe2-android/app/src/main/java/com/github/dedis/popstellar/ui/digitalcash/DigitalCashIssueFragment.java @@ -141,7 +141,7 @@ private Set attendeesPerRadioGroupButton(int radioGroup, String curre } else if (radioGroup == selectAllRollCallAttendees) { attendees = viewModel.getAttendeesFromLastRollCall(); } else if (radioGroup == selectAllLaoWitnesses) { - attendees = Objects.requireNonNull(viewModel.getCurrentLao()).getWitnesses(); + attendees = Objects.requireNonNull(viewModel.getLao()).getWitnesses(); } return attendees; } diff --git a/fe2-android/app/src/main/java/com/github/dedis/popstellar/ui/digitalcash/DigitalCashViewModel.java b/fe2-android/app/src/main/java/com/github/dedis/popstellar/ui/digitalcash/DigitalCashViewModel.java index 7c08689b9c..38f43b8c57 100644 --- a/fe2-android/app/src/main/java/com/github/dedis/popstellar/ui/digitalcash/DigitalCashViewModel.java +++ b/fe2-android/app/src/main/java/com/github/dedis/popstellar/ui/digitalcash/DigitalCashViewModel.java @@ -59,9 +59,6 @@ public class DigitalCashViewModel extends NavigationViewModel { private final MutableLiveData> postTransactionEvent = new MutableLiveData<>(); - private String laoId; - private final MutableLiveData mRollCallId = new MutableLiveData<>(); - /* Is used to change the lao Coin amount on the home fragment*/ private final MutableLiveData> updateLaoCoinEvent = new MutableLiveData<>(); @@ -205,7 +202,7 @@ public Completable postTransaction( /* Check if a Lao exist */ LaoView laoView; try { - laoView = getCurrentLao(); + laoView = getLao(); } catch (UnknownLaoException e) { Log.e(TAG, LAO_FAILURE_MESSAGE); return Completable.error(new UnknownLaoException()); @@ -276,18 +273,6 @@ private Input processSignInput( new ScriptInput(TYPE, keyPair.getPublicKey(), sig)); } - public String getLaoId() { - return laoId; - } - - public void setLaoId(String laoId) { - this.laoId = laoId; - } - - public void setRollCallId(String rollCallId) { - this.mRollCallId.setValue(rollCallId); - } - public LAORepository getLaoRepository() { return laoRepository; } @@ -298,12 +283,12 @@ public PublicKey getOwnKey() { @Nullable public Set getAttendeesFromLastRollCall() throws NoRollCallException { - return rollCallRepo.getLastClosedRollCall(laoId).getAttendees(); + return rollCallRepo.getLastClosedRollCall(getLaoId()).getAttendees(); } @Nullable public PublicKey getOrganizer() throws UnknownLaoException { - return getCurrentLao().getOrganizer(); + return getLao().getOrganizer(); } @Nullable @@ -313,16 +298,17 @@ public List getAttendeesFromTheRollCallList() throws NoRollCallException .collect(Collectors.toList()); } - public LaoView getCurrentLao() throws UnknownLaoException { - return laoRepository.getLaoView(laoId); + @Override + public LaoView getLao() throws UnknownLaoException { + return laoRepository.getLaoView(getLaoId()); } public Set getAllAttendees() { - return rollCallRepo.getAllAttendeesInLao(laoId); + return rollCallRepo.getAllAttendeesInLao(getLaoId()); } public PoPToken getValidToken() throws KeyException { - return keyManager.getValidPoPToken(laoId, rollCallRepo.getLastClosedRollCall(laoId)); + return keyManager.getValidPoPToken(getLaoId(), rollCallRepo.getLastClosedRollCall(getLaoId())); } public boolean canPerformTransaction( @@ -369,23 +355,23 @@ private void processNotCoinbaseTransaction( } public List getTransactionsForUser(PublicKey user) { - return digitalCashRepo.getTransactions(laoId, user); + return digitalCashRepo.getTransactions(getLaoId(), user); } public Observable> getTransactionsObservable() { try { - return digitalCashRepo.getTransactionsObservable(laoId, getValidToken().getPublicKey()); + return digitalCashRepo.getTransactionsObservable(getLaoId(), getValidToken().getPublicKey()); } catch (KeyException e) { return Observable.error(e); } } public Observable> getRollCallsObservable() { - return rollCallRepo.getRollCallsObservableInLao(laoId); + return rollCallRepo.getRollCallsObservableInLao(getLaoId()); } public long getUserBalance(PublicKey user) { - return digitalCashRepo.getUserBalance(laoId, user); + return digitalCashRepo.getUserBalance(getLaoId(), user); } public long getOwnBalance() throws KeyException { From 281d8a2db98acb125094793c03efde832cf0a6ae Mon Sep 17 00:00:00 2001 From: Johann Pluss Date: Sat, 14 Jan 2023 19:45:20 +0100 Subject: [PATCH 21/41] Change logging flow for display utils MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Johann Plüss --- .../com/github/dedis/popstellar/utility/error/ErrorUtils.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/fe2-android/app/src/main/java/com/github/dedis/popstellar/utility/error/ErrorUtils.java b/fe2-android/app/src/main/java/com/github/dedis/popstellar/utility/error/ErrorUtils.java index aeb69bf03f..7e521fa7ce 100644 --- a/fe2-android/app/src/main/java/com/github/dedis/popstellar/utility/error/ErrorUtils.java +++ b/fe2-android/app/src/main/java/com/github/dedis/popstellar/utility/error/ErrorUtils.java @@ -29,7 +29,7 @@ private ErrorUtils() throws IllegalAccessException { public static void logAndShow(Context context, String tag, @StringRes int action) { String message = context.getString(action); - Log.d(tag, message); + Log.e(tag, message); displayToast(context, message); } From 6e43485019d612c9e87c1dcf6e826e4e73b06d5b Mon Sep 17 00:00:00 2001 From: Johann Pluss Date: Sat, 14 Jan 2023 19:46:23 +0100 Subject: [PATCH 22/41] Adapt social media MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Johann Plüss --- .../ui/socialmedia/SocialMediaActivity.java | 22 +++++---------- .../ui/socialmedia/SocialMediaViewModel.java | 28 ++++++------------- 2 files changed, 15 insertions(+), 35 deletions(-) diff --git a/fe2-android/app/src/main/java/com/github/dedis/popstellar/ui/socialmedia/SocialMediaActivity.java b/fe2-android/app/src/main/java/com/github/dedis/popstellar/ui/socialmedia/SocialMediaActivity.java index 181b124800..5f4eed5816 100644 --- a/fe2-android/app/src/main/java/com/github/dedis/popstellar/ui/socialmedia/SocialMediaActivity.java +++ b/fe2-android/app/src/main/java/com/github/dedis/popstellar/ui/socialmedia/SocialMediaActivity.java @@ -18,8 +18,10 @@ import com.github.dedis.popstellar.ui.navigation.MainMenuTab; import com.github.dedis.popstellar.ui.navigation.NavigationActivity; import com.github.dedis.popstellar.utility.ActivityUtils; +import com.github.dedis.popstellar.utility.Constants; import java.security.GeneralSecurityException; +import java.util.Objects; import java.util.function.Supplier; import dagger.hilt.android.AndroidEntryPoint; @@ -43,20 +45,11 @@ protected void onCreate(Bundle savedInstanceState) { setContentView(binding.getRoot()); navigationViewModel = viewModel = obtainViewModel(this); - // When we launch the social media from a lao, it directly sets its id and name - if (getIntent().getExtras() != null) { - String laoId = getIntent().getExtras().getString(LAO_ID); - String laoName = getIntent().getExtras().getString(LAO_NAME); - - if (laoId != null) { - viewModel.setLaoId(laoId); - } - if (laoName != null) { - viewModel.setLaoName(laoName); - } - } + String laoId = Objects.requireNonNull(getIntent().getStringExtra(Constants.LAO_ID_EXTRA)); + navigationViewModel.setCurrentTab(MainMenuTab.SOCIAL_MEDIA); setupDrawer( + laoId, binding.socialMediaNavigationDrawer, binding.socialMediaAppBar, binding.socialMediaDrawerLayout); @@ -196,10 +189,9 @@ private void openDigitalCash() { startActivity(DigitalCashActivity.newIntent(this, viewModel.getLaoId())); } - public static Intent newIntent(Context ctx, String laoId, String laoName) { + public static Intent newIntent(Context ctx, String laoId) { Intent intent = new Intent(ctx, SocialMediaActivity.class); - intent.putExtra(LAO_ID, laoId); - intent.putExtra(LAO_NAME, laoName); + intent.putExtra(Constants.LAO_ID_EXTRA, laoId); return intent; } diff --git a/fe2-android/app/src/main/java/com/github/dedis/popstellar/ui/socialmedia/SocialMediaViewModel.java b/fe2-android/app/src/main/java/com/github/dedis/popstellar/ui/socialmedia/SocialMediaViewModel.java index e7a470765d..079ccec10b 100644 --- a/fe2-android/app/src/main/java/com/github/dedis/popstellar/ui/socialmedia/SocialMediaViewModel.java +++ b/fe2-android/app/src/main/java/com/github/dedis/popstellar/ui/socialmedia/SocialMediaViewModel.java @@ -45,7 +45,6 @@ public class SocialMediaViewModel extends NavigationViewModel { private static final String LAO_FAILURE_MESSAGE = "failed to retrieve lao"; private static final String SOCIAL = "social"; public static final Integer MAX_CHAR_NUMBERS = 300; - private String laoId; /* * LiveData objects for capturing events @@ -113,10 +112,6 @@ public void setNumberCharsLeft(Integer numberChars) { mNumberCharsLeft.setValue(numberChars); } - public void setLaoId(String laoId) { - this.laoId = laoId; - } - public LiveData getBottomNavigationTab() { return bottomNavigationTab; } @@ -141,7 +136,7 @@ public Single sendChirp( LaoView laoView; try { - laoView = getCurrentLaoView(); + laoView = getLao(); } catch (UnknownLaoException e) { Log.e(TAG, LAO_FAILURE_MESSAGE); return Single.error(new UnknownLaoException()); @@ -169,7 +164,7 @@ public Single deleteChirp(MessageID chirpId, long timestamp) { final LaoView laoView; try { - laoView = getCurrentLaoView(); + laoView = getLao(); } catch (UnknownLaoException e) { Log.e(TAG, LAO_FAILURE_MESSAGE); return Single.error(new UnknownLaoException()); @@ -194,13 +189,13 @@ public Single deleteChirp(MessageID chirpId, long timestamp) { public Observable> getChirps() { return socialMediaRepository - .getChirpsOfLao(laoId) + .getChirpsOfLao(getLaoId()) // Retrieve chirp subjects per id .map( ids -> { List> chirps = new ArrayList<>(ids.size()); for (MessageID id : ids) { - chirps.add(socialMediaRepository.getChirp(laoId, id)); + chirps.add(socialMediaRepository.getChirp(getLaoId(), id)); } return chirps; }) @@ -257,19 +252,12 @@ public void addDisposable(Disposable disposable) { this.disposables.add(disposable); } - public LaoView getLaoView(String laoId) throws UnknownLaoException { - return laoRepository.getLaoView(laoId); - } - - public LaoView getCurrentLaoView() throws UnknownLaoException { - return getLaoView(laoId); - } - - public String getLaoId() { - return laoId; + @Override + public LaoView getLao() throws UnknownLaoException { + return laoRepository.getLaoView(getLaoId()); } public PoPToken getValidPoPToken() throws KeyException { - return keyManager.getValidPoPToken(laoId, rollCallRepo.getLastClosedRollCall(laoId)); + return keyManager.getValidPoPToken(getLaoId(), rollCallRepo.getLastClosedRollCall(getLaoId())); } } From 057302926e35e16140fb06bb7c6dba82975ff96d Mon Sep 17 00:00:00 2001 From: Johann Pluss Date: Sat, 14 Jan 2023 19:46:45 +0100 Subject: [PATCH 23/41] Adapt lao detail MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Johann Plüss --- .../popstellar/ui/detail/InviteFragment.java | 34 +++-- .../ui/detail/LaoDetailActivity.java | 23 +--- .../ui/detail/LaoDetailViewModel.java | 128 +++--------------- .../consensus/ElectionStartFragment.java | 31 +++-- .../election/fragments/CastVoteFragment.java | 2 +- .../election/fragments/ElectionFragment.java | 3 +- .../fragments/ElectionResultFragment.java | 2 +- .../event/rollcall/RollCallFragment.java | 5 +- 8 files changed, 71 insertions(+), 157 deletions(-) diff --git a/fe2-android/app/src/main/java/com/github/dedis/popstellar/ui/detail/InviteFragment.java b/fe2-android/app/src/main/java/com/github/dedis/popstellar/ui/detail/InviteFragment.java index 9fc491753e..68b9e66eb9 100644 --- a/fe2-android/app/src/main/java/com/github/dedis/popstellar/ui/detail/InviteFragment.java +++ b/fe2-android/app/src/main/java/com/github/dedis/popstellar/ui/detail/InviteFragment.java @@ -10,8 +10,11 @@ import com.github.dedis.popstellar.R; import com.github.dedis.popstellar.databinding.InviteFragmentBinding; +import com.github.dedis.popstellar.model.objects.view.LaoView; import com.github.dedis.popstellar.model.qrcode.ConnectToLao; import com.github.dedis.popstellar.repository.remote.GlobalNetworkManager; +import com.github.dedis.popstellar.utility.error.ErrorUtils; +import com.github.dedis.popstellar.utility.error.UnknownLaoException; import com.google.gson.Gson; import net.glxn.qrgen.android.QRCode; @@ -23,6 +26,8 @@ @AndroidEntryPoint public class InviteFragment extends Fragment { + private static final String TAG = InviteFragment.class.getSimpleName(); + @Inject Gson gson; @Inject GlobalNetworkManager networkManager; @@ -46,24 +51,23 @@ public View onCreateView( binding.laoPropertiesIdentifierText.setText(viewModel.getPublicKey().getEncoded()); binding.laoPropertiesServerText.setText(networkManager.getCurrentUrl()); - viewModel - .getCurrentLao() - .observe( - requireActivity(), - laoView -> { - // Set the QR code - ConnectToLao data = new ConnectToLao(networkManager.getCurrentUrl(), laoView.getId()); - Bitmap myBitmap = QRCode.from(gson.toJson(data)).withSize(QR_SIDE, QR_SIDE).bitmap(); - binding.channelQrCode.setImageBitmap(myBitmap); + try { + LaoView laoView = viewModel.getLao(); - binding.laoPropertiesNameText.setText(laoView.getName()); - }); + ConnectToLao data = new ConnectToLao(networkManager.getCurrentUrl(), laoView.getId()); + Bitmap myBitmap = QRCode.from(gson.toJson(data)).withSize(QR_SIDE, QR_SIDE).bitmap(); + binding.channelQrCode.setImageBitmap(myBitmap); + binding.laoPropertiesNameText.setText(laoView.getName()); - viewModel - .getRole() - .observe( - requireActivity(), role -> binding.laoPropertiesRoleText.setText(role.getStringId())); + viewModel + .getRole() + .observe( + requireActivity(), role -> binding.laoPropertiesRoleText.setText(role.getStringId())); + } catch (UnknownLaoException e) { + ErrorUtils.logAndShow(requireContext(), TAG, e, R.string.unknown_lao_exception); + return null; + } return binding.getRoot(); } diff --git a/fe2-android/app/src/main/java/com/github/dedis/popstellar/ui/detail/LaoDetailActivity.java b/fe2-android/app/src/main/java/com/github/dedis/popstellar/ui/detail/LaoDetailActivity.java index e0260154e7..2f40a72c4f 100644 --- a/fe2-android/app/src/main/java/com/github/dedis/popstellar/ui/detail/LaoDetailActivity.java +++ b/fe2-android/app/src/main/java/com/github/dedis/popstellar/ui/detail/LaoDetailActivity.java @@ -13,8 +13,6 @@ import com.github.dedis.popstellar.R; import com.github.dedis.popstellar.databinding.LaoDetailActivityBinding; -import com.github.dedis.popstellar.model.objects.view.LaoView; -import com.github.dedis.popstellar.repository.RollCallRepository; import com.github.dedis.popstellar.repository.remote.GlobalNetworkManager; import com.github.dedis.popstellar.ui.detail.token.TokenListFragment; import com.github.dedis.popstellar.ui.detail.witness.WitnessingFragment; @@ -25,8 +23,6 @@ import com.github.dedis.popstellar.ui.socialmedia.SocialMediaActivity; import com.github.dedis.popstellar.utility.ActivityUtils; import com.github.dedis.popstellar.utility.Constants; -import com.github.dedis.popstellar.utility.error.ErrorUtils; -import com.github.dedis.popstellar.utility.error.UnknownLaoException; import com.google.gson.Gson; import java.security.GeneralSecurityException; @@ -47,8 +43,6 @@ public class LaoDetailActivity extends NavigationActivity { @Inject Gson gson; @Inject GlobalNetworkManager networkManager; - @Inject - RollCallRepository rollCallRepository; @Override protected void onCreate(@Nullable Bundle savedInstanceState) { @@ -56,21 +50,23 @@ protected void onCreate(@Nullable Bundle savedInstanceState) { binding = LaoDetailActivityBinding.inflate(getLayoutInflater()); setContentView(binding.getRoot()); navigationViewModel = viewModel = obtainViewModel(this); - setupDrawer( - binding.laoDetailNavigationDrawer, binding.laoTopAppBar, binding.laoDetailDrawerLayout); String laoId = Objects.requireNonNull(getIntent().getExtras()).getString(Constants.LAO_ID_EXTRA); viewModel.subscribeToLao(laoId); + setupDrawer( + laoId, + binding.laoDetailNavigationDrawer, + binding.laoTopAppBar, + binding.laoDetailDrawerLayout); + MainMenuTab tab = (MainMenuTab) getIntent().getExtras().get(Constants.TAB_EXTRA); if (tab == null) { tab = MainMenuTab.EVENTS; } navigationViewModel.setCurrentTab(tab); openTab(tab); - - viewModel.addDisposable(); } @Override @@ -141,12 +137,7 @@ private void openDigitalCashTab() { } private void openSocialMediaTab() { - try { - LaoView laoView = viewModel.getLaoView(); - startActivity(SocialMediaActivity.newIntent(this, viewModel.getLaoId(), laoView.getName())); - } catch (UnknownLaoException e) { - ErrorUtils.logAndShow(this, TAG, R.string.error_no_lao); - } + startActivity(SocialMediaActivity.newIntent(this, viewModel.getLaoId())); } public static LaoDetailViewModel obtainViewModel(FragmentActivity activity) { diff --git a/fe2-android/app/src/main/java/com/github/dedis/popstellar/ui/detail/LaoDetailViewModel.java b/fe2-android/app/src/main/java/com/github/dedis/popstellar/ui/detail/LaoDetailViewModel.java index f9557ecc96..70ee2e20e7 100644 --- a/fe2-android/app/src/main/java/com/github/dedis/popstellar/ui/detail/LaoDetailViewModel.java +++ b/fe2-android/app/src/main/java/com/github/dedis/popstellar/ui/detail/LaoDetailViewModel.java @@ -142,7 +142,7 @@ private boolean attendedOrOrganized(RollCall rollcall) { // find out if user has attended the rollcall try { PublicKey pk = wallet.generatePoPToken(laoId, rollcall.getPersistentId()).getPublicKey(); - return rollcall.getAttendees().contains(pk) || Boolean.TRUE.equals(isOrganizer().getValue()); + return rollcall.getAttendees().contains(pk) || Boolean.TRUE.equals(isOrganizer()); } catch (KeyGenerationException | UninitializedWalletException e) { Log.e(TAG, "failed to retrieve public key from wallet", e); return false; @@ -188,7 +188,7 @@ public Completable openElection(Election e) { Log.d(TAG, "opening election with name : " + e.getName()); LaoView laoView; try { - laoView = getLaoView(); + laoView = getLao(); } catch (UnknownLaoException unknownLaoException) { Log.d(TAG, LAO_FAILURE_MESSAGE); return Completable.error(new UnknownLaoException()); @@ -209,7 +209,7 @@ public Completable endElection(Election election) { Log.d(TAG, "ending election with name : " + election.getName()); LaoView laoView; try { - laoView = getLaoView(); + laoView = getLao(); } catch (UnknownLaoException e) { Log.d(TAG, LAO_FAILURE_MESSAGE); return Completable.error(new UnknownLaoException()); @@ -232,10 +232,10 @@ public Completable endElection(Election election) { * * @param votes the corresponding votes for that election */ - public Completable sendVote(List votes) { + public Completable sendVote(String electionId, List votes) { Election election; try { - election = electionRepo.getElection(laoId, currentElection); + election = electionRepo.getElection(laoId, electionId); } catch (UnknownElectionException e) { Log.d(TAG, "failed to retrieve current election"); return Completable.error(e); @@ -250,7 +250,7 @@ public Completable sendVote(List votes) { final LaoView laoView; try { - laoView = getLaoView(); + laoView = getLao(); } catch (UnknownLaoException e) { Log.d(TAG, LAO_FAILURE_MESSAGE); return Completable.error(new UnknownLaoException()); @@ -303,7 +303,7 @@ public Completable createNewElection( LaoView laoView; try { - laoView = getLaoView(); + laoView = getLao(); } catch (UnknownLaoException e) { Log.d(TAG, LAO_FAILURE_MESSAGE); return Completable.error(new UnknownLaoException()); @@ -342,7 +342,7 @@ public Single createNewRollCall( LaoView laoView; try { - laoView = getLaoView(); + laoView = getLao(); } catch (UnknownLaoException e) { Log.d(TAG, LAO_FAILURE_MESSAGE); return Single.error(new UnknownLaoException()); @@ -380,7 +380,7 @@ public Single sendConsensusElect( LaoView laoView; try { - laoView = getLaoView(); + laoView = getLao(); } catch (UnknownLaoException e) { Log.d(TAG, LAO_FAILURE_MESSAGE); return Single.error(new UnknownLaoException()); @@ -431,7 +431,7 @@ public Completable openRollCall(String id) { LaoView laoView; try { - laoView = getLaoView(); + laoView = getLao(); } catch (UnknownLaoException e) { Log.d(TAG, LAO_FAILURE_MESSAGE); return Completable.error(new UnknownLaoException()); @@ -482,7 +482,7 @@ public Completable closeRollCall() { LaoView laoView; try { - laoView = getLaoView(); + laoView = getLao(); } catch (UnknownLaoException e) { Log.d(TAG, LAO_FAILURE_MESSAGE); return Completable.error(new UnknownLaoException()); @@ -508,7 +508,7 @@ public Completable signMessage(WitnessMessage witnessMessage) { Log.d(TAG, "signing message with ID " + witnessMessage.getMessageId()); final LaoView laoView; try { - laoView = getLaoView(); + laoView = getLao(); } catch (UnknownLaoException e) { Log.d(TAG, LAO_FAILURE_MESSAGE); return Completable.error(new UnknownLaoException()); @@ -543,15 +543,8 @@ public Observable> getEvents() { return events; } - public LiveData getCurrentLao() { - return mCurrentLao; - } - - public String getLaoId() { - return laoId; - } - - public LaoView getLaoView() throws UnknownLaoException { + @Override + public LaoView getLao() throws UnknownLaoException { return laoRepository.getLaoView(laoId); } @@ -574,13 +567,11 @@ public LiveData getNbAttendees() { return mNbAttendees; } - public LiveData> getNodes() throws UnknownLaoException { - return LiveDataReactiveStreams.fromPublisher( - laoRepository - .getNodesByChannel(getLaoView().getChannel()) - .toFlowable(BackpressureStrategy.LATEST)); + public Observable> getNodes() throws UnknownLaoException { + return laoRepository.getNodesByChannel(getLao().getChannel()); } + public LiveData> getAttendeeScanConfirmEvent() { return mAttendeeScanConfirmEvent; } @@ -610,7 +601,7 @@ public Completable updateLaoWitnesses() { LaoView laoView; try { - laoView = getLaoView(); + laoView = getLao(); } catch (UnknownLaoException e) { Log.d(TAG, LAO_FAILURE_MESSAGE); return Completable.error(new UnknownLaoException()); @@ -689,87 +680,8 @@ public void subscribeToLao(String laoId) { .observeOn(AndroidSchedulers.mainThread()); } - public void subscribeToRollCalls(String laoId) { - disposables.add( - rollCallRepo - .getRollCallsObservableInLao(laoId) - .subscribeOn(Schedulers.io()) - .observeOn(AndroidSchedulers.mainThread()) - .subscribe( - idSet -> { - List rollCallList = - idSet.stream() - .map( - id -> { - try { - return rollCallRepo.getRollCallWithPersistentId(laoId, id); - } catch (UnknownRollCallException e) { - // Roll calls whose ids are in that list may not be absent - throw new IllegalStateException( - "Could not fetch roll call with id " + id); - } - }) - .collect(Collectors.toList()); - - mRollCalls.setValue(rollCallList); - - List attendedRollCall = - rollCallList.stream() - .filter(this::attendedOrOrganized) - .collect(Collectors.toList()); - Log.d(TAG, "attended roll calls: " + attendedRollCall); - - setIsAttendee( - attendedRollCall.contains(rollCallRepo.getLastClosedRollCall(laoId))); - }, - error -> Log.d(TAG, "Error updating Roll Call : " + error))); - } - - public void subscribeToElections(String laoId) { - - disposables.add( - electionRepo - .getElectionsObservable(laoId) - .subscribeOn(Schedulers.io()) - .map( - ids -> - ids.stream() - .map( - id -> { - try { - return electionRepo.getElectionObservable(laoId, id); - } catch (UnknownElectionException e) { - // Election whose ids are in that list may not be absent - throw new IllegalStateException( - "Could not fetch election with id " + id); - } - }) - .collect(Collectors.toList())) - .flatMap( - subjects -> - Observable.combineLatest( - subjects, - elections -> - // Sort the election list. That way it stays somewhat consistent over - // the updates - Arrays.stream(elections) - .map(Election.class::cast) - .sorted(Comparator.comparing(Election::getCreation).reversed()) - .collect(Collectors.toList()))) - .lift(suppressErrors(err -> Log.e(TAG, "Error creating election list : ", err))) - .observeOn(AndroidSchedulers.mainThread()) - .subscribe(mElections::setValue)); - } - - private void updateCurrentObjects() throws UnknownRollCallException { - if (currentRollCall != null) { - currentRollCall = - rollCallRepo.getRollCallWithPersistentId(laoId, currentRollCall.getPersistentId()); - } - } - - public PoPToken getCurrentPopToken() throws KeyException, UnknownLaoException { - return keyManager.getPoPToken(getLaoView(), currentRollCall); + public PoPToken getCurrentPopToken(RollCall rollCall) throws KeyException, UnknownLaoException { + return keyManager.getPoPToken(getLao(), rollCall); } public boolean isWalletSetup() { diff --git a/fe2-android/app/src/main/java/com/github/dedis/popstellar/ui/detail/event/consensus/ElectionStartFragment.java b/fe2-android/app/src/main/java/com/github/dedis/popstellar/ui/detail/event/consensus/ElectionStartFragment.java index 10e16190d0..f28566aff7 100644 --- a/fe2-android/app/src/main/java/com/github/dedis/popstellar/ui/detail/event/consensus/ElectionStartFragment.java +++ b/fe2-android/app/src/main/java/com/github/dedis/popstellar/ui/detail/event/consensus/ElectionStartFragment.java @@ -1,8 +1,12 @@ package com.github.dedis.popstellar.ui.detail.event.consensus; +import static io.reactivex.android.schedulers.AndroidSchedulers.mainThread; + import android.os.Bundle; import android.util.Log; -import android.view.*; +import android.view.LayoutInflater; +import android.view.View; +import android.view.ViewGroup; import android.widget.GridView; import androidx.annotation.NonNull; @@ -10,26 +14,31 @@ import com.github.dedis.popstellar.R; import com.github.dedis.popstellar.databinding.ElectionStartFragmentBinding; -import com.github.dedis.popstellar.model.objects.*; +import com.github.dedis.popstellar.model.objects.ConsensusNode; +import com.github.dedis.popstellar.model.objects.ElectInstance; import com.github.dedis.popstellar.model.objects.ElectInstance.State; +import com.github.dedis.popstellar.model.objects.Election; import com.github.dedis.popstellar.model.objects.view.LaoView; import com.github.dedis.popstellar.repository.ElectionRepository; import com.github.dedis.popstellar.ui.detail.LaoDetailActivity; import com.github.dedis.popstellar.ui.detail.LaoDetailViewModel; -import com.github.dedis.popstellar.utility.error.*; - -import java.text.SimpleDateFormat; -import java.time.Instant; -import java.util.*; - -import javax.inject.Inject; +import com.github.dedis.popstellar.utility.error.ErrorUtils; +import com.github.dedis.popstellar.utility.error.UnknownElectionException; +import com.github.dedis.popstellar.utility.error.UnknownLaoException; import dagger.hilt.android.AndroidEntryPoint; import io.reactivex.Observable; import io.reactivex.disposables.CompositeDisposable; import io.reactivex.functions.Consumer; -import static io.reactivex.android.schedulers.AndroidSchedulers.mainThread; +import java.text.SimpleDateFormat; +import java.time.Instant; +import java.util.Date; +import java.util.List; +import java.util.Locale; +import java.util.Optional; + +import javax.inject.Inject; /** * A simple {@link Fragment} subclass. Use the {@link ElectionStartFragment#newInstance} factory @@ -101,7 +110,7 @@ public View onCreateView( setupButtonListeners(viewModel, electionId); try { - LaoView laoView = viewModel.getLaoView(); + LaoView laoView = viewModel.getLao(); ownNode = laoView.getNode(viewModel.getPublicKey()); if (ownNode == null) { diff --git a/fe2-android/app/src/main/java/com/github/dedis/popstellar/ui/detail/event/election/fragments/CastVoteFragment.java b/fe2-android/app/src/main/java/com/github/dedis/popstellar/ui/detail/event/election/fragments/CastVoteFragment.java index d3d8f88e69..b2e8a241d9 100644 --- a/fe2-android/app/src/main/java/com/github/dedis/popstellar/ui/detail/event/election/fragments/CastVoteFragment.java +++ b/fe2-android/app/src/main/java/com/github/dedis/popstellar/ui/detail/event/election/fragments/CastVoteFragment.java @@ -107,7 +107,7 @@ public View onCreateView( private boolean setLaoName() { try { - LaoView laoView = viewModel.getLaoView(); + LaoView laoView = viewModel.getLao(); binding.castVoteLaoName.setText(laoView.getName()); return false; } catch (UnknownLaoException e) { diff --git a/fe2-android/app/src/main/java/com/github/dedis/popstellar/ui/detail/event/election/fragments/ElectionFragment.java b/fe2-android/app/src/main/java/com/github/dedis/popstellar/ui/detail/event/election/fragments/ElectionFragment.java index 42a584cd25..9079d076f4 100644 --- a/fe2-android/app/src/main/java/com/github/dedis/popstellar/ui/detail/event/election/fragments/ElectionFragment.java +++ b/fe2-android/app/src/main/java/com/github/dedis/popstellar/ui/detail/event/election/fragments/ElectionFragment.java @@ -350,8 +350,7 @@ private EnumMap buildActionTextMap() { private EnumMap buildManagementVisibilityMap() { // Only the organizer may start or end an election - int organizerVisibility = - Boolean.TRUE.equals(viewModel.isOrganizer().getValue()) ? View.VISIBLE : View.GONE; + int organizerVisibility = viewModel.isOrganizer() ? View.VISIBLE : View.GONE; EnumMap map = new EnumMap<>(EventState.class); map.put(EventState.CREATED, organizerVisibility); diff --git a/fe2-android/app/src/main/java/com/github/dedis/popstellar/ui/detail/event/election/fragments/ElectionResultFragment.java b/fe2-android/app/src/main/java/com/github/dedis/popstellar/ui/detail/event/election/fragments/ElectionResultFragment.java index 3d4dcff289..7c49a2970a 100644 --- a/fe2-android/app/src/main/java/com/github/dedis/popstellar/ui/detail/event/election/fragments/ElectionResultFragment.java +++ b/fe2-android/app/src/main/java/com/github/dedis/popstellar/ui/detail/event/election/fragments/ElectionResultFragment.java @@ -56,7 +56,7 @@ public View onCreateView( String electionId = requireArguments().getString(ELECTION_ID); try { - LaoView laoView = viewModel.getLaoView(); + LaoView laoView = viewModel.getLao(); Election election = electionRepository.getElection(viewModel.getLaoId(), electionId); // Setting the Lao Name diff --git a/fe2-android/app/src/main/java/com/github/dedis/popstellar/ui/detail/event/rollcall/RollCallFragment.java b/fe2-android/app/src/main/java/com/github/dedis/popstellar/ui/detail/event/rollcall/RollCallFragment.java index a450a2c09a..87f3dce03b 100644 --- a/fe2-android/app/src/main/java/com/github/dedis/popstellar/ui/detail/event/rollcall/RollCallFragment.java +++ b/fe2-android/app/src/main/java/com/github/dedis/popstellar/ui/detail/event/rollcall/RollCallFragment.java @@ -166,7 +166,7 @@ private void setUpStateDependantContent() { setupTime(); // Suggested time is updated in case of early/late close/open/reopen EventState rcState = rollCall.getState(); - boolean isOrganizer = Boolean.TRUE.equals(viewModel.isOrganizer().getValue()); + boolean isOrganizer = viewModel.isOrganizer(); binding.rollCallFragmentTitle.setText(rollCall.getName()); binding.rollCallManagementButton.setVisibility(isOrganizer ? View.VISIBLE : View.GONE); @@ -221,8 +221,7 @@ private void retrieveAndDisplayPublicKey() { PopTokenData data = new PopTokenData(new PublicKey(pk)); Bitmap myBitmap = QRCode.from(gson.toJson(data)).bitmap(); binding.rollCallPkQrCode.setImageBitmap(myBitmap); - binding.rollCallPkQrCode.setVisibility( - Boolean.TRUE.equals(viewModel.isOrganizer().getValue()) ? View.INVISIBLE : View.VISIBLE); + binding.rollCallPkQrCode.setVisibility(viewModel.isOrganizer() ? View.INVISIBLE : View.VISIBLE); } private EnumMap buildManagementTextMap() { From 9812aba23356b43e09566e8445046e9f6466682b Mon Sep 17 00:00:00 2001 From: Johann Pluss Date: Sat, 14 Jan 2023 20:21:59 +0100 Subject: [PATCH 24/41] Fix tests MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Johann Plüss --- .../ui/detail/LaoDetailFragment.java | 20 ++++++++++++---- .../ui/socialmedia/SocialMediaActivity.java | 2 -- .../main/res/layout/lao_detail_fragment.xml | 11 +-------- .../ui/socialmedia/ChirpListAdapterTest.java | 23 ++++++++++--------- 4 files changed, 28 insertions(+), 28 deletions(-) diff --git a/fe2-android/app/src/main/java/com/github/dedis/popstellar/ui/detail/LaoDetailFragment.java b/fe2-android/app/src/main/java/com/github/dedis/popstellar/ui/detail/LaoDetailFragment.java index 7d87e53851..8128e5a94a 100644 --- a/fe2-android/app/src/main/java/com/github/dedis/popstellar/ui/detail/LaoDetailFragment.java +++ b/fe2-android/app/src/main/java/com/github/dedis/popstellar/ui/detail/LaoDetailFragment.java @@ -2,7 +2,9 @@ import android.os.Bundle; import android.util.Log; -import android.view.*; +import android.view.LayoutInflater; +import android.view.View; +import android.view.ViewGroup; import androidx.annotation.NonNull; import androidx.annotation.Nullable; @@ -13,17 +15,20 @@ import com.github.dedis.popstellar.R; import com.github.dedis.popstellar.databinding.LaoDetailFragmentBinding; +import com.github.dedis.popstellar.model.Role; import com.github.dedis.popstellar.model.objects.event.EventType; -import com.github.dedis.popstellar.ui.detail.event.*; +import com.github.dedis.popstellar.ui.detail.event.EventListAdapter; +import com.github.dedis.popstellar.ui.detail.event.EventListDivider; +import com.github.dedis.popstellar.ui.detail.event.LaoDetailAnimation; import com.github.dedis.popstellar.ui.detail.event.election.fragments.ElectionSetupFragment; import com.github.dedis.popstellar.ui.detail.event.rollcall.RollCallCreationFragment; import com.google.android.material.floatingactionbutton.FloatingActionButton; import com.google.gson.Gson; -import javax.inject.Inject; - import dagger.hilt.android.AndroidEntryPoint; +import javax.inject.Inject; + /** Fragment used to display the LAO Detail UI */ @AndroidEntryPoint public class LaoDetailFragment extends Fragment { @@ -49,11 +54,16 @@ public View onCreateView( binding = LaoDetailFragmentBinding.inflate(inflater, container, false); viewModel = LaoDetailActivity.obtainViewModel(requireActivity()); - binding.setViewModel(viewModel); binding.setLifecycleOwner(requireActivity()); FloatingActionButton addButton = binding.addEvent; addButton.setOnClickListener(fabListener); + viewModel + .getRole() + .observe( + requireActivity(), + role -> + addButton.setVisibility(role.equals(Role.ORGANIZER) ? View.VISIBLE : View.GONE)); binding.addElection.setOnClickListener(openCreateEvent(EventType.ELECTION)); binding.addElectionText.setOnClickListener(openCreateEvent(EventType.ELECTION)); diff --git a/fe2-android/app/src/main/java/com/github/dedis/popstellar/ui/socialmedia/SocialMediaActivity.java b/fe2-android/app/src/main/java/com/github/dedis/popstellar/ui/socialmedia/SocialMediaActivity.java index 5f4eed5816..09e9fc08c8 100644 --- a/fe2-android/app/src/main/java/com/github/dedis/popstellar/ui/socialmedia/SocialMediaActivity.java +++ b/fe2-android/app/src/main/java/com/github/dedis/popstellar/ui/socialmedia/SocialMediaActivity.java @@ -34,8 +34,6 @@ public class SocialMediaActivity extends NavigationActivity { private SocialMediaActivityBinding binding; public static final String TAG = SocialMediaActivity.class.getSimpleName(); - public static final String LAO_ID = "LAO_ID"; - public static final String LAO_NAME = "LAO_NAME"; @Override protected void onCreate(Bundle savedInstanceState) { diff --git a/fe2-android/app/src/main/res/layout/lao_detail_fragment.xml b/fe2-android/app/src/main/res/layout/lao_detail_fragment.xml index f5ee95b385..3fc988f2b5 100644 --- a/fe2-android/app/src/main/res/layout/lao_detail_fragment.xml +++ b/fe2-android/app/src/main/res/layout/lao_detail_fragment.xml @@ -2,15 +2,6 @@ - - - - - - - activityScenarioRule = new ActivityScenarioRule<>(intent); @@ -42,16 +53,6 @@ public class ChirpListAdapterTest { private static final MessageID MESSAGE_ID_1 = generateMessageID(); private static final MessageID MESSAGE_ID_2 = generateMessageID(); - private static final KeyPair SENDER_KEY_1 = generatePoPToken(); - private static final KeyPair SENDER_KEY_2 = generatePoPToken(); - - private static final PublicKey SENDER_1 = SENDER_KEY_1.getPublicKey(); - private static final PublicKey SENDER_2 = SENDER_KEY_2.getPublicKey(); - - private static final long CREATION_TIME = 1631280815; - private static final String LAO_NAME = "laoName"; - private static final String LAO_ID = Lao.generateLaoId(SENDER_1, CREATION_TIME, LAO_NAME); - private static final Channel CHIRP_CHANNEL_1 = Channel.getLaoChannel(LAO_ID).subChannel("social").subChannel(SENDER_1.getEncoded()); private static final Channel CHIRP_CHANNEL_2 = From f9f28e6db5a2b7419c63372d2f3b3441420707c2 Mon Sep 17 00:00:00 2001 From: Johann Pluss Date: Sat, 14 Jan 2023 22:45:36 +0100 Subject: [PATCH 25/41] Removed unused fragment MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Johann Plüss --- .../ui/detail/IdentityFragment.java | 113 ------------------ 1 file changed, 113 deletions(-) delete mode 100644 fe2-android/app/src/main/java/com/github/dedis/popstellar/ui/detail/IdentityFragment.java diff --git a/fe2-android/app/src/main/java/com/github/dedis/popstellar/ui/detail/IdentityFragment.java b/fe2-android/app/src/main/java/com/github/dedis/popstellar/ui/detail/IdentityFragment.java deleted file mode 100644 index 1b29073c51..0000000000 --- a/fe2-android/app/src/main/java/com/github/dedis/popstellar/ui/detail/IdentityFragment.java +++ /dev/null @@ -1,113 +0,0 @@ -package com.github.dedis.popstellar.ui.detail; - -import android.graphics.Bitmap; -import android.os.Bundle; -import android.view.*; -import android.widget.*; - -import androidx.annotation.NonNull; -import androidx.annotation.Nullable; -import androidx.fragment.app.Fragment; - -import com.github.dedis.popstellar.R; -import com.github.dedis.popstellar.model.objects.security.PublicKey; -import com.github.dedis.popstellar.model.qrcode.MainPublicKeyData; -import com.google.gson.Gson; - -import net.glxn.qrgen.android.QRCode; - -import javax.inject.Inject; - -import dagger.hilt.android.AndroidEntryPoint; - -/** - * Represents the identity of a user within an organization (which allows users to “wear different - * hats” in different organizations) TODO : For the moment, the goal of this UI is just to show a QR - * code, but in the future, it will be needed to store identity information somewhere to make it - * dependent of the current user and LAO - */ -@AndroidEntryPoint -public class IdentityFragment extends Fragment { - - public static final String TAG = IdentityFragment.class.getSimpleName(); - - @Inject Gson gson; - - public static final String PUBLIC_KEY = "public key"; - private EditText identityNameEditText; - private EditText identityTitleEditText; - private EditText identityOrganizationEditText; - private EditText identityEmailEditText; - private EditText identityPhoneEditText; - private ImageView qrCode; - - public static IdentityFragment newInstance(PublicKey publicKey) { - IdentityFragment identityFragment = new IdentityFragment(); - Bundle bundle = new Bundle(1); - bundle.putString(PUBLIC_KEY, publicKey.getEncoded()); - identityFragment.setArguments(bundle); - return identityFragment; - } - - @Nullable - @Override - public View onCreateView( - @NonNull LayoutInflater inflater, - @Nullable ViewGroup container, - @Nullable Bundle savedInstanceState) { - View view = inflater.inflate(R.layout.identity_fragment, container, false); - // TODO : The QR code does not appear at all unless the Name field is non-empty - // and not all whitespace. - CheckBox anonymousCheckBox = view.findViewById(R.id.checkbox_anonymous); - qrCode = view.findViewById(R.id.qr_code); - identityEmailEditText = view.findViewById(R.id.identity_email); - identityNameEditText = view.findViewById(R.id.identity_name); - identityOrganizationEditText = view.findViewById(R.id.identity_organization); - identityPhoneEditText = view.findViewById(R.id.identity_phone); - identityTitleEditText = view.findViewById(R.id.identity_title); - - hideIdentityInformation(); - - anonymousCheckBox.setOnCheckedChangeListener( - (buttonView, isChecked) -> { - if (isChecked) { - hideIdentityInformation(); - } else { - qrCode.setVisibility(View.VISIBLE); - identityEmailEditText.setVisibility(View.VISIBLE); - identityNameEditText.setVisibility(View.VISIBLE); - identityOrganizationEditText.setVisibility(View.VISIBLE); - identityPhoneEditText.setVisibility(View.VISIBLE); - identityTitleEditText.setVisibility(View.VISIBLE); - } - }); - - // for now we use the user's public key to generate the QR code - // TODO: In the future use Wallet with user's token - String pk = this.requireArguments().getString(PUBLIC_KEY); - identityNameEditText.setText(pk); - - MainPublicKeyData data = new MainPublicKeyData(new PublicKey(pk)); - Bitmap myBitmap = QRCode.from(gson.toJson(data)).bitmap(); - qrCode.setImageBitmap(myBitmap); - - return view; - } - - @Override - public void onResume() { - super.onResume(); - LaoDetailViewModel viewModel = LaoDetailActivity.obtainViewModel(requireActivity()); - viewModel.setPageTitle(R.string.tab_identity); - } - - /** Hide fields when user wants to be anonymous */ - private void hideIdentityInformation() { - qrCode.setVisibility(View.GONE); - identityEmailEditText.setVisibility(View.GONE); - identityNameEditText.setVisibility(View.GONE); - identityOrganizationEditText.setVisibility(View.GONE); - identityPhoneEditText.setVisibility(View.GONE); - identityTitleEditText.setVisibility(View.GONE); - } -} From b743eb9c81ac7d78918a068aef012a9db7bee3e1 Mon Sep 17 00:00:00 2001 From: Johann Pluss Date: Sat, 14 Jan 2023 23:05:48 +0100 Subject: [PATCH 26/41] Handle back arrow MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Johann Plüss --- .../dedis/popstellar/ui/detail/InviteFragment.java | 1 + .../popstellar/ui/detail/LaoDetailActivity.java | 5 +++++ .../popstellar/ui/detail/LaoDetailFragment.java | 13 +++++-------- .../event/election/fragments/CastVoteFragment.java | 1 + .../event/election/fragments/ElectionFragment.java | 1 + .../election/fragments/ElectionResultFragment.java | 1 + .../election/fragments/ElectionSetupFragment.java | 1 + .../event/rollcall/RollCallCreationFragment.java | 1 + .../ui/detail/event/rollcall/RollCallFragment.java | 1 + .../popstellar/ui/detail/token/TokenFragment.java | 1 + .../ui/detail/token/TokenListFragment.java | 1 + .../ui/detail/witness/WitnessingFragment.java | 1 + 12 files changed, 20 insertions(+), 8 deletions(-) diff --git a/fe2-android/app/src/main/java/com/github/dedis/popstellar/ui/detail/InviteFragment.java b/fe2-android/app/src/main/java/com/github/dedis/popstellar/ui/detail/InviteFragment.java index 68b9e66eb9..66339d44f8 100644 --- a/fe2-android/app/src/main/java/com/github/dedis/popstellar/ui/detail/InviteFragment.java +++ b/fe2-android/app/src/main/java/com/github/dedis/popstellar/ui/detail/InviteFragment.java @@ -75,5 +75,6 @@ public View onCreateView( public void onResume() { super.onResume(); viewModel.setPageTitle(R.string.invite); + viewModel.setIsTab(true); } } diff --git a/fe2-android/app/src/main/java/com/github/dedis/popstellar/ui/detail/LaoDetailActivity.java b/fe2-android/app/src/main/java/com/github/dedis/popstellar/ui/detail/LaoDetailActivity.java index 2f40a72c4f..cd1961524a 100644 --- a/fe2-android/app/src/main/java/com/github/dedis/popstellar/ui/detail/LaoDetailActivity.java +++ b/fe2-android/app/src/main/java/com/github/dedis/popstellar/ui/detail/LaoDetailActivity.java @@ -82,6 +82,11 @@ public void onStop() { } } + @Override + public void onBackPressed() { + openEventsTab(); + } + @Override protected boolean openTab(MainMenuTab tab) { switch (tab) { diff --git a/fe2-android/app/src/main/java/com/github/dedis/popstellar/ui/detail/LaoDetailFragment.java b/fe2-android/app/src/main/java/com/github/dedis/popstellar/ui/detail/LaoDetailFragment.java index 8128e5a94a..137e556804 100644 --- a/fe2-android/app/src/main/java/com/github/dedis/popstellar/ui/detail/LaoDetailFragment.java +++ b/fe2-android/app/src/main/java/com/github/dedis/popstellar/ui/detail/LaoDetailFragment.java @@ -2,9 +2,7 @@ import android.os.Bundle; import android.util.Log; -import android.view.LayoutInflater; -import android.view.View; -import android.view.ViewGroup; +import android.view.*; import androidx.annotation.NonNull; import androidx.annotation.Nullable; @@ -17,18 +15,16 @@ import com.github.dedis.popstellar.databinding.LaoDetailFragmentBinding; import com.github.dedis.popstellar.model.Role; import com.github.dedis.popstellar.model.objects.event.EventType; -import com.github.dedis.popstellar.ui.detail.event.EventListAdapter; -import com.github.dedis.popstellar.ui.detail.event.EventListDivider; -import com.github.dedis.popstellar.ui.detail.event.LaoDetailAnimation; +import com.github.dedis.popstellar.ui.detail.event.*; import com.github.dedis.popstellar.ui.detail.event.election.fragments.ElectionSetupFragment; import com.github.dedis.popstellar.ui.detail.event.rollcall.RollCallCreationFragment; import com.google.android.material.floatingactionbutton.FloatingActionButton; import com.google.gson.Gson; -import dagger.hilt.android.AndroidEntryPoint; - import javax.inject.Inject; +import dagger.hilt.android.AndroidEntryPoint; + /** Fragment used to display the LAO Detail UI */ @AndroidEntryPoint public class LaoDetailFragment extends Fragment { @@ -123,6 +119,7 @@ public void onViewCreated(@NonNull View view, @Nullable Bundle savedInstanceStat public void onResume() { super.onResume(); viewModel.setPageTitle(R.string.event_list); + viewModel.setIsTab(true); } private void setupEventListAdapter() { diff --git a/fe2-android/app/src/main/java/com/github/dedis/popstellar/ui/detail/event/election/fragments/CastVoteFragment.java b/fe2-android/app/src/main/java/com/github/dedis/popstellar/ui/detail/event/election/fragments/CastVoteFragment.java index b2e8a241d9..58c891f72e 100644 --- a/fe2-android/app/src/main/java/com/github/dedis/popstellar/ui/detail/event/election/fragments/CastVoteFragment.java +++ b/fe2-android/app/src/main/java/com/github/dedis/popstellar/ui/detail/event/election/fragments/CastVoteFragment.java @@ -177,5 +177,6 @@ private void castVote(View voteButton) { public void onResume() { super.onResume(); viewModel.setPageTitle(R.string.vote); + viewModel.setIsTab(false); } } diff --git a/fe2-android/app/src/main/java/com/github/dedis/popstellar/ui/detail/event/election/fragments/ElectionFragment.java b/fe2-android/app/src/main/java/com/github/dedis/popstellar/ui/detail/event/election/fragments/ElectionFragment.java index 9079d076f4..1a61f9e078 100644 --- a/fe2-android/app/src/main/java/com/github/dedis/popstellar/ui/detail/event/election/fragments/ElectionFragment.java +++ b/fe2-android/app/src/main/java/com/github/dedis/popstellar/ui/detail/event/election/fragments/ElectionFragment.java @@ -207,6 +207,7 @@ public void onViewCreated(@NonNull View view, @Nullable Bundle savedInstanceStat public void onResume() { super.onResume(); viewModel.setPageTitle(R.string.election_title); + viewModel.setIsTab(false); } @Override diff --git a/fe2-android/app/src/main/java/com/github/dedis/popstellar/ui/detail/event/election/fragments/ElectionResultFragment.java b/fe2-android/app/src/main/java/com/github/dedis/popstellar/ui/detail/event/election/fragments/ElectionResultFragment.java index 7c49a2970a..3da5498b06 100644 --- a/fe2-android/app/src/main/java/com/github/dedis/popstellar/ui/detail/event/election/fragments/ElectionResultFragment.java +++ b/fe2-android/app/src/main/java/com/github/dedis/popstellar/ui/detail/event/election/fragments/ElectionResultFragment.java @@ -89,5 +89,6 @@ public void onResume() { super.onResume(); LaoDetailViewModel viewModel = LaoDetailActivity.obtainViewModel(requireActivity()); viewModel.setPageTitle(R.string.election_result_title); + viewModel.setIsTab(false); } } diff --git a/fe2-android/app/src/main/java/com/github/dedis/popstellar/ui/detail/event/election/fragments/ElectionSetupFragment.java b/fe2-android/app/src/main/java/com/github/dedis/popstellar/ui/detail/event/election/fragments/ElectionSetupFragment.java index bc2c226d63..f48ca2e60f 100644 --- a/fe2-android/app/src/main/java/com/github/dedis/popstellar/ui/detail/event/election/fragments/ElectionSetupFragment.java +++ b/fe2-android/app/src/main/java/com/github/dedis/popstellar/ui/detail/event/election/fragments/ElectionSetupFragment.java @@ -187,6 +187,7 @@ public void onViewCreated(@NonNull View view, @Nullable Bundle savedInstanceStat public void onResume() { super.onResume(); viewModel.setPageTitle(R.string.election_setup_title); + viewModel.setIsTab(false); } /** Setups the submit button that creates the new election */ diff --git a/fe2-android/app/src/main/java/com/github/dedis/popstellar/ui/detail/event/rollcall/RollCallCreationFragment.java b/fe2-android/app/src/main/java/com/github/dedis/popstellar/ui/detail/event/rollcall/RollCallCreationFragment.java index 80a1ee2886..3065f26b95 100644 --- a/fe2-android/app/src/main/java/com/github/dedis/popstellar/ui/detail/event/rollcall/RollCallCreationFragment.java +++ b/fe2-android/app/src/main/java/com/github/dedis/popstellar/ui/detail/event/rollcall/RollCallCreationFragment.java @@ -105,6 +105,7 @@ public void onViewCreated(@NonNull View view, @Nullable Bundle savedInstanceStat public void onResume() { super.onResume(); viewModel.setPageTitle(R.string.roll_call_setup_title); + viewModel.setIsTab(false); } private void setupConfirmButton() { diff --git a/fe2-android/app/src/main/java/com/github/dedis/popstellar/ui/detail/event/rollcall/RollCallFragment.java b/fe2-android/app/src/main/java/com/github/dedis/popstellar/ui/detail/event/rollcall/RollCallFragment.java index 87f3dce03b..b1a105aec4 100644 --- a/fe2-android/app/src/main/java/com/github/dedis/popstellar/ui/detail/event/rollcall/RollCallFragment.java +++ b/fe2-android/app/src/main/java/com/github/dedis/popstellar/ui/detail/event/rollcall/RollCallFragment.java @@ -155,6 +155,7 @@ public View onCreateView( public void onResume() { super.onResume(); viewModel.setPageTitle(R.string.roll_call_title); + viewModel.setIsTab(false); try { rollCall = viewModel.getRollCall(requireArguments().getString(ROLL_CALL_ID)); } catch (UnknownRollCallException e) { diff --git a/fe2-android/app/src/main/java/com/github/dedis/popstellar/ui/detail/token/TokenFragment.java b/fe2-android/app/src/main/java/com/github/dedis/popstellar/ui/detail/token/TokenFragment.java index b1a9638c0b..73386a1772 100644 --- a/fe2-android/app/src/main/java/com/github/dedis/popstellar/ui/detail/token/TokenFragment.java +++ b/fe2-android/app/src/main/java/com/github/dedis/popstellar/ui/detail/token/TokenFragment.java @@ -59,6 +59,7 @@ public static TokenFragment newInstance(String rcId) { public void onResume() { super.onResume(); viewModel.setPageTitle(R.string.token); + viewModel.setIsTab(false); } @Override diff --git a/fe2-android/app/src/main/java/com/github/dedis/popstellar/ui/detail/token/TokenListFragment.java b/fe2-android/app/src/main/java/com/github/dedis/popstellar/ui/detail/token/TokenListFragment.java index 4711c003c1..0d1e5e9ec9 100644 --- a/fe2-android/app/src/main/java/com/github/dedis/popstellar/ui/detail/token/TokenListFragment.java +++ b/fe2-android/app/src/main/java/com/github/dedis/popstellar/ui/detail/token/TokenListFragment.java @@ -42,6 +42,7 @@ public TokenListFragment() { public void onResume() { super.onResume(); viewModel.setPageTitle(R.string.tokens); + viewModel.setIsTab(true); } @Nullable diff --git a/fe2-android/app/src/main/java/com/github/dedis/popstellar/ui/detail/witness/WitnessingFragment.java b/fe2-android/app/src/main/java/com/github/dedis/popstellar/ui/detail/witness/WitnessingFragment.java index 26b3faa11c..400c471c18 100644 --- a/fe2-android/app/src/main/java/com/github/dedis/popstellar/ui/detail/witness/WitnessingFragment.java +++ b/fe2-android/app/src/main/java/com/github/dedis/popstellar/ui/detail/witness/WitnessingFragment.java @@ -47,5 +47,6 @@ public void onResume() { super.onResume(); LaoDetailViewModel viewModel = LaoDetailActivity.obtainViewModel(requireActivity()); viewModel.setPageTitle(R.string.witnessing); + viewModel.setIsTab(true); } } From 742c53c2451c7388c7fee648f259471bbdbdd927 Mon Sep 17 00:00:00 2001 From: Johann Pluss Date: Sat, 14 Jan 2023 23:06:05 +0100 Subject: [PATCH 27/41] Improve naming of events tab MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Johann Plüss --- fe2-android/app/src/main/res/values/strings.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/fe2-android/app/src/main/res/values/strings.xml b/fe2-android/app/src/main/res/values/strings.xml index eddbdd1fca..6f09f525ab 100644 --- a/fe2-android/app/src/main/res/values/strings.xml +++ b/fe2-android/app/src/main/res/values/strings.xml @@ -17,7 +17,7 @@ Identity Social Media Digital Cash - Event List + Events Witnessing Invite Tokens From b379911e5a58955ce011c1e49eda9f82a697ef41 Mon Sep 17 00:00:00 2001 From: Johann Pluss Date: Sat, 14 Jan 2023 23:15:08 +0100 Subject: [PATCH 28/41] Improve navigation icons MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Johann Plüss --- .../ui/navigation/NavigationActivity.java | 2 +- .../app/src/main/res/drawable/back_arrow_icon.xml | 11 +++++++++++ .../src/main/res/drawable/menu_drawer_icon.xml | 15 --------------- .../app/src/main/res/drawable/menu_icon.xml | 15 +++++++++++++++ .../res/layout/digital_cash_main_activity.xml | 2 +- .../src/main/res/layout/lao_detail_activity.xml | 2 +- .../src/main/res/layout/social_media_activity.xml | 2 +- 7 files changed, 30 insertions(+), 19 deletions(-) create mode 100644 fe2-android/app/src/main/res/drawable/back_arrow_icon.xml delete mode 100644 fe2-android/app/src/main/res/drawable/menu_drawer_icon.xml create mode 100644 fe2-android/app/src/main/res/drawable/menu_icon.xml diff --git a/fe2-android/app/src/main/java/com/github/dedis/popstellar/ui/navigation/NavigationActivity.java b/fe2-android/app/src/main/java/com/github/dedis/popstellar/ui/navigation/NavigationActivity.java index 261a1616c2..a1a20367f1 100644 --- a/fe2-android/app/src/main/java/com/github/dedis/popstellar/ui/navigation/NavigationActivity.java +++ b/fe2-android/app/src/main/java/com/github/dedis/popstellar/ui/navigation/NavigationActivity.java @@ -83,7 +83,7 @@ protected void setupDrawer( this, isTab -> toolbar.setNavigationIcon( - isTab ? R.drawable.menu_drawer_icon : R.drawable.ic_back_arrow)); + isTab ? R.drawable.menu_icon : R.drawable.back_arrow_icon)); // Observe changes to the tab selected navigationViewModel diff --git a/fe2-android/app/src/main/res/drawable/back_arrow_icon.xml b/fe2-android/app/src/main/res/drawable/back_arrow_icon.xml new file mode 100644 index 0000000000..ab7e1d6373 --- /dev/null +++ b/fe2-android/app/src/main/res/drawable/back_arrow_icon.xml @@ -0,0 +1,11 @@ + + + diff --git a/fe2-android/app/src/main/res/drawable/menu_drawer_icon.xml b/fe2-android/app/src/main/res/drawable/menu_drawer_icon.xml deleted file mode 100644 index fcc5a42f00..0000000000 --- a/fe2-android/app/src/main/res/drawable/menu_drawer_icon.xml +++ /dev/null @@ -1,15 +0,0 @@ - - - - - diff --git a/fe2-android/app/src/main/res/drawable/menu_icon.xml b/fe2-android/app/src/main/res/drawable/menu_icon.xml new file mode 100644 index 0000000000..64fecd8fde --- /dev/null +++ b/fe2-android/app/src/main/res/drawable/menu_icon.xml @@ -0,0 +1,15 @@ + + + + + diff --git a/fe2-android/app/src/main/res/layout/digital_cash_main_activity.xml b/fe2-android/app/src/main/res/layout/digital_cash_main_activity.xml index ca0533866c..05c8e2b358 100644 --- a/fe2-android/app/src/main/res/layout/digital_cash_main_activity.xml +++ b/fe2-android/app/src/main/res/layout/digital_cash_main_activity.xml @@ -47,7 +47,7 @@ android:layout_width="match_parent" android:layout_height="?attr/actionBarSize" app:navigationContentDescription="Open Menu" - app:navigationIcon="@drawable/menu_drawer_icon" /> + app:navigationIcon="@drawable/menu_icon" /> diff --git a/fe2-android/app/src/main/res/layout/lao_detail_activity.xml b/fe2-android/app/src/main/res/layout/lao_detail_activity.xml index f4f45bd8d1..4c8aed6f92 100644 --- a/fe2-android/app/src/main/res/layout/lao_detail_activity.xml +++ b/fe2-android/app/src/main/res/layout/lao_detail_activity.xml @@ -26,7 +26,7 @@ android:layout_width="match_parent" android:layout_height="?attr/actionBarSize" app:navigationContentDescription="Open Menu" - app:navigationIcon="@drawable/menu_drawer_icon" /> + app:navigationIcon="@drawable/menu_icon" /> + app:navigationIcon="@drawable/menu_icon" /> From 4fc78835d79018e609cb117bfb89a9b7c41dd2da Mon Sep 17 00:00:00 2001 From: Johann Pluss Date: Sat, 14 Jan 2023 23:35:24 +0100 Subject: [PATCH 29/41] Remove test MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Johann Plüss --- .../ui/detail/LaoDetailActivityTest.java | 131 ------------------ 1 file changed, 131 deletions(-) delete mode 100644 fe2-android/app/src/test/ui/robolectric/com/github/dedis/popstellar/ui/detail/LaoDetailActivityTest.java diff --git a/fe2-android/app/src/test/ui/robolectric/com/github/dedis/popstellar/ui/detail/LaoDetailActivityTest.java b/fe2-android/app/src/test/ui/robolectric/com/github/dedis/popstellar/ui/detail/LaoDetailActivityTest.java deleted file mode 100644 index f66d42b255..0000000000 --- a/fe2-android/app/src/test/ui/robolectric/com/github/dedis/popstellar/ui/detail/LaoDetailActivityTest.java +++ /dev/null @@ -1,131 +0,0 @@ -// package com.github.dedis.popstellar.ui.detail; -// -// import androidx.test.espresso.contrib.DrawerActions; -// import androidx.test.espresso.contrib.NavigationViewActions; -// import androidx.test.espresso.intent.Intents; -// import androidx.test.ext.junit.rules.ActivityScenarioRule; -// import androidx.test.ext.junit.runners.AndroidJUnit4; -// -// import com.github.dedis.popstellar.model.objects.Lao; -// import com.github.dedis.popstellar.model.objects.Wallet; -// import com.github.dedis.popstellar.model.objects.view.LaoView; -// import com.github.dedis.popstellar.repository.LAORepository; -// import com.github.dedis.popstellar.repository.remote.GlobalNetworkManager; -// import com.github.dedis.popstellar.testutils.*; -// import com.github.dedis.popstellar.ui.digitalcash.DigitalCashActivity; -// import com.github.dedis.popstellar.ui.socialmedia.SocialMediaActivity; -// import com.github.dedis.popstellar.utility.error.UnknownLaoException; -// import com.google.gson.Gson; -// -// import org.junit.Rule; -// import org.junit.Test; -// import org.junit.rules.ExternalResource; -// import org.junit.runner.RunWith; -// import org.mockito.Mock; -// import org.mockito.junit.MockitoJUnit; -// import org.mockito.junit.MockitoTestRule; -// -// import java.security.GeneralSecurityException; -// -// import javax.inject.Inject; -// -// import dagger.hilt.android.testing.*; -// import io.reactivex.subjects.BehaviorSubject; -// -// import static androidx.test.espresso.action.ViewActions.click; -// import static androidx.test.espresso.assertion.ViewAssertions.matches; -// import static androidx.test.espresso.intent.Intents.intended; -// import static androidx.test.espresso.intent.matcher.IntentMatchers.hasComponent; -// import static androidx.test.espresso.matcher.ViewMatchers.withChild; -// import static androidx.test.espresso.matcher.ViewMatchers.withId; -// import static com.github.dedis.popstellar.testutils.pages.detail.LaoDetailActivityPageObject.*; -// import static org.mockito.ArgumentMatchers.any; -// import static org.mockito.ArgumentMatchers.anyString; -// import static org.mockito.Mockito.when; -// -// @HiltAndroidTest -// @RunWith(AndroidJUnit4.class) -// public class LaoDetailActivityTest { -// -// private static final Lao LAO = new Lao("LAO", Base64DataUtils.generatePublicKey(), 10223421); -// private static final String LAO_ID = LAO.getId(); -// -// @Inject GlobalNetworkManager networkManager; -// @Inject Gson gson; -// -// @BindValue @Mock LAORepository laoRepository; -// @BindValue @Mock Wallet wallet; -// -// @Rule(order = 0) -// public final MockitoTestRule mockitoRule = MockitoJUnit.testRule(this); -// -// @Rule(order = 1) -// public final HiltAndroidRule hiltAndroidRule = new HiltAndroidRule(this); -// -// @Rule(order = 2) -// public final ExternalResource setupRule = -// new ExternalResource() { -// @Override -// protected void before() throws UnknownLaoException, GeneralSecurityException { -// hiltAndroidRule.inject(); -// when(laoRepository.getLao(any())).thenAnswer(invocation -> new LaoView(LAO)); -// -// when(laoRepository.getLaoObservable(anyString())) -// .thenReturn(BehaviorSubject.createDefault(new LaoView(LAO))); -// -// when(wallet.exportSeed()) -// .thenReturn( -// new String[] { -// "jar", -// "together", -// "minor", -// "alley", -// "glow", -// "hybrid", -// "village", -// "creek", -// "meadow", -// "atom", -// "travel", -// "bracket" -// }); -// } -// }; -// -// @Rule(order = 3) -// public ActivityScenarioRule activityScenarioRule = -// new ActivityScenarioRule<>( -// IntentUtils.createIntent( -// LaoDetailActivity.class, -// new BundleBuilder() -// .putString(laoIdExtra(), LAO_ID) -// .putString(fragmentToOpenExtra(), laoDetailValue()) -// .build())); -// -// -// @Test -// public void witnessingTabShowsWitnessTab() { -// witnessButton().perform(click()); -// fragmentContainer().check(matches(withChild(withId(witnessingFragmentId())))); -// } -// -// @Test -// public void socialMediaNavOpensSocialMediaActivity() { -// Intents.init(); -// socialMediaButton().perform(click()); -// intended(hasComponent(SocialMediaActivity.class.getName())); -// Intents.release(); -// } -// -// @Test -// public void digitalCashNavOpensActivity() { -// drawerLayout().perform(DrawerActions.open()); -// Intents.init(); -// navigationDrawer().perform(NavigationViewActions.navigateTo(digitalCashMenu())); -// intended(hasComponent(DigitalCashActivity.class.getName())); -// Intents.release(); -// } -// -// private void openDrawer(){ -// } -// } From 724a171b05b5161604d3476934dc032cb693d0b4 Mon Sep 17 00:00:00 2001 From: Johann Pluss Date: Sat, 14 Jan 2023 23:35:51 +0100 Subject: [PATCH 30/41] Add Invite test MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Johann Plüss --- .../detail/InviteFragmentPageObject.java | 27 ++++++ .../ui/detail/InviteFragmentTest.java | 88 +++++++++++++++++++ 2 files changed, 115 insertions(+) create mode 100644 fe2-android/app/src/test/framework/common/java/com/github/dedis/popstellar/testutils/pages/detail/InviteFragmentPageObject.java create mode 100644 fe2-android/app/src/test/ui/robolectric/com/github/dedis/popstellar/ui/detail/InviteFragmentTest.java diff --git a/fe2-android/app/src/test/framework/common/java/com/github/dedis/popstellar/testutils/pages/detail/InviteFragmentPageObject.java b/fe2-android/app/src/test/framework/common/java/com/github/dedis/popstellar/testutils/pages/detail/InviteFragmentPageObject.java new file mode 100644 index 0000000000..288c00bd7c --- /dev/null +++ b/fe2-android/app/src/test/framework/common/java/com/github/dedis/popstellar/testutils/pages/detail/InviteFragmentPageObject.java @@ -0,0 +1,27 @@ +package com.github.dedis.popstellar.testutils.pages.detail; + +import androidx.test.espresso.ViewInteraction; + +import com.github.dedis.popstellar.R; + +import static androidx.test.espresso.Espresso.onView; +import static androidx.test.espresso.matcher.ViewMatchers.withId; + +public class InviteFragmentPageObject { + + private InviteFragmentPageObject() { + throw new IllegalStateException("Page object"); + } + + public static ViewInteraction roleText() { + return onView(withId(R.id.lao_properties_role_text)); + } + + public static ViewInteraction identifierText() { + return onView(withId(R.id.lao_properties_identifier_text)); + } + + public static ViewInteraction laoNameText() { + return onView(withId(R.id.lao_properties_name_text)); + } +} diff --git a/fe2-android/app/src/test/ui/robolectric/com/github/dedis/popstellar/ui/detail/InviteFragmentTest.java b/fe2-android/app/src/test/ui/robolectric/com/github/dedis/popstellar/ui/detail/InviteFragmentTest.java new file mode 100644 index 0000000000..29918afbb9 --- /dev/null +++ b/fe2-android/app/src/test/ui/robolectric/com/github/dedis/popstellar/ui/detail/InviteFragmentTest.java @@ -0,0 +1,88 @@ +package com.github.dedis.popstellar.ui.detail; + +import androidx.arch.core.executor.testing.InstantTaskExecutorRule; +import androidx.test.ext.junit.runners.AndroidJUnit4; +import androidx.test.filters.SmallTest; + +import com.github.dedis.popstellar.model.objects.Lao; +import com.github.dedis.popstellar.model.objects.security.KeyPair; +import com.github.dedis.popstellar.model.objects.security.PublicKey; +import com.github.dedis.popstellar.repository.LAORepository; +import com.github.dedis.popstellar.testutils.Base64DataUtils; +import com.github.dedis.popstellar.testutils.BundleBuilder; +import com.github.dedis.popstellar.testutils.fragment.ActivityFragmentScenarioRule; +import com.github.dedis.popstellar.utility.security.KeyManager; + +import org.junit.Rule; +import org.junit.Test; +import org.junit.rules.ExternalResource; +import org.junit.runner.RunWith; +import org.mockito.Mock; +import org.mockito.junit.MockitoJUnit; +import org.mockito.junit.MockitoTestRule; + +import javax.inject.Inject; + +import dagger.hilt.android.testing.*; + +import static androidx.test.espresso.assertion.ViewAssertions.matches; +import static androidx.test.espresso.matcher.ViewMatchers.withText; +import static com.github.dedis.popstellar.testutils.pages.detail.InviteFragmentPageObject.*; +import static com.github.dedis.popstellar.testutils.pages.detail.LaoDetailActivityPageObject.*; +import static org.mockito.Mockito.when; + +@SmallTest +@HiltAndroidTest +@RunWith(AndroidJUnit4.class) +public class InviteFragmentTest { + private static final String LAO_NAME = "LAO"; + private static final KeyPair KEY_PAIR = Base64DataUtils.generateKeyPair(); + private static final PublicKey PK = KEY_PAIR.getPublicKey(); + + private static final Lao LAO = new Lao(LAO_NAME, PK, 44444444); + + @Inject LAORepository laoRepository; + + @BindValue @Mock KeyManager keyManager; + + @Rule public InstantTaskExecutorRule rule = new InstantTaskExecutorRule(); + + @Rule(order = 0) + public final MockitoTestRule mockitoRule = MockitoJUnit.testRule(this); + + @Rule(order = 1) + public final HiltAndroidRule hiltRule = new HiltAndroidRule(this); + + @Rule(order = 2) + public final ExternalResource setupRule = + new ExternalResource() { + @Override + protected void before() { + hiltRule.inject(); + + laoRepository.updateLao(LAO); + + when(keyManager.getMainKeyPair()).thenReturn(KEY_PAIR); + when(keyManager.getMainPublicKey()).thenReturn(PK); + } + }; + + @Rule(order = 3) + public ActivityFragmentScenarioRule activityScenarioRule = + ActivityFragmentScenarioRule.launchIn( + LaoDetailActivity.class, + new BundleBuilder() + .putString(laoIdExtra(), LAO.getId()) + .putString(fragmentToOpenExtra(), laoDetailValue()) + .build(), + containerId(), + InviteFragment.class, + InviteFragment::newInstance); + + @Test + public void displayedInfoIsCorrect() { + roleText().check(matches(withText("Organizer"))); + laoNameText().check(matches(withText(LAO_NAME))); + identifierText().check(matches(withText(PK.getEncoded()))); + } +} From 2dff7899b271be628c1445d728bcf488f1214088 Mon Sep 17 00:00:00 2001 From: Johann Pluss Date: Sat, 14 Jan 2023 23:55:26 +0100 Subject: [PATCH 31/41] Fix code smells MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Johann Plüss --- .../ui/detail/LaoDetailActivity.java | 3 +- .../ui/detail/LaoDetailViewModel.java | 22 -------- .../dedis/popstellar/ui/detail/LaoTab.java | 53 ------------------- .../WitnessMessageListViewAdapter.java | 2 +- .../ui/digitalcash/DigitalCashActivity.java | 16 +++--- .../digitalcash/DigitalCashIssueFragment.java | 2 +- .../digitalcash/DigitalCashSendFragment.java | 2 +- .../ui/digitalcash/DigitalCashViewModel.java | 14 ----- .../ui/navigation/NavigationActivity.java | 6 ++- .../ui/navigation/NavigationViewModel.java | 25 ++++++--- .../ui/socialmedia/SocialMediaActivity.java | 16 +++--- .../socialmedia/SocialMediaSendFragment.java | 2 +- .../ui/socialmedia/SocialMediaViewModel.java | 15 ------ .../app/src/main/res/menu/lao_detail_menu.xml | 24 --------- .../main/res/menu/lao_detail_tool_menu.xml | 11 ---- .../app/src/main/res/values/dimens.xml | 3 -- .../app/src/main/res/values/strings.xml | 4 -- .../detail/LaoDetailActivityPageObject.java | 39 -------------- .../detail/LaoDetailFragmentPageObject.java | 12 ----- 19 files changed, 42 insertions(+), 229 deletions(-) delete mode 100644 fe2-android/app/src/main/java/com/github/dedis/popstellar/ui/detail/LaoTab.java delete mode 100644 fe2-android/app/src/main/res/menu/lao_detail_menu.xml delete mode 100644 fe2-android/app/src/main/res/menu/lao_detail_tool_menu.xml diff --git a/fe2-android/app/src/main/java/com/github/dedis/popstellar/ui/detail/LaoDetailActivity.java b/fe2-android/app/src/main/java/com/github/dedis/popstellar/ui/detail/LaoDetailActivity.java index cd1961524a..412571cfbf 100644 --- a/fe2-android/app/src/main/java/com/github/dedis/popstellar/ui/detail/LaoDetailActivity.java +++ b/fe2-android/app/src/main/java/com/github/dedis/popstellar/ui/detail/LaoDetailActivity.java @@ -39,7 +39,6 @@ public class LaoDetailActivity extends NavigationActivity { private static final String TAG = LaoDetailActivity.class.getSimpleName(); private LaoDetailViewModel viewModel; - private LaoDetailActivityBinding binding; @Inject Gson gson; @Inject GlobalNetworkManager networkManager; @@ -47,7 +46,7 @@ public class LaoDetailActivity extends NavigationActivity { @Override protected void onCreate(@Nullable Bundle savedInstanceState) { super.onCreate(savedInstanceState); - binding = LaoDetailActivityBinding.inflate(getLayoutInflater()); + LaoDetailActivityBinding binding = LaoDetailActivityBinding.inflate(getLayoutInflater()); setContentView(binding.getRoot()); navigationViewModel = viewModel = obtainViewModel(this); diff --git a/fe2-android/app/src/main/java/com/github/dedis/popstellar/ui/detail/LaoDetailViewModel.java b/fe2-android/app/src/main/java/com/github/dedis/popstellar/ui/detail/LaoDetailViewModel.java index 70ee2e20e7..74122e51f9 100644 --- a/fe2-android/app/src/main/java/com/github/dedis/popstellar/ui/detail/LaoDetailViewModel.java +++ b/fe2-android/app/src/main/java/com/github/dedis/popstellar/ui/detail/LaoDetailViewModel.java @@ -49,7 +49,6 @@ import io.reactivex.*; import io.reactivex.android.schedulers.AndroidSchedulers; import io.reactivex.disposables.CompositeDisposable; -import io.reactivex.disposables.Disposable; import io.reactivex.schedulers.Schedulers; @HiltViewModel @@ -555,14 +554,6 @@ public LiveData isSignedByCurrentWitness(Set witnesses) { return mIsSignedByCurrentWitness; } - public LiveData> getWitnesses() { - return mWitnesses; - } - - public LiveData> getWitnessMessages() { - return mWitnessMessages; - } - public LiveData getNbAttendees() { return mNbAttendees; } @@ -786,17 +777,4 @@ public boolean handleWitnessAddition(String data) { return true; } - - /** - * This function should be used to add disposable object generated from subscription to sent - * messages flows - * - *

They will be disposed of when the view model is cleaned which ensures that the subscription - * stays relevant throughout the whole lifecycle of the activity and it is not bound to a fragment - * - * @param disposable to add - */ - public void addDisposable(Disposable disposable) { - this.disposables.add(disposable); - } } diff --git a/fe2-android/app/src/main/java/com/github/dedis/popstellar/ui/detail/LaoTab.java b/fe2-android/app/src/main/java/com/github/dedis/popstellar/ui/detail/LaoTab.java deleted file mode 100644 index 724e1581db..0000000000 --- a/fe2-android/app/src/main/java/com/github/dedis/popstellar/ui/detail/LaoTab.java +++ /dev/null @@ -1,53 +0,0 @@ -package com.github.dedis.popstellar.ui.detail; - -import androidx.annotation.IdRes; - -import com.github.dedis.popstellar.R; -import com.github.dedis.popstellar.ui.navigation.Tab; - -import java.util.Arrays; -import java.util.List; - -/** Enum where each element represent a tab in LaoActivity */ -public enum LaoTab implements Tab { - EVENTS(R.id.lao_detail_event_list_menu), - TOKENS(R.id.lao_detail_tokens_menu), - WITNESSING(R.id.lao_detail_witnessing_menu), - DIGITAL_CASH(R.id.lao_detail_digital_cash_menu), - SOCIAL(R.id.lao_detail_social_media_menu); - - private static final List ALL = Arrays.asList(values()); - - /** - * Find a tab based on its menu id, throws an exception when no tab match the id - * - * @param menuId of the menu - * @return the tab corresponding to the given menu id - */ - public static LaoTab findByMenu(@IdRes int menuId) { - for (LaoTab tab : ALL) { - if (tab.menuId == menuId) { - return tab; - } - } - - throw new IllegalArgumentException("Unknown id : " + menuId); - } - - @IdRes private final int menuId; - - LaoTab(@IdRes int menuId) { - this.menuId = menuId; - } - - @IdRes - @Override - public int getMenuId() { - return menuId; - } - - @Override - public String getName() { - return toString(); - } -} diff --git a/fe2-android/app/src/main/java/com/github/dedis/popstellar/ui/detail/witness/WitnessMessageListViewAdapter.java b/fe2-android/app/src/main/java/com/github/dedis/popstellar/ui/detail/witness/WitnessMessageListViewAdapter.java index 23cb113882..bfbb754f9b 100644 --- a/fe2-android/app/src/main/java/com/github/dedis/popstellar/ui/detail/witness/WitnessMessageListViewAdapter.java +++ b/fe2-android/app/src/main/java/com/github/dedis/popstellar/ui/detail/witness/WitnessMessageListViewAdapter.java @@ -81,7 +81,7 @@ public View getView(int position, View convertView, ViewGroup parent) { v -> { AlertDialog.Builder adb = new AlertDialog.Builder(context); - if (viewModel.isWitness().getValue()) { + if (Boolean.TRUE.equals(viewModel.isWitness().getValue())) { adb.setTitle("Sign Message"); adb.setMessage( " Are you sure you want to sign message with ID : " diff --git a/fe2-android/app/src/main/java/com/github/dedis/popstellar/ui/digitalcash/DigitalCashActivity.java b/fe2-android/app/src/main/java/com/github/dedis/popstellar/ui/digitalcash/DigitalCashActivity.java index 71c3a57524..aa68942328 100644 --- a/fe2-android/app/src/main/java/com/github/dedis/popstellar/ui/digitalcash/DigitalCashActivity.java +++ b/fe2-android/app/src/main/java/com/github/dedis/popstellar/ui/digitalcash/DigitalCashActivity.java @@ -113,28 +113,28 @@ protected boolean openTab(MainMenuTab tab) { switch (tab) { case INVITE: openInviteTab(); - return false; + break; case EVENTS: openEventsTab(); - return false; + break; case SOCIAL_MEDIA: openSocialMediaTab(); - return false; + break; case DIGITAL_CASH: - return false; + break; case WITNESSING: openWitnessingTab(); - return false; + break; case TOKENS: openTokensTab(); - return false; + break; case DISCONNECT: startActivity(HomeActivity.newIntent(this)); - return false; + break; default: Log.w(TAG, "Unhandled tab type : " + tab); - return false; } + return false; } private void openHomeTab() { diff --git a/fe2-android/app/src/main/java/com/github/dedis/popstellar/ui/digitalcash/DigitalCashIssueFragment.java b/fe2-android/app/src/main/java/com/github/dedis/popstellar/ui/digitalcash/DigitalCashIssueFragment.java index 6c1f659098..46d1595902 100644 --- a/fe2-android/app/src/main/java/com/github/dedis/popstellar/ui/digitalcash/DigitalCashIssueFragment.java +++ b/fe2-android/app/src/main/java/com/github/dedis/popstellar/ui/digitalcash/DigitalCashIssueFragment.java @@ -158,7 +158,7 @@ public void setTheAdapterRollCallAttendee() { try { myArray = viewModel.getAttendeesFromTheRollCallList(); } catch (NoRollCallException e) { - // viewModel.setCurrentTab(DigitalCashTab.HOME); + viewModel.setBottomNavigationTab(DigitalCashTab.HOME); Log.d(TAG, getString(R.string.error_no_rollcall_closed_in_LAO)); Toast.makeText( requireContext(), diff --git a/fe2-android/app/src/main/java/com/github/dedis/popstellar/ui/digitalcash/DigitalCashSendFragment.java b/fe2-android/app/src/main/java/com/github/dedis/popstellar/ui/digitalcash/DigitalCashSendFragment.java index 13ce63086d..02144bb8e6 100644 --- a/fe2-android/app/src/main/java/com/github/dedis/popstellar/ui/digitalcash/DigitalCashSendFragment.java +++ b/fe2-android/app/src/main/java/com/github/dedis/popstellar/ui/digitalcash/DigitalCashSendFragment.java @@ -140,7 +140,7 @@ private void setUpTheAdapter() throws KeyException { try { myArray = viewModel.getAttendeesFromTheRollCallList(); } catch (NoRollCallException e) { - // viewModel.setCurrentTab(DigitalCashTab.HOME); + viewModel.setBottomNavigationTab(DigitalCashTab.HOME); Toast.makeText( requireContext(), R.string.digital_cash_please_enter_roll_call, Toast.LENGTH_SHORT) .show(); diff --git a/fe2-android/app/src/main/java/com/github/dedis/popstellar/ui/digitalcash/DigitalCashViewModel.java b/fe2-android/app/src/main/java/com/github/dedis/popstellar/ui/digitalcash/DigitalCashViewModel.java index 38f43b8c57..6efd1175b0 100644 --- a/fe2-android/app/src/main/java/com/github/dedis/popstellar/ui/digitalcash/DigitalCashViewModel.java +++ b/fe2-android/app/src/main/java/com/github/dedis/popstellar/ui/digitalcash/DigitalCashViewModel.java @@ -37,7 +37,6 @@ import io.reactivex.Observable; import io.reactivex.*; import io.reactivex.disposables.CompositeDisposable; -import io.reactivex.disposables.Disposable; @HiltViewModel public class DigitalCashViewModel extends NavigationViewModel { @@ -377,17 +376,4 @@ public long getUserBalance(PublicKey user) { public long getOwnBalance() throws KeyException { return getUserBalance(getValidToken().getPublicKey()); } - - /** - * This function should be used to add disposable object generated from subscription to sent - * messages flows - * - *

They will be disposed of when the view model is cleaned which ensures that the subscription - * stays relevant throughout the whole lifecycle of the activity and it is not bound to a fragment - * - * @param disposable to add - */ - public void addDisposable(Disposable disposable) { - this.disposables.add(disposable); - } } diff --git a/fe2-android/app/src/main/java/com/github/dedis/popstellar/ui/navigation/NavigationActivity.java b/fe2-android/app/src/main/java/com/github/dedis/popstellar/ui/navigation/NavigationActivity.java index a1a20367f1..e70adf9b40 100644 --- a/fe2-android/app/src/main/java/com/github/dedis/popstellar/ui/navigation/NavigationActivity.java +++ b/fe2-android/app/src/main/java/com/github/dedis/popstellar/ui/navigation/NavigationActivity.java @@ -67,7 +67,7 @@ protected void setupDrawer( // Listen to click on left icon of toolbar toolbar.setNavigationOnClickListener( view -> { - if (navigationViewModel.isTab().getValue()) { + if (Boolean.TRUE.equals(navigationViewModel.isTab().getValue())) { // If it is a tab open menu drawerLayout.openDrawer(GravityCompat.START); } else { @@ -83,7 +83,9 @@ protected void setupDrawer( this, isTab -> toolbar.setNavigationIcon( - isTab ? R.drawable.menu_icon : R.drawable.back_arrow_icon)); + Boolean.TRUE.equals(isTab) + ? R.drawable.menu_icon + : R.drawable.back_arrow_icon)); // Observe changes to the tab selected navigationViewModel diff --git a/fe2-android/app/src/main/java/com/github/dedis/popstellar/ui/navigation/NavigationViewModel.java b/fe2-android/app/src/main/java/com/github/dedis/popstellar/ui/navigation/NavigationViewModel.java index a4298c1836..a79e5e80ea 100644 --- a/fe2-android/app/src/main/java/com/github/dedis/popstellar/ui/navigation/NavigationViewModel.java +++ b/fe2-android/app/src/main/java/com/github/dedis/popstellar/ui/navigation/NavigationViewModel.java @@ -94,9 +94,9 @@ public LiveData> getWitnessMessages() { } public void updateRole() { - Role role = determineRole(); - if (this.role.getValue() != role) { - this.role.setValue(role); + Role currentRole = determineRole(); + if (role.getValue() != currentRole) { + this.role.setValue(currentRole); } } @@ -109,19 +109,19 @@ public void setIsOrganizer(boolean isOrganizer) { } public void setIsWitness(boolean isWitness) { - if (this.isWitness.getValue() != isWitness) { + if (isWitness != this.isWitness.getValue()) { this.isWitness.setValue(isWitness); } } public void setIsAttendee(boolean isAttendee) { - if (this.isAttendee.getValue() != isAttendee) { + if (isAttendee != this.isAttendee.getValue()) { this.isAttendee.setValue(isAttendee); } } public void setIsTab(boolean isTab) { - if (this.isTab.getValue() != isTab) { + if (isTab != this.isTab.getValue()) { this.isTab.setValue(isTab); } } @@ -140,6 +140,15 @@ public void setWitnessMessages(List messages) { this.witnessMessages.setValue(messages); } + /** + * This function should be used to add disposable object generated from subscription to sent + * messages flows + * + *

They will be disposed of when the view model is cleaned which ensures that the subscription + * stays relevant throughout the whole lifecycle of the activity and it is not bound to a fragment + * + * @param disposable to add + */ public void addDisposable(Disposable disposable) { this.disposables.add(disposable); } @@ -154,10 +163,10 @@ private Role determineRole() { if (isOrganizer) { return Role.ORGANIZER; } - if (isWitness.getValue()) { + if (Boolean.TRUE.equals(isWitness.getValue())) { return Role.WITNESS; } - if (isAttendee.getValue()) { + if (Boolean.TRUE.equals(isAttendee.getValue())) { return Role.ATTENDEE; } return Role.MEMBER; diff --git a/fe2-android/app/src/main/java/com/github/dedis/popstellar/ui/socialmedia/SocialMediaActivity.java b/fe2-android/app/src/main/java/com/github/dedis/popstellar/ui/socialmedia/SocialMediaActivity.java index 09e9fc08c8..b211d0409c 100644 --- a/fe2-android/app/src/main/java/com/github/dedis/popstellar/ui/socialmedia/SocialMediaActivity.java +++ b/fe2-android/app/src/main/java/com/github/dedis/popstellar/ui/socialmedia/SocialMediaActivity.java @@ -111,28 +111,28 @@ protected boolean openTab(MainMenuTab tab) { switch (tab) { case INVITE: openInviteTab(); - return false; + break; case EVENTS: openEventsTab(); - return false; + break; case SOCIAL_MEDIA: - return false; + break; case DIGITAL_CASH: openDigitalCash(); - return false; + break; case WITNESSING: openWitnessingTab(); - return false; + break; case TOKENS: openTokensTab(); - return false; + break; case DISCONNECT: startActivity(HomeActivity.newIntent(this)); - return false; + break; default: Log.w(TAG, "Unhandled tab type : " + tab); - return false; } + return false; } private void openHomeTab() { diff --git a/fe2-android/app/src/main/java/com/github/dedis/popstellar/ui/socialmedia/SocialMediaSendFragment.java b/fe2-android/app/src/main/java/com/github/dedis/popstellar/ui/socialmedia/SocialMediaSendFragment.java index b5bcc94ed7..16c199bf50 100644 --- a/fe2-android/app/src/main/java/com/github/dedis/popstellar/ui/socialmedia/SocialMediaSendFragment.java +++ b/fe2-android/app/src/main/java/com/github/dedis/popstellar/ui/socialmedia/SocialMediaSendFragment.java @@ -93,7 +93,7 @@ private void sendNewChirp() { requireContext(), TAG, error, R.string.error_sending_chirp); } })); - // viewModel.setCurrentTab(SocialMediaTab.HOME); + viewModel.setBottomNavigationTab(SocialMediaTab.HOME); } } } diff --git a/fe2-android/app/src/main/java/com/github/dedis/popstellar/ui/socialmedia/SocialMediaViewModel.java b/fe2-android/app/src/main/java/com/github/dedis/popstellar/ui/socialmedia/SocialMediaViewModel.java index 079ccec10b..3cc629f472 100644 --- a/fe2-android/app/src/main/java/com/github/dedis/popstellar/ui/socialmedia/SocialMediaViewModel.java +++ b/fe2-android/app/src/main/java/com/github/dedis/popstellar/ui/socialmedia/SocialMediaViewModel.java @@ -37,7 +37,6 @@ import io.reactivex.Observable; import io.reactivex.Single; import io.reactivex.disposables.CompositeDisposable; -import io.reactivex.disposables.Disposable; @HiltViewModel public class SocialMediaViewModel extends NavigationViewModel { @@ -50,7 +49,6 @@ public class SocialMediaViewModel extends NavigationViewModel { * LiveData objects for capturing events */ private final MutableLiveData mNumberCharsLeft = new MutableLiveData<>(); - private final MutableLiveData mLaoName = new MutableLiveData<>(); private final MutableLiveData bottomNavigationTab = new MutableLiveData<>(SocialMediaTab.HOME); @@ -239,19 +237,6 @@ public void savePersistentData() throws GeneralSecurityException { networkManager, wallet, getApplication().getApplicationContext()); } - /** - * This function should be used to add disposable object generated from subscription to sent - * messages flows - * - *

They will be disposed of when the view model is cleaned which ensures that the subscription - * stays relevant throughout the whole lifecycle of the activity and it is not bound to a fragment - * - * @param disposable to add - */ - public void addDisposable(Disposable disposable) { - this.disposables.add(disposable); - } - @Override public LaoView getLao() throws UnknownLaoException { return laoRepository.getLaoView(getLaoId()); diff --git a/fe2-android/app/src/main/res/menu/lao_detail_menu.xml b/fe2-android/app/src/main/res/menu/lao_detail_menu.xml deleted file mode 100644 index bc68ced262..0000000000 --- a/fe2-android/app/src/main/res/menu/lao_detail_menu.xml +++ /dev/null @@ -1,24 +0,0 @@ - -

- - - - - - - diff --git a/fe2-android/app/src/main/res/menu/lao_detail_tool_menu.xml b/fe2-android/app/src/main/res/menu/lao_detail_tool_menu.xml deleted file mode 100644 index a058098ddf..0000000000 --- a/fe2-android/app/src/main/res/menu/lao_detail_tool_menu.xml +++ /dev/null @@ -1,11 +0,0 @@ - - - - diff --git a/fe2-android/app/src/main/res/values/dimens.xml b/fe2-android/app/src/main/res/values/dimens.xml index 0b78d7ea50..fbd52162a1 100644 --- a/fe2-android/app/src/main/res/values/dimens.xml +++ b/fe2-android/app/src/main/res/values/dimens.xml @@ -14,7 +14,6 @@ 18sp 14sp 16sp - 12sp 13sp 10sp 10dp @@ -114,8 +113,6 @@ 18sp 8dp 30dp - 30dp - 20dp 28dp diff --git a/fe2-android/app/src/main/res/values/strings.xml b/fe2-android/app/src/main/res/values/strings.xml index 6f09f525ab..38a82e7178 100644 --- a/fe2-android/app/src/main/res/values/strings.xml +++ b/fe2-android/app/src/main/res/values/strings.xml @@ -48,8 +48,6 @@ Current Upcoming Previous - Lao\'s QR code - Lao Properties Connected to server Identifier @@ -288,9 +286,7 @@ Clearing was unsuccessful - Open Qr code image Qr code image to display LAO connecting information - Close Qr code Status of the event Time icon Expand diff --git a/fe2-android/app/src/test/framework/common/java/com/github/dedis/popstellar/testutils/pages/detail/LaoDetailActivityPageObject.java b/fe2-android/app/src/test/framework/common/java/com/github/dedis/popstellar/testutils/pages/detail/LaoDetailActivityPageObject.java index a7bf5d5633..b8808328d6 100644 --- a/fe2-android/app/src/test/framework/common/java/com/github/dedis/popstellar/testutils/pages/detail/LaoDetailActivityPageObject.java +++ b/fe2-android/app/src/test/framework/common/java/com/github/dedis/popstellar/testutils/pages/detail/LaoDetailActivityPageObject.java @@ -25,50 +25,11 @@ public static ViewInteraction fragmentContainer() { return onView(withId(R.id.fragment_container_lao_detail)); } - public static ViewInteraction tokenButton() { - return onView(withId(R.id.lao_detail_tokens_menu)); - } - - public static ViewInteraction socialMediaButton() { - return onView(withId(R.id.main_menu_digital_cash)); - } - - public static ViewInteraction digitalCashButton() { - return onView(withId(R.id.main_menu_digital_cash)); - } - - @IdRes - public static int digitalCashMenu() { - return R.id.main_menu_digital_cash; - } - - public static ViewInteraction witnessButton() { - return onView(withId(R.id.main_menu_witnessing)); - } - - public static ViewInteraction drawerLayout() { - return onView(withId(R.id.lao_detail_drawer_layout)); - } - - public static ViewInteraction navigationDrawer() { - return onView(withId(R.id.lao_detail_navigation_drawer)); - } - @IdRes public static int laoDetailFragmentId() { return R.id.fragment_lao_detail; } - @IdRes - public static int tokenListFragmentId() { - return R.id.fragment_tokens; - } - - @IdRes - public static int witnessingFragmentId() { - return R.id.fragment_witnessing; - } - @IdRes public static int qrCodeFragmentId() { return R.id.fragment_qrcode; diff --git a/fe2-android/app/src/test/framework/common/java/com/github/dedis/popstellar/testutils/pages/detail/LaoDetailFragmentPageObject.java b/fe2-android/app/src/test/framework/common/java/com/github/dedis/popstellar/testutils/pages/detail/LaoDetailFragmentPageObject.java index dd921f0f8c..1b80b3968a 100644 --- a/fe2-android/app/src/test/framework/common/java/com/github/dedis/popstellar/testutils/pages/detail/LaoDetailFragmentPageObject.java +++ b/fe2-android/app/src/test/framework/common/java/com/github/dedis/popstellar/testutils/pages/detail/LaoDetailFragmentPageObject.java @@ -13,14 +13,6 @@ private LaoDetailFragmentPageObject() { throw new IllegalStateException("Page object"); } - public static ViewInteraction qrCodeLayout() { - return null; // onView(withId(R.id.lao_detail_qr_layout)); - } - - public static ViewInteraction connectQrCode() { - return onView(withId(R.id.channel_qr_code)); - } - public static ViewInteraction addEventButton() { return onView(withId(R.id.add_event)); } @@ -41,10 +33,6 @@ public static ViewInteraction addRollCallText() { return onView(withId(R.id.add_roll_call_text)); } - public static ViewInteraction qrCodeIcon() { - return onView(withId(R.id.lao_toolbar_qr_code)); - } - public static ViewInteraction eventList() { return onView(withId(R.id.event_list)); } From 69748499c2a698283a5a461b7ce0a2e931fdb775 Mon Sep 17 00:00:00 2001 From: Johann Pluss Date: Sun, 15 Jan 2023 14:45:00 +0100 Subject: [PATCH 32/41] Fix code smells MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Johann Plüss --- .../ui/detail/LaoDetailViewModel.java | 13 +- .../ui/navigation/NavigationViewModel.java | 6 +- .../src/main/res/layout/identity_fragment.xml | 130 ------------------ .../app/src/main/res/values/dimens.xml | 3 - .../app/src/main/res/values/strings.xml | 15 +- 5 files changed, 6 insertions(+), 161 deletions(-) delete mode 100644 fe2-android/app/src/main/res/layout/identity_fragment.xml diff --git a/fe2-android/app/src/main/java/com/github/dedis/popstellar/ui/detail/LaoDetailViewModel.java b/fe2-android/app/src/main/java/com/github/dedis/popstellar/ui/detail/LaoDetailViewModel.java index 74122e51f9..04a4ed36dc 100644 --- a/fe2-android/app/src/main/java/com/github/dedis/popstellar/ui/detail/LaoDetailViewModel.java +++ b/fe2-android/app/src/main/java/com/github/dedis/popstellar/ui/detail/LaoDetailViewModel.java @@ -5,7 +5,8 @@ import android.widget.Toast; import androidx.annotation.NonNull; -import androidx.lifecycle.*; +import androidx.lifecycle.LiveData; +import androidx.lifecycle.MutableLiveData; import com.github.dedis.popstellar.R; import com.github.dedis.popstellar.SingleEvent; @@ -72,16 +73,6 @@ public class LaoDetailViewModel extends NavigationViewModel implements QRCodeSca private final MutableLiveData mCurrentLao = new MutableLiveData<>(); private final MutableLiveData mIsSignedByCurrentWitness = new MutableLiveData<>(); private final MutableLiveData mNbAttendees = new MutableLiveData<>(); - private final LiveData> mWitnesses = - Transformations.map( - mCurrentLao, - lao -> lao == null ? new ArrayList<>() : new ArrayList<>(lao.getWitnesses())); - - private final LiveData> mWitnessMessages = - Transformations.map( - mCurrentLao, - lao -> - lao == null ? new ArrayList<>() : new ArrayList<>(lao.getWitnessMessages().values())); private Observable> events; private Observable> attendedRollCalls; diff --git a/fe2-android/app/src/main/java/com/github/dedis/popstellar/ui/navigation/NavigationViewModel.java b/fe2-android/app/src/main/java/com/github/dedis/popstellar/ui/navigation/NavigationViewModel.java index a79e5e80ea..b9d1b8033e 100644 --- a/fe2-android/app/src/main/java/com/github/dedis/popstellar/ui/navigation/NavigationViewModel.java +++ b/fe2-android/app/src/main/java/com/github/dedis/popstellar/ui/navigation/NavigationViewModel.java @@ -109,19 +109,19 @@ public void setIsOrganizer(boolean isOrganizer) { } public void setIsWitness(boolean isWitness) { - if (isWitness != this.isWitness.getValue()) { + if (!Boolean.valueOf(isWitness).equals(this.isWitness.getValue())) { this.isWitness.setValue(isWitness); } } public void setIsAttendee(boolean isAttendee) { - if (isAttendee != this.isAttendee.getValue()) { + if (!Boolean.valueOf(isAttendee).equals(this.isAttendee.getValue())) { this.isAttendee.setValue(isAttendee); } } public void setIsTab(boolean isTab) { - if (isTab != this.isTab.getValue()) { + if (!Boolean.valueOf(isTab).equals(this.isTab.getValue())) { this.isTab.setValue(isTab); } } diff --git a/fe2-android/app/src/main/res/layout/identity_fragment.xml b/fe2-android/app/src/main/res/layout/identity_fragment.xml deleted file mode 100644 index 349f3fc728..0000000000 --- a/fe2-android/app/src/main/res/layout/identity_fragment.xml +++ /dev/null @@ -1,130 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/fe2-android/app/src/main/res/values/dimens.xml b/fe2-android/app/src/main/res/values/dimens.xml index 05d99bbd65..ec7bcb82af 100644 --- a/fe2-android/app/src/main/res/values/dimens.xml +++ b/fe2-android/app/src/main/res/values/dimens.xml @@ -14,7 +14,6 @@ 18sp 14sp 16sp - 13sp 10sp 10dp @@ -47,7 +46,6 @@ 8dp - 40dp 20dp 10dp 14sp @@ -99,7 +97,6 @@ 18sp 8dp - 30dp 28dp diff --git a/fe2-android/app/src/main/res/values/strings.xml b/fe2-android/app/src/main/res/values/strings.xml index c775a507b0..6b5ca691e8 100644 --- a/fe2-android/app/src/main/res/values/strings.xml +++ b/fe2-android/app/src/main/res/values/strings.xml @@ -14,7 +14,6 @@ Member - Identity Social Media Digital Cash Events @@ -50,6 +49,7 @@ Previous Connected to server Identifier + Name Open @@ -71,23 +71,10 @@ Roll Call Title* - You can participate in organizations and meetings anonymously by leaving this - box checked.\nIf you wish to reveal your identity to other participants in this organization,\nyou may un-check - this box and enter the information you wish to reveal below.\nYou must enter identity information in order to - play an Organizer or Witness role in an organization. - Open Attendee scanned successfully REOPEN - - Name - Title - Email - Organization - Phone - Anonymous - Scan personal QR code of the witness to add Scan a QR code to connect to a LAO From f732647c1c48500e2fd5713e26379f4205018bb8 Mon Sep 17 00:00:00 2001 From: Johann Pluss Date: Sun, 15 Jan 2023 15:00:16 +0100 Subject: [PATCH 33/41] Removed unused variable MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Johann Plüss --- .../github/dedis/popstellar/ui/detail/LaoDetailViewModel.java | 1 - 1 file changed, 1 deletion(-) diff --git a/fe2-android/app/src/main/java/com/github/dedis/popstellar/ui/detail/LaoDetailViewModel.java b/fe2-android/app/src/main/java/com/github/dedis/popstellar/ui/detail/LaoDetailViewModel.java index 04a4ed36dc..cf355184c7 100644 --- a/fe2-android/app/src/main/java/com/github/dedis/popstellar/ui/detail/LaoDetailViewModel.java +++ b/fe2-android/app/src/main/java/com/github/dedis/popstellar/ui/detail/LaoDetailViewModel.java @@ -70,7 +70,6 @@ public class LaoDetailViewModel extends NavigationViewModel implements QRCodeSca /* * LiveData objects that represent the state in a fragment */ - private final MutableLiveData mCurrentLao = new MutableLiveData<>(); private final MutableLiveData mIsSignedByCurrentWitness = new MutableLiveData<>(); private final MutableLiveData mNbAttendees = new MutableLiveData<>(); From 3f8fe40fd7f4f96b96f8ae6d75a7066664ad0b31 Mon Sep 17 00:00:00 2001 From: Johann Pluss Date: Sun, 15 Jan 2023 15:18:36 +0100 Subject: [PATCH 34/41] Minor fix for long text display bug MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Johann Plüss --- fe2-android/app/src/main/res/layout/invite_fragment.xml | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/fe2-android/app/src/main/res/layout/invite_fragment.xml b/fe2-android/app/src/main/res/layout/invite_fragment.xml index fc4f785d18..405d235d37 100644 --- a/fe2-android/app/src/main/res/layout/invite_fragment.xml +++ b/fe2-android/app/src/main/res/layout/invite_fragment.xml @@ -38,8 +38,9 @@ From 36c9fda1a17c85944d26bec47e4298410b972867 Mon Sep 17 00:00:00 2001 From: Johann Pluss Date: Sun, 15 Jan 2023 15:21:22 +0100 Subject: [PATCH 35/41] Improve naming MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Johann Plüss --- .../ui/detail/LaoDetailActivity.java | 10 ++-- .../ui/detail/LaoDetailViewModel.java | 4 +- .../ui/digitalcash/DigitalCashActivity.java | 10 ++-- .../ui/digitalcash/DigitalCashViewModel.java | 4 +- ...vigationActivity.java => LaoActivity.java} | 48 +++++++++---------- ...gationViewModel.java => LaoViewModel.java} | 4 +- .../ui/socialmedia/SocialMediaActivity.java | 10 ++-- .../ui/socialmedia/SocialMediaViewModel.java | 4 +- 8 files changed, 47 insertions(+), 47 deletions(-) rename fe2-android/app/src/main/java/com/github/dedis/popstellar/ui/navigation/{NavigationActivity.java => LaoActivity.java} (82%) rename fe2-android/app/src/main/java/com/github/dedis/popstellar/ui/navigation/{NavigationViewModel.java => LaoViewModel.java} (97%) diff --git a/fe2-android/app/src/main/java/com/github/dedis/popstellar/ui/detail/LaoDetailActivity.java b/fe2-android/app/src/main/java/com/github/dedis/popstellar/ui/detail/LaoDetailActivity.java index 412571cfbf..53e2ad7afd 100644 --- a/fe2-android/app/src/main/java/com/github/dedis/popstellar/ui/detail/LaoDetailActivity.java +++ b/fe2-android/app/src/main/java/com/github/dedis/popstellar/ui/detail/LaoDetailActivity.java @@ -18,8 +18,8 @@ import com.github.dedis.popstellar.ui.detail.witness.WitnessingFragment; import com.github.dedis.popstellar.ui.digitalcash.DigitalCashActivity; import com.github.dedis.popstellar.ui.home.HomeActivity; +import com.github.dedis.popstellar.ui.navigation.LaoActivity; import com.github.dedis.popstellar.ui.navigation.MainMenuTab; -import com.github.dedis.popstellar.ui.navigation.NavigationActivity; import com.github.dedis.popstellar.ui.socialmedia.SocialMediaActivity; import com.github.dedis.popstellar.utility.ActivityUtils; import com.github.dedis.popstellar.utility.Constants; @@ -34,7 +34,7 @@ import dagger.hilt.android.AndroidEntryPoint; @AndroidEntryPoint -public class LaoDetailActivity extends NavigationActivity { +public class LaoDetailActivity extends LaoActivity { private static final String TAG = LaoDetailActivity.class.getSimpleName(); @@ -48,13 +48,13 @@ protected void onCreate(@Nullable Bundle savedInstanceState) { super.onCreate(savedInstanceState); LaoDetailActivityBinding binding = LaoDetailActivityBinding.inflate(getLayoutInflater()); setContentView(binding.getRoot()); - navigationViewModel = viewModel = obtainViewModel(this); + laoViewModel = viewModel = obtainViewModel(this); String laoId = Objects.requireNonNull(getIntent().getExtras()).getString(Constants.LAO_ID_EXTRA); viewModel.subscribeToLao(laoId); - setupDrawer( + initializeLaoActivity( laoId, binding.laoDetailNavigationDrawer, binding.laoTopAppBar, @@ -64,7 +64,7 @@ protected void onCreate(@Nullable Bundle savedInstanceState) { if (tab == null) { tab = MainMenuTab.EVENTS; } - navigationViewModel.setCurrentTab(tab); + laoViewModel.setCurrentTab(tab); openTab(tab); } diff --git a/fe2-android/app/src/main/java/com/github/dedis/popstellar/ui/detail/LaoDetailViewModel.java b/fe2-android/app/src/main/java/com/github/dedis/popstellar/ui/detail/LaoDetailViewModel.java index cf355184c7..9b55f22b15 100644 --- a/fe2-android/app/src/main/java/com/github/dedis/popstellar/ui/detail/LaoDetailViewModel.java +++ b/fe2-android/app/src/main/java/com/github/dedis/popstellar/ui/detail/LaoDetailViewModel.java @@ -26,7 +26,7 @@ import com.github.dedis.popstellar.model.qrcode.PopTokenData; import com.github.dedis.popstellar.repository.*; import com.github.dedis.popstellar.repository.remote.GlobalNetworkManager; -import com.github.dedis.popstellar.ui.navigation.NavigationViewModel; +import com.github.dedis.popstellar.ui.navigation.LaoViewModel; import com.github.dedis.popstellar.ui.qrcode.QRCodeScanningViewModel; import com.github.dedis.popstellar.ui.qrcode.ScanningAction; import com.github.dedis.popstellar.utility.ActivityUtils; @@ -53,7 +53,7 @@ import io.reactivex.schedulers.Schedulers; @HiltViewModel -public class LaoDetailViewModel extends NavigationViewModel implements QRCodeScanningViewModel { +public class LaoDetailViewModel extends LaoViewModel implements QRCodeScanningViewModel { public static final String TAG = LaoDetailViewModel.class.getSimpleName(); private static final String LAO_FAILURE_MESSAGE = "failed to retrieve current lao"; diff --git a/fe2-android/app/src/main/java/com/github/dedis/popstellar/ui/digitalcash/DigitalCashActivity.java b/fe2-android/app/src/main/java/com/github/dedis/popstellar/ui/digitalcash/DigitalCashActivity.java index aa68942328..ab5cf3ff67 100644 --- a/fe2-android/app/src/main/java/com/github/dedis/popstellar/ui/digitalcash/DigitalCashActivity.java +++ b/fe2-android/app/src/main/java/com/github/dedis/popstellar/ui/digitalcash/DigitalCashActivity.java @@ -15,8 +15,8 @@ import com.github.dedis.popstellar.model.objects.security.PublicKey; import com.github.dedis.popstellar.ui.detail.LaoDetailActivity; import com.github.dedis.popstellar.ui.home.HomeActivity; +import com.github.dedis.popstellar.ui.navigation.LaoActivity; import com.github.dedis.popstellar.ui.navigation.MainMenuTab; -import com.github.dedis.popstellar.ui.navigation.NavigationActivity; import com.github.dedis.popstellar.ui.socialmedia.SocialMediaActivity; import com.github.dedis.popstellar.utility.ActivityUtils; import com.github.dedis.popstellar.utility.Constants; @@ -31,7 +31,7 @@ /** Activity for the digital cash */ @AndroidEntryPoint -public class DigitalCashActivity extends NavigationActivity { +public class DigitalCashActivity extends LaoActivity { private DigitalCashViewModel viewModel; private DigitalCashMainActivityBinding binding; public static final String TAG = DigitalCashActivity.class.getSimpleName(); @@ -41,16 +41,16 @@ protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); binding = DigitalCashMainActivityBinding.inflate(getLayoutInflater()); setContentView(binding.getRoot()); - navigationViewModel = viewModel = obtainViewModel(this); + laoViewModel = viewModel = obtainViewModel(this); String laoId = Objects.requireNonNull(getIntent().getStringExtra(Constants.LAO_ID_EXTRA)); Log.d(TAG, "Opening digitalCash with id " + laoId); - setupDrawer( + initializeLaoActivity( laoId, binding.digitalCashNavigationDrawer, binding.digitalCashAppBar, binding.digitalCashDrawerLayout); - navigationViewModel.setCurrentTab(MainMenuTab.DIGITAL_CASH); + laoViewModel.setCurrentTab(MainMenuTab.DIGITAL_CASH); setupBottomNavBar(); openHomeTab(); } diff --git a/fe2-android/app/src/main/java/com/github/dedis/popstellar/ui/digitalcash/DigitalCashViewModel.java b/fe2-android/app/src/main/java/com/github/dedis/popstellar/ui/digitalcash/DigitalCashViewModel.java index 6efd1175b0..af21228b1e 100644 --- a/fe2-android/app/src/main/java/com/github/dedis/popstellar/ui/digitalcash/DigitalCashViewModel.java +++ b/fe2-android/app/src/main/java/com/github/dedis/popstellar/ui/digitalcash/DigitalCashViewModel.java @@ -18,7 +18,7 @@ import com.github.dedis.popstellar.model.objects.view.LaoView; import com.github.dedis.popstellar.repository.*; import com.github.dedis.popstellar.repository.remote.GlobalNetworkManager; -import com.github.dedis.popstellar.ui.navigation.NavigationViewModel; +import com.github.dedis.popstellar.ui.navigation.LaoViewModel; import com.github.dedis.popstellar.utility.ActivityUtils; import com.github.dedis.popstellar.utility.error.UnknownLaoException; import com.github.dedis.popstellar.utility.error.keys.KeyException; @@ -39,7 +39,7 @@ import io.reactivex.disposables.CompositeDisposable; @HiltViewModel -public class DigitalCashViewModel extends NavigationViewModel { +public class DigitalCashViewModel extends LaoViewModel { public static final String TAG = DigitalCashViewModel.class.getSimpleName(); private static final String LAO_FAILURE_MESSAGE = "failed to retrieve lao"; diff --git a/fe2-android/app/src/main/java/com/github/dedis/popstellar/ui/navigation/NavigationActivity.java b/fe2-android/app/src/main/java/com/github/dedis/popstellar/ui/navigation/LaoActivity.java similarity index 82% rename from fe2-android/app/src/main/java/com/github/dedis/popstellar/ui/navigation/NavigationActivity.java rename to fe2-android/app/src/main/java/com/github/dedis/popstellar/ui/navigation/LaoActivity.java index e70adf9b40..f2d580bb88 100644 --- a/fe2-android/app/src/main/java/com/github/dedis/popstellar/ui/navigation/NavigationActivity.java +++ b/fe2-android/app/src/main/java/com/github/dedis/popstellar/ui/navigation/LaoActivity.java @@ -33,14 +33,14 @@ * This abstract activity encapsulate the redundant behavior of an activity with a navigation bar * *

An activity extending this must instantiate the navigationViewModel in its onCreate and it - * should call setupDrawer with the navigationView as parameter. + * should call initializeLaoActivity with the navigationView as parameter. */ @AndroidEntryPoint -public abstract class NavigationActivity extends AppCompatActivity { +public abstract class LaoActivity extends AppCompatActivity { - private static final String TAG = NavigationActivity.class.getSimpleName(); + private static final String TAG = LaoActivity.class.getSimpleName(); - protected NavigationViewModel navigationViewModel; + protected LaoViewModel laoViewModel; @Inject RollCallRepository rollCallRepo; @Inject LAORepository laoRepo; @@ -55,19 +55,19 @@ public abstract class NavigationActivity extends AppCompatActivity { * * @param navigationView the view */ - protected void setupDrawer( + protected void initializeLaoActivity( String laoId, NavigationView navigationView, MaterialToolbar toolbar, DrawerLayout drawerLayout) { - navigationViewModel.setLaoId(laoId); + laoViewModel.setLaoId(laoId); observeRoles(); // Listen to click on left icon of toolbar toolbar.setNavigationOnClickListener( view -> { - if (Boolean.TRUE.equals(navigationViewModel.isTab().getValue())) { + if (Boolean.TRUE.equals(laoViewModel.isTab().getValue())) { // If it is a tab open menu drawerLayout.openDrawer(GravityCompat.START); } else { @@ -77,7 +77,7 @@ protected void setupDrawer( }); // Observe whether the menu icon or back arrow should be displayed - navigationViewModel + laoViewModel .isTab() .observe( this, @@ -88,12 +88,12 @@ protected void setupDrawer( : R.drawable.back_arrow_icon)); // Observe changes to the tab selected - navigationViewModel + laoViewModel .getCurrentTab() .observe( this, tab -> { - navigationViewModel.setIsTab(true); + laoViewModel.setIsTab(true); navigationView.setCheckedItem(tab.getMenuId()); }); @@ -104,7 +104,7 @@ protected void setupDrawer( boolean selected = openTab(tab); if (selected) { Log.d(TAG, "The tab was successfully opened"); - navigationViewModel.setCurrentTab(tab); + laoViewModel.setCurrentTab(tab); } else { Log.d(TAG, "The tab wasn't opened"); } @@ -114,17 +114,17 @@ protected void setupDrawer( observeLao(laoId); try { - setupHeaderLaoName(navigationView, navigationViewModel.getLao().getName()); + setupHeaderLaoName(navigationView, laoViewModel.getLao().getName()); } catch (UnknownLaoException e) { ErrorUtils.logAndShow(this, TAG, e, R.string.unknown_lao_exception); startActivity(HomeActivity.newIntent(this)); } // Update the user's role in the drawer header when it changes - navigationViewModel.getRole().observe(this, role -> setupHeaderRole(navigationView, role)); + laoViewModel.getRole().observe(this, role -> setupHeaderRole(navigationView, role)); // Observe the toolbar title to display - navigationViewModel + laoViewModel .getPageTitle() .observe( this, @@ -139,12 +139,12 @@ protected void setupDrawer( private void observeRoles() { // Observe any change in the following variable to update the role - navigationViewModel.isWitness().observe(this, any -> navigationViewModel.updateRole()); - navigationViewModel.isAttendee().observe(this, any -> navigationViewModel.updateRole()); + laoViewModel.isWitness().observe(this, any -> laoViewModel.updateRole()); + laoViewModel.isAttendee().observe(this, any -> laoViewModel.updateRole()); } private void observeRollCalls(String laoId) { - navigationViewModel.addDisposable( + laoViewModel.addDisposable( rollCallRepo .getRollCallsObservableInLao(laoId) .observeOn(AndroidSchedulers.mainThread()) @@ -161,14 +161,14 @@ private void observeRollCalls(String laoId) { return false; } }); - navigationViewModel.setIsAttendee(isLastRollCallAttended); + laoViewModel.setIsAttendee(isLastRollCallAttended); }, error -> ErrorUtils.logAndShow(this, TAG, error, R.string.unknown_roll_call_exception))); } private void observeLao(String laoId) { - navigationViewModel.addDisposable( + laoViewModel.addDisposable( laoRepo .getLaoObservable(laoId) .observeOn(AndroidSchedulers.mainThread()) @@ -176,17 +176,17 @@ private void observeLao(String laoId) { laoView -> { Log.d(TAG, "got an update for lao: " + laoView); - navigationViewModel.setWitnessMessages( + laoViewModel.setWitnessMessages( new ArrayList<>(laoView.getWitnessMessages().values())); - navigationViewModel.setWitnesses(new ArrayList<>(laoView.getWitnesses())); + laoViewModel.setWitnesses(new ArrayList<>(laoView.getWitnesses())); boolean isOrganizer = laoView.getOrganizer().equals(keyManager.getMainPublicKey()); - navigationViewModel.setIsOrganizer(isOrganizer); - navigationViewModel.setIsWitness( + laoViewModel.setIsOrganizer(isOrganizer); + laoViewModel.setIsWitness( laoView.getWitnesses().contains(keyManager.getMainPublicKey())); - navigationViewModel.updateRole(); + laoViewModel.updateRole(); }, error -> Log.d(TAG, "error updating LAO :" + error))); } diff --git a/fe2-android/app/src/main/java/com/github/dedis/popstellar/ui/navigation/NavigationViewModel.java b/fe2-android/app/src/main/java/com/github/dedis/popstellar/ui/navigation/LaoViewModel.java similarity index 97% rename from fe2-android/app/src/main/java/com/github/dedis/popstellar/ui/navigation/NavigationViewModel.java rename to fe2-android/app/src/main/java/com/github/dedis/popstellar/ui/navigation/LaoViewModel.java index b9d1b8033e..218ee8e0d1 100644 --- a/fe2-android/app/src/main/java/com/github/dedis/popstellar/ui/navigation/NavigationViewModel.java +++ b/fe2-android/app/src/main/java/com/github/dedis/popstellar/ui/navigation/LaoViewModel.java @@ -24,7 +24,7 @@ *

Any activity that uses a navigation bar should have its view model extends from the this * * class */ -public abstract class NavigationViewModel extends AndroidViewModel { +public abstract class LaoViewModel extends AndroidViewModel { private final MutableLiveData currentTab = new MutableLiveData<>(); @@ -43,7 +43,7 @@ public abstract class NavigationViewModel extends AndroidViewModel { private final CompositeDisposable disposables = new CompositeDisposable(); - protected NavigationViewModel(@NonNull Application application) { + protected LaoViewModel(@NonNull Application application) { super(application); } diff --git a/fe2-android/app/src/main/java/com/github/dedis/popstellar/ui/socialmedia/SocialMediaActivity.java b/fe2-android/app/src/main/java/com/github/dedis/popstellar/ui/socialmedia/SocialMediaActivity.java index b211d0409c..89c99971e1 100644 --- a/fe2-android/app/src/main/java/com/github/dedis/popstellar/ui/socialmedia/SocialMediaActivity.java +++ b/fe2-android/app/src/main/java/com/github/dedis/popstellar/ui/socialmedia/SocialMediaActivity.java @@ -15,8 +15,8 @@ import com.github.dedis.popstellar.ui.detail.LaoDetailActivity; import com.github.dedis.popstellar.ui.digitalcash.DigitalCashActivity; import com.github.dedis.popstellar.ui.home.HomeActivity; +import com.github.dedis.popstellar.ui.navigation.LaoActivity; import com.github.dedis.popstellar.ui.navigation.MainMenuTab; -import com.github.dedis.popstellar.ui.navigation.NavigationActivity; import com.github.dedis.popstellar.utility.ActivityUtils; import com.github.dedis.popstellar.utility.Constants; @@ -28,7 +28,7 @@ /** Activity for the social media */ @AndroidEntryPoint -public class SocialMediaActivity extends NavigationActivity { +public class SocialMediaActivity extends LaoActivity { private SocialMediaViewModel viewModel; private SocialMediaActivityBinding binding; @@ -41,12 +41,12 @@ protected void onCreate(Bundle savedInstanceState) { binding = SocialMediaActivityBinding.inflate(getLayoutInflater()); setContentView(binding.getRoot()); - navigationViewModel = viewModel = obtainViewModel(this); + laoViewModel = viewModel = obtainViewModel(this); String laoId = Objects.requireNonNull(getIntent().getStringExtra(Constants.LAO_ID_EXTRA)); - navigationViewModel.setCurrentTab(MainMenuTab.SOCIAL_MEDIA); - setupDrawer( + laoViewModel.setCurrentTab(MainMenuTab.SOCIAL_MEDIA); + initializeLaoActivity( laoId, binding.socialMediaNavigationDrawer, binding.socialMediaAppBar, diff --git a/fe2-android/app/src/main/java/com/github/dedis/popstellar/ui/socialmedia/SocialMediaViewModel.java b/fe2-android/app/src/main/java/com/github/dedis/popstellar/ui/socialmedia/SocialMediaViewModel.java index 3cc629f472..c4ca425463 100644 --- a/fe2-android/app/src/main/java/com/github/dedis/popstellar/ui/socialmedia/SocialMediaViewModel.java +++ b/fe2-android/app/src/main/java/com/github/dedis/popstellar/ui/socialmedia/SocialMediaViewModel.java @@ -18,7 +18,7 @@ import com.github.dedis.popstellar.model.objects.view.LaoView; import com.github.dedis.popstellar.repository.*; import com.github.dedis.popstellar.repository.remote.GlobalNetworkManager; -import com.github.dedis.popstellar.ui.navigation.NavigationViewModel; +import com.github.dedis.popstellar.ui.navigation.LaoViewModel; import com.github.dedis.popstellar.utility.ActivityUtils; import com.github.dedis.popstellar.utility.error.ErrorUtils; import com.github.dedis.popstellar.utility.error.UnknownLaoException; @@ -39,7 +39,7 @@ import io.reactivex.disposables.CompositeDisposable; @HiltViewModel -public class SocialMediaViewModel extends NavigationViewModel { +public class SocialMediaViewModel extends LaoViewModel { public static final String TAG = SocialMediaViewModel.class.getSimpleName(); private static final String LAO_FAILURE_MESSAGE = "failed to retrieve lao"; private static final String SOCIAL = "social"; From db826ea0889c113533efebd3c6c6244ce3c9fb50 Mon Sep 17 00:00:00 2001 From: Johann Pluss Date: Sun, 15 Jan 2023 15:41:42 +0100 Subject: [PATCH 36/41] slight fixes MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Johann Plüss --- .../github/dedis/popstellar/repository/ElectionRepository.java | 2 +- .../com/github/dedis/popstellar/repository/LAORepository.java | 2 -- 2 files changed, 1 insertion(+), 3 deletions(-) diff --git a/fe2-android/app/src/main/java/com/github/dedis/popstellar/repository/ElectionRepository.java b/fe2-android/app/src/main/java/com/github/dedis/popstellar/repository/ElectionRepository.java index 405f617a77..717f8ef3dd 100644 --- a/fe2-android/app/src/main/java/com/github/dedis/popstellar/repository/ElectionRepository.java +++ b/fe2-android/app/src/main/java/com/github/dedis/popstellar/repository/ElectionRepository.java @@ -50,7 +50,7 @@ public void updateElection(@NonNull Election election) { * @throws UnknownElectionException if no election with this id exist in this lao */ @NonNull - public com.github.dedis.popstellar.model.objects.Election getElection(@NonNull String laoId, @NonNull String electionId) + public Election getElection(@NonNull String laoId, @NonNull String electionId) throws UnknownElectionException { return getLaoElections(laoId).getElection(electionId); } diff --git a/fe2-android/app/src/main/java/com/github/dedis/popstellar/repository/LAORepository.java b/fe2-android/app/src/main/java/com/github/dedis/popstellar/repository/LAORepository.java index 6f83426ecc..c00b4caa60 100644 --- a/fe2-android/app/src/main/java/com/github/dedis/popstellar/repository/LAORepository.java +++ b/fe2-android/app/src/main/java/com/github/dedis/popstellar/repository/LAORepository.java @@ -56,8 +56,6 @@ public Observable getLaoObservable(String laoId) { } public LaoView getLaoView(String id) throws UnknownLaoException { - Log.d(TAG, "id:" + id); - Log.d(TAG, "laos:" + laoById.values()); Lao lao = laoById.get(id); if (lao == null) { throw new UnknownLaoException(id); From 96aade7ac894bb1e38849390fcb361917e0d7ff0 Mon Sep 17 00:00:00 2001 From: Johann Pluss Date: Sun, 15 Jan 2023 15:41:42 +0100 Subject: [PATCH 37/41] slight fixes MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Johann Plüss --- .../repository/ElectionRepository.java | 2 +- .../popstellar/repository/LAORepository.java | 2 -- .../ui/detail/LaoDetailViewModel.java | 2 +- .../ui/digitalcash/DigitalCashActivity.java | 18 +++--------------- 4 files changed, 5 insertions(+), 19 deletions(-) diff --git a/fe2-android/app/src/main/java/com/github/dedis/popstellar/repository/ElectionRepository.java b/fe2-android/app/src/main/java/com/github/dedis/popstellar/repository/ElectionRepository.java index 405f617a77..717f8ef3dd 100644 --- a/fe2-android/app/src/main/java/com/github/dedis/popstellar/repository/ElectionRepository.java +++ b/fe2-android/app/src/main/java/com/github/dedis/popstellar/repository/ElectionRepository.java @@ -50,7 +50,7 @@ public void updateElection(@NonNull Election election) { * @throws UnknownElectionException if no election with this id exist in this lao */ @NonNull - public com.github.dedis.popstellar.model.objects.Election getElection(@NonNull String laoId, @NonNull String electionId) + public Election getElection(@NonNull String laoId, @NonNull String electionId) throws UnknownElectionException { return getLaoElections(laoId).getElection(electionId); } diff --git a/fe2-android/app/src/main/java/com/github/dedis/popstellar/repository/LAORepository.java b/fe2-android/app/src/main/java/com/github/dedis/popstellar/repository/LAORepository.java index 6f83426ecc..c00b4caa60 100644 --- a/fe2-android/app/src/main/java/com/github/dedis/popstellar/repository/LAORepository.java +++ b/fe2-android/app/src/main/java/com/github/dedis/popstellar/repository/LAORepository.java @@ -56,8 +56,6 @@ public Observable getLaoObservable(String laoId) { } public LaoView getLaoView(String id) throws UnknownLaoException { - Log.d(TAG, "id:" + id); - Log.d(TAG, "laos:" + laoById.values()); Lao lao = laoById.get(id); if (lao == null) { throw new UnknownLaoException(id); diff --git a/fe2-android/app/src/main/java/com/github/dedis/popstellar/ui/detail/LaoDetailViewModel.java b/fe2-android/app/src/main/java/com/github/dedis/popstellar/ui/detail/LaoDetailViewModel.java index 9b55f22b15..b80fb5af0a 100644 --- a/fe2-android/app/src/main/java/com/github/dedis/popstellar/ui/detail/LaoDetailViewModel.java +++ b/fe2-android/app/src/main/java/com/github/dedis/popstellar/ui/detail/LaoDetailViewModel.java @@ -131,7 +131,7 @@ private boolean attendedOrOrganized(RollCall rollcall) { // find out if user has attended the rollcall try { PublicKey pk = wallet.generatePoPToken(laoId, rollcall.getPersistentId()).getPublicKey(); - return rollcall.getAttendees().contains(pk) || Boolean.TRUE.equals(isOrganizer()); + return rollcall.getAttendees().contains(pk) || isOrganizer(); } catch (KeyGenerationException | UninitializedWalletException e) { Log.e(TAG, "failed to retrieve public key from wallet", e); return false; diff --git a/fe2-android/app/src/main/java/com/github/dedis/popstellar/ui/digitalcash/DigitalCashActivity.java b/fe2-android/app/src/main/java/com/github/dedis/popstellar/ui/digitalcash/DigitalCashActivity.java index ab5cf3ff67..cd4441f002 100644 --- a/fe2-android/app/src/main/java/com/github/dedis/popstellar/ui/digitalcash/DigitalCashActivity.java +++ b/fe2-android/app/src/main/java/com/github/dedis/popstellar/ui/digitalcash/DigitalCashActivity.java @@ -12,7 +12,6 @@ import com.github.dedis.popstellar.R; import com.github.dedis.popstellar.databinding.DigitalCashMainActivityBinding; -import com.github.dedis.popstellar.model.objects.security.PublicKey; import com.github.dedis.popstellar.ui.detail.LaoDetailActivity; import com.github.dedis.popstellar.ui.home.HomeActivity; import com.github.dedis.popstellar.ui.navigation.LaoActivity; @@ -21,7 +20,6 @@ import com.github.dedis.popstellar.utility.ActivityUtils; import com.github.dedis.popstellar.utility.Constants; import com.github.dedis.popstellar.utility.error.ErrorUtils; -import com.github.dedis.popstellar.utility.error.UnknownLaoException; import java.security.GeneralSecurityException; import java.util.Objects; @@ -165,25 +163,15 @@ private void openReceiveTab() { DigitalCashReceiveFragment::newInstance); } - private boolean openIssueTab() { - try { - PublicKey organizerKey = viewModel.getLao().getOrganizer(); - if (!viewModel.getOwnKey().equals(organizerKey)) { - ErrorUtils.logAndShow(this, TAG, R.string.digital_cash_non_organizer_error_issue); - return false; - } - } catch (UnknownLaoException e) { - ErrorUtils.logAndShow(this, TAG, e, R.string.unknown_lao_exception); - return false; + private void openIssueTab() { + if (!viewModel.isOrganizer()) { + ErrorUtils.logAndShow(this, TAG, R.string.digital_cash_non_organizer_error_issue); } - setCurrentFragment( getSupportFragmentManager(), R.id.fragment_digital_cash_issue, DigitalCashIssueFragment::newInstance); viewModel.setPageTitle(R.string.digital_cash_issue); - - return true; } private void openSocialMediaTab() { From c1222db050ae6f8a8fb0c40ec7c2c3ff163ea33a Mon Sep 17 00:00:00 2001 From: Johann Pluss Date: Tue, 17 Jan 2023 16:33:40 +0100 Subject: [PATCH 38/41] Improve header spacing MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Johann Plüss --- .../main/res/layout/header_navigation_drawer.xml | 16 +++++++++++----- fe2-android/app/src/main/res/values/dimens.xml | 3 ++- 2 files changed, 13 insertions(+), 6 deletions(-) diff --git a/fe2-android/app/src/main/res/layout/header_navigation_drawer.xml b/fe2-android/app/src/main/res/layout/header_navigation_drawer.xml index bda5375667..78dc351fc6 100644 --- a/fe2-android/app/src/main/res/layout/header_navigation_drawer.xml +++ b/fe2-android/app/src/main/res/layout/header_navigation_drawer.xml @@ -6,26 +6,32 @@ android:layout_width="match_parent" android:layout_height="wrap_content" android:background="@color/colorPrimary" - android:paddingBottom="@dimen/header_layout_padding" android:fitsSystemWindows="true"> + android:textSize="@dimen/size_body" + android:textStyle="bold" + android:layout_marginTop="@dimen/margin_top" + app:layout_constraintTop_toBottomOf="@id/drawer_header_lao_title" + android:layout_marginHorizontal="@dimen/drawer_header_horizontal_margin" + app:layout_constraintBottom_toBottomOf="parent" + android:layout_marginBottom="@dimen/drawer_header_vertical_margin" /> diff --git a/fe2-android/app/src/main/res/values/dimens.xml b/fe2-android/app/src/main/res/values/dimens.xml index ec7bcb82af..17bc151d33 100644 --- a/fe2-android/app/src/main/res/values/dimens.xml +++ b/fe2-android/app/src/main/res/values/dimens.xml @@ -144,5 +144,6 @@ 1dp - 16dp + 20dp + 16dp From 2d083aeba5981e549c7fffdc8de6bc68b09d91a5 Mon Sep 17 00:00:00 2001 From: Johann Pluss Date: Tue, 17 Jan 2023 16:36:31 +0100 Subject: [PATCH 39/41] Replace lifecycle provided MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Johann Plüss --- .../com/github/dedis/popstellar/ui/detail/InviteFragment.java | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/fe2-android/app/src/main/java/com/github/dedis/popstellar/ui/detail/InviteFragment.java b/fe2-android/app/src/main/java/com/github/dedis/popstellar/ui/detail/InviteFragment.java index 66339d44f8..751ea71e70 100644 --- a/fe2-android/app/src/main/java/com/github/dedis/popstellar/ui/detail/InviteFragment.java +++ b/fe2-android/app/src/main/java/com/github/dedis/popstellar/ui/detail/InviteFragment.java @@ -62,7 +62,8 @@ public View onCreateView( viewModel .getRole() .observe( - requireActivity(), role -> binding.laoPropertiesRoleText.setText(role.getStringId())); + getViewLifecycleOwner(), + role -> binding.laoPropertiesRoleText.setText(role.getStringId())); } catch (UnknownLaoException e) { ErrorUtils.logAndShow(requireContext(), TAG, e, R.string.unknown_lao_exception); From 00decd9a42b5a13547260783f1ce5ad291f8f3be Mon Sep 17 00:00:00 2001 From: Johann Pluss Date: Tue, 17 Jan 2023 17:17:22 +0100 Subject: [PATCH 40/41] Update comments MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Johann Plüss --- .../popstellar/ui/navigation/LaoActivity.java | 16 ++++++++-------- .../popstellar/ui/navigation/LaoViewModel.java | 7 +------ 2 files changed, 9 insertions(+), 14 deletions(-) diff --git a/fe2-android/app/src/main/java/com/github/dedis/popstellar/ui/navigation/LaoActivity.java b/fe2-android/app/src/main/java/com/github/dedis/popstellar/ui/navigation/LaoActivity.java index f2d580bb88..2548fe4080 100644 --- a/fe2-android/app/src/main/java/com/github/dedis/popstellar/ui/navigation/LaoActivity.java +++ b/fe2-android/app/src/main/java/com/github/dedis/popstellar/ui/navigation/LaoActivity.java @@ -30,10 +30,10 @@ import io.reactivex.android.schedulers.AndroidSchedulers; /** - * This abstract activity encapsulate the redundant behavior of an activity with a navigation bar + * This abstract activity encapsulate the redundant behavior of an activity in a LAO * - *

An activity extending this must instantiate the navigationViewModel in its onCreate and it - * should call initializeLaoActivity with the navigationView as parameter. + *

An activity extending this must instantiate the laoViewModel in its onCreate and it should + * call initializeLaoActivity */ @AndroidEntryPoint public abstract class LaoActivity extends AppCompatActivity { @@ -48,12 +48,12 @@ public abstract class LaoActivity extends AppCompatActivity { @Inject Wallet wallet; /** - * Setup the navigation bar listeners given the navigation bar view + * Initialize the parent activity. It sets up views common to the 3 activities * - *

This function should be called in the activity's onCreate after the navigation view model - * has been set - * - * @param navigationView the view + * @param laoId the id of the LAO + * @param navigationView the drawer navigation view + * @param toolbar the activity toolbar + * @param drawerLayout the drawer layout */ protected void initializeLaoActivity( String laoId, diff --git a/fe2-android/app/src/main/java/com/github/dedis/popstellar/ui/navigation/LaoViewModel.java b/fe2-android/app/src/main/java/com/github/dedis/popstellar/ui/navigation/LaoViewModel.java index 218ee8e0d1..bea392dced 100644 --- a/fe2-android/app/src/main/java/com/github/dedis/popstellar/ui/navigation/LaoViewModel.java +++ b/fe2-android/app/src/main/java/com/github/dedis/popstellar/ui/navigation/LaoViewModel.java @@ -18,12 +18,7 @@ import io.reactivex.disposables.CompositeDisposable; import io.reactivex.disposables.Disposable; -/** - * Abstract view model that provides the components of the navigation bar - * - *

Any activity that uses a navigation bar should have its view model extends from the this * - * class - */ +/** Abstract view model that provides the common interface for lao activities */ public abstract class LaoViewModel extends AndroidViewModel { private final MutableLiveData currentTab = new MutableLiveData<>(); From 46688b0ab2e122f9c56ac147c6ccec275661cc10 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Johann=20Pl=C3=BCss?= <45600803+Warhedgehog@users.noreply.github.com> Date: Tue, 17 Jan 2023 17:18:15 +0100 Subject: [PATCH 41/41] Slight improvement Co-authored-by: Gabriel Fleischer --- .../dedis/popstellar/ui/socialmedia/ChirpListAdapterTest.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/fe2-android/app/src/test/ui/robolectric/com/github/dedis/popstellar/ui/socialmedia/ChirpListAdapterTest.java b/fe2-android/app/src/test/ui/robolectric/com/github/dedis/popstellar/ui/socialmedia/ChirpListAdapterTest.java index 2f3f6a392f..703c7ddcb1 100644 --- a/fe2-android/app/src/test/ui/robolectric/com/github/dedis/popstellar/ui/socialmedia/ChirpListAdapterTest.java +++ b/fe2-android/app/src/test/ui/robolectric/com/github/dedis/popstellar/ui/socialmedia/ChirpListAdapterTest.java @@ -41,7 +41,7 @@ public class ChirpListAdapterTest { private final Intent intent = new Intent(ApplicationProvider.getApplicationContext(), SocialMediaActivity.class) - .putExtra(Constants.LAO_ID_EXTRA, ""); + .putExtra(Constants.LAO_ID_EXTRA, LAO_ID); private final ActivityScenarioRule activityScenarioRule = new ActivityScenarioRule<>(intent);