Add Contact Details

master
Paul Schaub 5 years ago
parent 350e665cef
commit 7bc1207581
Signed by: vanitasvitae
GPG Key ID: 62BEE9264BF17311
  1. 1
      mobile/src/main/AndroidManifest.xml
  2. 17
      mobile/src/main/java/de/vanitasvitae/slam/mvp/DummyStore.java
  3. 8
      mobile/src/main/java/de/vanitasvitae/slam/mvp/contracts/ContactDetailContract.java
  4. 4
      mobile/src/main/java/de/vanitasvitae/slam/mvp/contracts/ContactListContract.java
  5. 1
      mobile/src/main/java/de/vanitasvitae/slam/mvp/contracts/ConversationListContract.java
  6. 17
      mobile/src/main/java/de/vanitasvitae/slam/mvp/presenter/dummy/DummyContactDetailPresenter.java
  7. 3
      mobile/src/main/java/de/vanitasvitae/slam/mvp/presenter/dummy/DummyContactListPresenter.java
  8. 174
      mobile/src/main/java/de/vanitasvitae/slam/mvp/view/ContactDetailActivity.java
  9. 47
      mobile/src/main/java/de/vanitasvitae/slam/mvp/view/ContactDetailInfoFragment.java
  10. 97
      mobile/src/main/java/de/vanitasvitae/slam/mvp/view/ContactDetailResourcesFragment.java
  11. 42
      mobile/src/main/java/de/vanitasvitae/slam/mvp/view/ContactDetailSecurityFragment.java
  12. 88
      mobile/src/main/java/de/vanitasvitae/slam/mvp/view/ContactListFragment.java
  13. 28
      mobile/src/main/java/de/vanitasvitae/slam/mvp/view/ConversationFragment.java
  14. 86
      mobile/src/main/java/de/vanitasvitae/slam/mvp/view/ConversationListFragment.java
  15. 10
      mobile/src/main/java/de/vanitasvitae/slam/mvp/view/LoginActivity.java
  16. 37
      mobile/src/main/java/de/vanitasvitae/slam/mvp/view/MainActivity.java
  17. 2
      mobile/src/main/java/de/vanitasvitae/slam/mvp/view/SearchFragment.java
  18. 15
      mobile/src/main/java/de/vanitasvitae/slam/ui/ChatMessageEntry.java
  19. 48
      mobile/src/main/java/de/vanitasvitae/slam/ui/ContactListEntry.java
  20. 20
      mobile/src/main/java/de/vanitasvitae/slam/ui/ConversationEntry.java
  21. 17
      mobile/src/main/java/de/vanitasvitae/slam/xmpp/Contact.java
  22. 17
      mobile/src/main/java/de/vanitasvitae/slam/xmpp/Conversation.java
  23. 49
      mobile/src/main/java/de/vanitasvitae/slam/xmpp/Resource.java
  24. BIN
      mobile/src/main/res/drawable-hdpi/ic_chat_black_48dp.png
  25. BIN
      mobile/src/main/res/drawable-hdpi/ic_chat_white_48dp.png
  26. BIN
      mobile/src/main/res/drawable-hdpi/ic_public_black_48dp.png
  27. BIN
      mobile/src/main/res/drawable-hdpi/ic_public_white_48dp.png
  28. BIN
      mobile/src/main/res/drawable-mdpi/ic_chat_black_48dp.png
  29. BIN
      mobile/src/main/res/drawable-mdpi/ic_chat_white_48dp.png
  30. BIN
      mobile/src/main/res/drawable-mdpi/ic_public_black_48dp.png
  31. BIN
      mobile/src/main/res/drawable-mdpi/ic_public_white_48dp.png
  32. BIN
      mobile/src/main/res/drawable-xhdpi/ic_chat_black_48dp.png
  33. BIN
      mobile/src/main/res/drawable-xhdpi/ic_chat_white_48dp.png
  34. BIN
      mobile/src/main/res/drawable-xhdpi/ic_public_black_48dp.png
  35. BIN
      mobile/src/main/res/drawable-xhdpi/ic_public_white_48dp.png
  36. BIN
      mobile/src/main/res/drawable-xxhdpi/ic_chat_black_48dp.png
  37. BIN
      mobile/src/main/res/drawable-xxhdpi/ic_chat_white_48dp.png
  38. BIN
      mobile/src/main/res/drawable-xxhdpi/ic_public_black_48dp.png
  39. BIN
      mobile/src/main/res/drawable-xxhdpi/ic_public_white_48dp.png
  40. BIN
      mobile/src/main/res/drawable-xxxhdpi/ic_chat_black_48dp.png
  41. BIN
      mobile/src/main/res/drawable-xxxhdpi/ic_chat_white_48dp.png
  42. BIN
      mobile/src/main/res/drawable-xxxhdpi/ic_public_black_48dp.png
  43. BIN
      mobile/src/main/res/drawable-xxxhdpi/ic_public_white_48dp.png
  44. BIN
      mobile/src/main/res/drawable/background_image.png
  45. BIN
      mobile/src/main/res/drawable/face.png
  46. 111
      mobile/src/main/res/layout/activity_contact_detail.xml
  47. 6
      mobile/src/main/res/layout/activity_login.xml
  48. 57
      mobile/src/main/res/layout/fragment_contact_detail.xml
  49. 48
      mobile/src/main/res/layout/fragment_contact_detail__info.xml
  50. 14
      mobile/src/main/res/layout/fragment_contact_detail__resources.xml
  51. 22
      mobile/src/main/res/layout/fragment_contact_detail__security.xml
  52. 0
      mobile/src/main/res/layout/fragment_conversation.xml
  53. 2
      mobile/src/main/res/layout/fragment_conversation_contact_list.xml
  54. 37
      mobile/src/main/res/layout/item_contact.xml
  55. 2
      mobile/src/main/res/layout/item_conversation_list.xml
  56. 1
      mobile/src/main/res/layout/item_conversation_message.xml
  57. 151
      mobile/src/main/res/layout/item_resource.xml
  58. 5
      mobile/src/main/res/layout/toolbar_main.xml
  59. 20
      mobile/src/main/res/menu/drawer_main.xml
  60. 2
      mobile/src/main/res/menu/menu_login.xml
  61. 4
      mobile/src/main/res/menu/menu_main.xml
  62. 2
      mobile/src/main/res/values/attrs.xml
  63. 47
      mobile/src/main/res/values/strings.xml
  64. 6
      mobile/src/main/res/values/styles.xml

@ -27,6 +27,7 @@
</intent-filter>
</activity>
<activity android:name=".mvp.view.MainActivity" />
<activity android:name=".mvp.view.ContactDetailActivity" />
<meta-data
android:name="com.google.android.gms.car.application"

@ -1,3 +1,20 @@
/*
* Copyright 2018 Paul Schaub
*
* This code is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software Foundation,
* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*/
package de.vanitasvitae.slam.mvp;
import org.jivesoftware.smack.packet.Message;

@ -17,19 +17,19 @@
*/
package de.vanitasvitae.slam.mvp.contracts;
import org.jivesoftware.smack.packet.Presence;
import java.util.List;
import de.vanitasvitae.slam.xmpp.Resource;
/**
* Model-View-Presenter contract for the {@link de.vanitasvitae.slam.mvp.view.ContactDetailFragment}.
* Model-View-Presenter contract for the {@link de.vanitasvitae.slam.mvp.view.ContactDetailActivity}.
*/
public interface ContactDetailContract {
interface View {
void setContactAvatar();
void setNickname(String nickname);
void setPresence(Presence presence);
void setResources(List<Resource> presences);
void clearFingerprints();
void addFingerprints(List<?> fingerprints);
}

@ -22,6 +22,7 @@ import org.jxmpp.jid.BareJid;
import java.util.List;
import de.vanitasvitae.slam.mvp.view.ConversationListFragment;
import de.vanitasvitae.slam.xmpp.Contact;
/**
* Model-View-Presenter contract for the {@link ConversationListFragment}.
@ -31,12 +32,13 @@ import de.vanitasvitae.slam.mvp.view.ConversationListFragment;
public interface ContactListContract {
interface View {
void addContactListItems(List<?> contacts);
void addContactListItems(List<Contact> contacts);
void clearContactListItems();
void onUpdateContactPresence();
void showContactListLoadingIndicator();
void hideContactListLoadingIndicator();
void navigateToConversation(BareJid contact);
void navigateToContactDetail(BareJid contact);
}
interface Presenter {

@ -32,6 +32,7 @@ public interface ConversationListContract {
interface View {
void populateConversationList(List<Conversation> conversations);
void navigateToConversation(BareJid contact);
void navigateToContactDetail(BareJid contact);
}
interface Presenter {

@ -17,9 +17,15 @@
*/
package de.vanitasvitae.slam.mvp.presenter.dummy;
import android.util.Log;
import org.jxmpp.jid.BareJid;
import java.util.ArrayList;
import java.util.List;
import de.vanitasvitae.slam.mvp.contracts.ContactDetailContract;
import de.vanitasvitae.slam.xmpp.Resource;
public class DummyContactDetailPresenter implements ContactDetailContract.Presenter {
@ -28,6 +34,17 @@ public class DummyContactDetailPresenter implements ContactDetailContract.Presen
public DummyContactDetailPresenter(ContactDetailContract.View view) {
this.view = view;
Log.d("SLAM", "Set dummy resources");
view.setResources(dummyResources());
}
private List<Resource> dummyResources() {
List<Resource> r = new ArrayList<>();
r.add(new Resource("Mobile", "Away since 15min", "Conversations 1.23.4", "Android"));
r.add(new Resource("Laptop", "online", "Gajim 16.0.6", "Arch Linux"));
r.add(new Resource("Desktop", "I like coffee!", "Dino", "Debian Stable"));
return r;
}
@Override

@ -17,6 +17,8 @@
*/
package de.vanitasvitae.slam.mvp.presenter.dummy;
import de.vanitasvitae.slam.mvp.DummyPresenterFactory;
import de.vanitasvitae.slam.mvp.DummyStore;
import de.vanitasvitae.slam.mvp.contracts.ContactListContract;
public class DummyContactListPresenter implements ContactListContract.Presenter {
@ -25,6 +27,7 @@ public class DummyContactListPresenter implements ContactListContract.Presenter
public DummyContactListPresenter(ContactListContract.View view) {
this.view = view;
view.addContactListItems(DummyPresenterFactory.STORE.contacts);
}
@Override

@ -0,0 +1,174 @@
/*
* Copyright 2018 Paul Schaub
*
* This code is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software Foundation,
* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*/
package de.vanitasvitae.slam.mvp.view;
import android.os.Bundle;
import android.support.design.widget.AppBarLayout;
import android.support.design.widget.TabLayout;
import android.support.v4.app.FragmentManager;
import android.support.v4.app.FragmentPagerAdapter;
import android.support.v4.view.ViewPager;
import android.support.v7.widget.Toolbar;
import java.util.List;
import butterknife.BindView;
import butterknife.ButterKnife;
import de.hdodenhof.circleimageview.CircleImageView;
import de.vanitasvitae.slam.R;
import de.vanitasvitae.slam.mvp.PresenterFactory;
import de.vanitasvitae.slam.mvp.contracts.ContactDetailContract;
import de.vanitasvitae.slam.mvp.view.abstr.ThemedAppCompatActivity;
import de.vanitasvitae.slam.xmpp.Resource;
/**
* Main activity that hosts some fragments.
*/
public class ContactDetailActivity extends ThemedAppCompatActivity implements ContactDetailContract.View, AppBarLayout.OnOffsetChangedListener {
public static final String TAG = "Slam!";
private final ContactDetailContract.Presenter presenter;
private final ContactDetailResourcesFragment resourcesFragment = new ContactDetailResourcesFragment();
private final ContactDetailInfoFragment infoFragment = new ContactDetailInfoFragment();
private final ContactDetailSecurityFragment securityFragment = new ContactDetailSecurityFragment();
@BindView(R.id.contact_detail_toolbar)
Toolbar toolbar;
@BindView(R.id.contact_detail_appbar_layout)
AppBarLayout appBarLayout;
@BindView(R.id.contact_detail_tab_layout)
TabLayout tabLayout;
@BindView(R.id.contact_detail_viewpager)
ViewPager pager;
@BindView(R.id.contact_detail_profile_circle)
CircleImageView profileCircle;
private int mMaxScrollSize;
private boolean isProfileCircleShown;
private int animateProfileCirclePercent = 20;
public ContactDetailActivity() {
this.presenter = PresenterFactory.getInstance().createContactDetailPresenter(this);
}
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_contact_detail);
ButterKnife.bind(this);
setSupportActionBar(toolbar);
getSupportActionBar().setDisplayHomeAsUpEnabled(true);
appBarLayout.addOnOffsetChangedListener(this);
pager.setAdapter(new DetailFragmentPagerAdapter(getSupportFragmentManager()));
tabLayout.setupWithViewPager(pager);
}
@Override
public void onOffsetChanged(AppBarLayout appBarLayout, int i) {
if (mMaxScrollSize == 0)
mMaxScrollSize = appBarLayout.getTotalScrollRange();
int percentage = (Math.abs(i)) * 100 / mMaxScrollSize;
if (percentage >= animateProfileCirclePercent && isProfileCircleShown) {
isProfileCircleShown = false;
profileCircle.animate()
.scaleY(0).scaleX(0)
.setDuration(200)
.start();
}
if (percentage <= animateProfileCirclePercent && !isProfileCircleShown) {
isProfileCircleShown = true;
profileCircle.animate()
.scaleY(1).scaleX(1)
.start();
}
}
@Override
public void setContactAvatar() {
}
@Override
public void setNickname(String nickname) {
}
@Override
public void setResources(List<Resource> resources) {
resourcesFragment.setResources(resources);
}
@Override
public void clearFingerprints() {
}
@Override
public void addFingerprints(List<?> fingerprints) {
}
class DetailFragmentPagerAdapter extends FragmentPagerAdapter {
public DetailFragmentPagerAdapter(FragmentManager fm) {
super(fm);
}
@Override
public android.support.v4.app.Fragment getItem(int position) {
switch (position) {
case 0: return infoFragment;
case 1: return resourcesFragment;
case 2: return securityFragment;
default: return infoFragment;
}
}
@Override
public int getCount() {
return 3;
}
@Override
public CharSequence getPageTitle(int position) {
//TODO
switch (position) {
case 0:
return "Info";
case 1:
return "Devices";
case 2:
return "Security";
}
return null;
}
}
}

@ -17,60 +17,25 @@
*/
package de.vanitasvitae.slam.mvp.view;
import android.app.Fragment;
import android.os.Bundle;
import android.support.v4.app.Fragment;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import org.jivesoftware.smack.packet.Presence;
import org.jxmpp.jid.BareJid;
import java.util.List;
import butterknife.ButterKnife;
import de.vanitasvitae.slam.R;
import de.vanitasvitae.slam.mvp.PresenterFactory;
import de.vanitasvitae.slam.mvp.contracts.ContactDetailContract;
public class ContactDetailFragment extends Fragment implements ContactDetailContract.View {
private final ContactDetailContract.Presenter presenter;
public ContactDetailFragment() {
this.presenter = PresenterFactory.getInstance().createContactDetailPresenter(this);
}
/**
* Created by Paul Schaub on 13.02.18.
*/
public class ContactDetailInfoFragment extends Fragment {
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
View view = inflater.inflate(R.layout.fragment_contact_detail, container, false);
View view = inflater.inflate(R.layout.fragment_contact_detail__info, container, false);
ButterKnife.bind(this, view);
return view;
}
@Override
public void setContactAvatar() {
}
@Override
public void setNickname(String nickname) {
}
@Override
public void setPresence(Presence presence) {
}
@Override
public void clearFingerprints() {
}
@Override
public void addFingerprints(List<?> fingerprints) {
}
}

@ -0,0 +1,97 @@
/*
* Copyright 2018 Paul Schaub
*
* This code is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software Foundation,
* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*/
package de.vanitasvitae.slam.mvp.view;
import android.os.Bundle;
import android.support.v4.app.Fragment;
import android.support.v7.widget.LinearLayoutManager;
import android.support.v7.widget.RecyclerView;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.TextView;
import java.util.ArrayList;
import java.util.List;
import butterknife.BindView;
import butterknife.ButterKnife;
import de.vanitasvitae.slam.R;
import de.vanitasvitae.slam.xmpp.Resource;
/**
* Created by Paul Schaub on 13.02.18.
*/
public class ContactDetailResourcesFragment extends Fragment {
@BindView(R.id.contact_detail_resources_recycler_view)
RecyclerView resourcesRecyclerView;
private final List<Resource> resources = new ArrayList<>();
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
View view = inflater.inflate(R.layout.fragment_contact_detail__resources, container, false);
ButterKnife.bind(this, view);
resourcesRecyclerView.setLayoutManager(new LinearLayoutManager(getActivity()));
resourcesRecyclerView.setAdapter(resourcesAdapter);
resourcesAdapter.notifyDataSetChanged();
return view;
}
public void setResources(List<Resource> resources) {
this.resources.clear();
this.resources.addAll(resources);
resourcesAdapter.notifyDataSetChanged();
}
private final RecyclerView.Adapter<ResourceView> resourcesAdapter = new RecyclerView.Adapter<ResourceView>() {
@Override
public ResourceView onCreateViewHolder(ViewGroup parent, int viewType) {
View resourceView = LayoutInflater.from(getActivity()).inflate(R.layout.item_resource, parent, false);
return new ResourceView(resourceView);
}
@Override
public void onBindViewHolder(final ResourceView holder, final int position) {
Resource resource = resources.get(holder.getAdapterPosition());
holder.bind(resource);
}
@Override
public int getItemCount() {
return resources.size();
}
};
static class ResourceView extends RecyclerView.ViewHolder {
public ResourceView(View itemView) {
super(itemView);
}
public void bind(Resource resource) {
((TextView)itemView.findViewById(R.id.resource__resource_value)).setText(resource.getResource());
((TextView)itemView.findViewById(R.id.resource__status_value)).setText(resource.getStatus());
((TextView)itemView.findViewById(R.id.resource__client_value)).setText(resource.getClient());
((TextView)itemView.findViewById(R.id.resource__system_value)).setText(resource.getSystem());
}
}
}

@ -0,0 +1,42 @@
/*
* Copyright 2018 Paul Schaub
*
* This code is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software Foundation,
* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*/
package de.vanitasvitae.slam.mvp.view;
import android.os.Bundle;
import android.support.v4.app.Fragment;
import android.support.v4.app.FragmentPagerAdapter;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import butterknife.ButterKnife;
import de.vanitasvitae.slam.R;
/**
* Created by Paul Schaub on 13.02.18.
*/
public class ContactDetailSecurityFragment extends Fragment {
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
View view = inflater.inflate(R.layout.fragment_contact_detail__security, container, false);
ButterKnife.bind(this, view);
return view;
}
}

@ -1,36 +1,86 @@
/*
* Copyright 2018 Paul Schaub
*
* This code is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software Foundation,
* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*/
package de.vanitasvitae.slam.mvp.view;
import android.app.Fragment;
import android.content.Intent;
import android.os.Bundle;
import android.support.v4.app.Fragment;
import android.support.v7.widget.LinearLayoutManager;
import android.support.v7.widget.RecyclerView;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import org.jxmpp.jid.BareJid;
import java.util.ArrayList;
import java.util.List;
import butterknife.BindView;
import butterknife.ButterKnife;
import de.vanitasvitae.slam.R;
import de.vanitasvitae.slam.mvp.PresenterFactory;
import de.vanitasvitae.slam.mvp.contracts.ContactListContract;
import de.vanitasvitae.slam.ui.ContactListEntry;
import de.vanitasvitae.slam.xmpp.Contact;
/**
* Created by Paul Schaub on 11.02.18.
*/
public class ContactListFragment extends Fragment implements ContactListContract.View {
@BindView(R.id.recycler_list)
RecyclerView recyclerView;
private final ContactListContract.Presenter presenter;
private final List<Contact> contacts = new ArrayList<>();
public ContactListFragment() {
super();
this.presenter = PresenterFactory.getInstance().createContactListPresenter(this);
}
@Override
public void addContactListItems(List<?> contacts) {
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
View view = inflater.inflate(R.layout.fragment_conversation_contact_list, container, false);
ButterKnife.bind(this, view);
return view;
}
@Override
public void onViewCreated(final View view, Bundle savedInstanceState) {
recyclerView.setLayoutManager(new LinearLayoutManager(getContext()));
recyclerView.setAdapter(contactsAdapter);
contactsAdapter.notifyDataSetChanged();
}
@Override
public void clearContactListItems() {
public void addContactListItems(List<Contact> contacts) {
this.contacts.addAll(contacts);
contactsAdapter.notifyDataSetChanged();
}
@Override
public void clearContactListItems() {
this.contacts.clear();
contactsAdapter.notifyDataSetChanged();
}
@Override
@ -48,6 +98,31 @@ public class ContactListFragment extends Fragment implements ContactListContract
}
private final RecyclerView.Adapter<ContactListEntry> contactsAdapter = new RecyclerView.Adapter<ContactListEntry>() {
@Override
public ContactListEntry onCreateViewHolder(ViewGroup parent, int viewType) {
View contactView = LayoutInflater.from(getActivity()).inflate(R.layout.item_contact, parent, false);
return new ContactListEntry(contactView);
}
@Override
public void onBindViewHolder(ContactListEntry holder, int position) {
final Contact contact = contacts.get(holder.getAdapterPosition());
holder.bind(contact);
holder.setOnAvatarClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
navigateToContactDetail(contact.getJid());
}
});
}
@Override
public int getItemCount() {
return contacts.size();
}
};
@Override
public void navigateToConversation(BareJid contact) {
ConversationFragment fragment = new ConversationFragment();
@ -60,4 +135,11 @@ public class ContactListFragment extends Fragment implements ContactListContract
.addToBackStack("conversation")
.commit();
}
@Override
public void navigateToContactDetail(BareJid contact) {
startActivity(new Intent(getContext(), ContactDetailActivity.class));
}
}

@ -17,8 +17,9 @@
*/
package de.vanitasvitae.slam.mvp.view;
import android.app.Fragment;
import android.content.Intent;
import android.os.Bundle;
import android.support.v4.app.Fragment;
import android.support.v7.widget.LinearLayoutManager;
import android.support.v7.widget.RecyclerView;
import android.view.LayoutInflater;
@ -61,15 +62,7 @@ public class ConversationFragment extends Fragment implements ConversationContra
private final RecyclerView.Adapter<ChatMessageEntry> chatMessageAdapter = new RecyclerView.Adapter<ChatMessageEntry>() {
@Override
public ChatMessageEntry onCreateViewHolder(ViewGroup parent, int viewType) {
View messageView = LayoutInflater.from(getActivity()).inflate(R.layout.item_chatmessage, parent, false);
messageView.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
getFragmentManager().beginTransaction()
.replace(R.id.fragment_container, new ContactDetailFragment())
.commit();
}
});
View messageView = LayoutInflater.from(getActivity()).inflate(R.layout.item_conversation_message, parent, false);
return new ChatMessageEntry(messageView);
}
@ -83,6 +76,13 @@ public class ConversationFragment extends Fragment implements ConversationContra
((TextView)content).setText(message.getBody());
holder.bind(sender, role, content, "now");
holder.setOnAvatarClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
navigateToContactProfile();
}
});
}
@Override
@ -99,7 +99,7 @@ public class ConversationFragment extends Fragment implements ConversationContra
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
View view = inflater.inflate(R.layout.fragment_chat, container, false);
View view = inflater.inflate(R.layout.fragment_conversation, container, false);
ButterKnife.bind(this, view);
Bundle arguments = getArguments();
@ -145,10 +145,6 @@ public class ConversationFragment extends Fragment implements ConversationContra
@Override
public void navigateToContactProfile() {
getFragmentManager().beginTransaction()
.setCustomAnimations(android.R.animator.fade_in, android.R.animator.fade_out)
.add(R.id.fragment_container, new ContactDetailFragment())
.addToBackStack("detail")
.commit();
startActivity(new Intent(getContext(), ContactDetailActivity.class));
}
}

@ -17,8 +17,9 @@
*/
package de.vanitasvitae.slam.mvp.view;
import android.app.Fragment;
import android.content.Intent;
import android.os.Bundle;
import android.support.v4.app.Fragment;
import android.support.v7.widget.LinearLayoutManager;
import android.support.v7.widget.RecyclerView;
import android.view.LayoutInflater;
@ -45,45 +46,12 @@ import de.vanitasvitae.slam.xmpp.Conversation;
*/
public class ConversationListFragment extends Fragment implements ConversationListContract.View {
@BindView(R.id.recycler_chatlist)
@BindView(R.id.recycler_list)
RecyclerView recyclerView;
private final ConversationListContract.Presenter presenter;
private final List<Conversation> conversations = new ArrayList<>();
private final RecyclerView.Adapter<ConversationEntry> conversationEntryAdapter = new RecyclerView.Adapter<ConversationEntry>() {
@Override
public ConversationEntry onCreateViewHolder(ViewGroup parent, int viewType) {
View conversationView = LayoutInflater.from(getActivity()).inflate(R.layout.chatlist_singlechat, parent, false);
return new ConversationEntry(conversationView);
}
@Override
public void onBindViewHolder(final ConversationEntry holder, final int position) {
Conversation conversation = conversations.get(holder.getAdapterPosition());
String name = conversation.getContact().getNickname();
holder.bind(
name != null ? name : conversation.getContact().getJid().toString(),
conversation.getLastMessage(),
conversation.getDate(),
true);
holder.itemView.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
int pos = holder.getAdapterPosition();
navigateToConversation(conversations.get(pos).getContact().getJid());
}
});
}
@Override
public int getItemCount() {
return conversations.size();
}
};
public ConversationListFragment() {
super();
this.presenter = PresenterFactory.getInstance().createConversationListPresenter(this);
@ -92,7 +60,7 @@ public class ConversationListFragment extends Fragment implements ConversationLi
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
View view = inflater.inflate(R.layout.fragment_chatlist, container, false);
View view = inflater.inflate(R.layout.fragment_conversation_contact_list, container, false);
ButterKnife.bind(this, view);
return view;
}
@ -120,8 +88,52 @@ public class ConversationListFragment extends Fragment implements ConversationLi
fragment.setArguments(bundle);
getFragmentManager().beginTransaction()
.add(R.id.fragment_container, fragment)
.replace(R.id.fragment_container, fragment)
.addToBackStack("conversation")
.commit();
}
@Override
public void navigateToContactDetail(BareJid contact) {
startActivity(new Intent(getContext(), ContactDetailActivity.class));
}
private final RecyclerView.Adapter<ConversationEntry> conversationEntryAdapter = new RecyclerView.Adapter<ConversationEntry>() {
@Override
public ConversationEntry onCreateViewHolder(ViewGroup parent, int viewType) {
View conversationView = LayoutInflater.from(getActivity()).inflate(R.layout.item_conversation_list, parent, false);
return new ConversationEntry(conversationView);
}
@Override
public void onBindViewHolder(final ConversationEntry holder, final int position) {
final Conversation conversation = conversations.get(holder.getAdapterPosition());
String name = conversation.getContact().getNickname();
holder.bind(
name != null ? name : conversation.getContact().getJid().toString(),
conversation.getLastMessage(),
conversation.getDate(),
true);
holder.setOnEntryClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
navigateToConversation(conversation.getContact().getJid());
}
});
holder.setOnAvatarClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
navigateToContactDetail(conversation.getContact().getJid());
}
});
}
@Override
public int getItemCount() {
return conversations.size();
}
};
}

@ -37,10 +37,8 @@ import butterknife.OnClick;
import de.vanitasvitae.slam.AbstractTextWatcher;
import de.vanitasvitae.slam.EditorActionDoneListener;
import de.vanitasvitae.slam.R;
import de.vanitasvitae.slam.mvp.DummyPresenterFactory;
import de.vanitasvitae.slam.mvp.PresenterFactory;
import de.vanitasvitae.slam.mvp.view.abstr.ThemedAppCompatActivity;
import de.vanitasvitae.slam.mvp.presenter.dummy.DummyLoginPresenter;
import de.vanitasvitae.slam.mvp.contracts.LoginContract;
public class LoginActivity extends ThemedAppCompatActivity implements LoginContract.View {
@ -118,17 +116,17 @@ public class LoginActivity extends ThemedAppCompatActivity implements LoginContr
@Override
public void showInvalidJidError() {
inputUsernameLayout.setError(getResources().getText(R.string.error_invalid_jid));
inputUsernameLayout.setError(getResources().getText(R.string.login__error_invalid_jid));
}
@Override
public void showInvalidPasswordError() {
inputPasswordLayout.setError(getResources().getText(R.string.error_invalid_password));
inputPasswordLayout.setError(getResources().getText(R.string.login__error_invalid_password));
}
@Override
public void showIncorrectPasswordError() {
inputPasswordLayout.setError(getResources().getText(R.string.error_incorrect_password));
inputPasswordLayout.setError(getResources().getText(R.string.login__error_incorrect_password));
}
@Override
@ -143,7 +141,7 @@ public class LoginActivity extends ThemedAppCompatActivity implements LoginContr
@Override
public void showServerNotFoundError() {
Toast.makeText(this, R.string.error_server_not_found, Toast.LENGTH_LONG).show();
Toast.makeText(this, R.string.login__error_server_not_found, Toast.LENGTH_LONG).show();
}
@Override

@ -17,15 +17,17 @@
*/
package de.vanitasvitae.slam.mvp.view;
import android.app.Fragment;
import android.os.Bundle;
import android.support.annotation.NonNull;
import android.support.design.widget.NavigationView;
import android.support.v4.app.Fragment;
import android.support.v4.widget.DrawerLayout;
import android.support.v7.app.ActionBarDrawerToggle;
import android.support.v7.widget.Toolbar;
import android.util.Log;
import android.view.Menu;
import android.view.MenuItem;
import android.widget.FrameLayout;
import android.widget.Toast;
import butterknife.BindView;
import butterknife.ButterKnife;
@ -35,7 +37,7 @@ import de.vanitasvitae.slam.mvp.view.abstr.ThemedAppCompatActivity;
/**
* Main activity that hosts some fragments.
*/
public class MainActivity extends ThemedAppCompatActivity {
public class MainActivity extends ThemedAppCompatActivity implements NavigationView.OnNavigationItemSelectedListener {
public static final String TAG = "Slam!";
@ -62,11 +64,12 @@ public class MainActivity extends ThemedAppCompatActivity {
setSupportActionBar(toolbar);
drawerToggle = new ActionBarDrawerToggle(
this, drawerLayout, toolbar, R.string.error_incorrect_password, R.string.error_invalid_jid);
this, drawerLayout, toolbar, R.string.login__error_incorrect_password, R.string.login__error_invalid_jid);
drawerLayout.addDrawerListener(drawerToggle);
navigationView.setNavigationItemSelectedListener(this);
Fragment chatListFragment = new ConversationListFragment();
getFragmentManager().beginTransaction()
getSupportFragmentManager().beginTransaction()
.add(R.id.fragment_container, chatListFragment)
.addToBackStack("conversation_list")
.commit();
@ -83,4 +86,28 @@ public class MainActivity extends ThemedAppCompatActivity {
super.onPostCreate(savedInstanceState);
drawerToggle.syncState();
}
@Override
public boolean onNavigationItemSelected(@NonNull MenuItem item) {
drawerLayout.closeDrawers();
switch (item.getItemId()) {
case R.id.navdrawer__item_conversations:
getSupportFragmentManager().beginTransaction()
.replace(R.id.fragment_container, new ConversationListFragment())
.commit();
return true;
case R.id.navdrawer__item_contacts:
getSupportFragmentManager().beginTransaction()
.replace(R.id.fragment_container, new ContactListFragment())
.commit();
return true;
case R.id.navdrawer__item_bookmarks:
case R.id.navdrawer__item_blogging:
case R.id.navdrawer__item_settings:
Toast.makeText(this, R.string.feature_not_implemented, Toast.LENGTH_SHORT).show();
return true;
}
return false;
}
}

@ -17,7 +17,7 @@
*/
package de.vanitasvitae.slam.mvp.view;
import android.app.Fragment;
import android.support.v4.app.Fragment;
import java.util.List;

@ -29,17 +29,18 @@ import de.vanitasvitae.slam.R;
*/
public class ChatMessageEntry extends RecyclerView.ViewHolder {
private View view;
public ChatMessageEntry(View itemView) {
super(itemView);
this.view = itemView;
}
public void bind(String sender, String role, View content, String date) {
((TextView)view.findViewById(R.id.message_sender)).setText(sender);
((TextView)view.findViewById(R.id.message_sender_role)).setText(role);
((RelativeLayout)view.findViewById(R.id.message_content)).addView(content);
((TextView)view.findViewById(R.id.message_date)).setText(date);
((TextView)itemView.findViewById(R.id.message_sender)).setText(sender);
((TextView)itemView.findViewById(R.id.message_sender_role)).setText(role);
((RelativeLayout)itemView.findViewById(R.id.message_content)).addView(content);
((TextView)itemView.findViewById(R.id.message_date)).setText(date);
}
public void setOnAvatarClickListener(View.OnClickListener listener) {
itemView.findViewById(R.id.contact_image).setOnClickListener(listener);
}
}

@ -0,0 +1,48 @@
/*
* Copyright 2018 Paul Schaub
*
* This code is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software Foundation,
* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*/
package de.vanitasvitae.slam.ui;
import android.support.v7.widget.RecyclerView;
import android.view.View;
import android.widget.TextView;
import de.vanitasvitae.slam.R;
import de.vanitasvitae.slam.xmpp.Contact;
/**
* Created by Paul Schaub on 13.02.18.
*/
public class ContactListEntry extends RecyclerView.ViewHolder {
public ContactListEntry(View itemView) {
super(itemView);
}
public void bind(Contact contact) {
((TextView)itemView.findViewById(R.id.contact_name)).setText(contact.getNickname());
((TextView)itemView.findViewById(R.id.contact_jid)).setText(contact.getJid());
}
public void setOnAvatarClickListener(View.OnClickListener listener) {
itemView.findViewById(R.id.contact_image).setOnClickListener(listener);
}
public void setOnEntryClickListener(View.OnClickListener listener) {
itemView.setOnClickListener(listener);
}
}

@ -28,18 +28,22 @@ import de.vanitasvitae.slam.R;
*/
public class ConversationEntry extends RecyclerView.ViewHolder {
private View view;
public ConversationEntry(View itemView) {
super(itemView);
this.view = itemView;
}
public void bind(String username, String message, String date, boolean read) {
View v = view;
((TextView)v.findViewById(R.id.contact_name)).setText(username);
((TextView)v.findViewById(R.id.contact_textcontent)).setText(message);
((TextView)v.findViewById(R.id.contact_date)).setText(date);
v.findViewById(R.id.send_indicator).setVisibility(read ? View.VISIBLE : View.GONE);
((TextView)itemView.findViewById(R.id.contact_name)).setText(username);
((TextView)itemView.findViewById(R.id.contact_jid)).setText(message);
((TextView)itemView.findViewById(R.id.contact_date)).setText(date);
itemView.findViewById(R.id.send_indicator).setVisibility(read ? View.VISIBLE : View.GONE);
}
public void setOnAvatarClickListener(View.OnClickListener listener) {
itemView.findViewById(R.id.contact_image).setOnClickListener(listener);
}
public void setOnEntryClickListener(View.OnClickListener listener) {
itemView.setOnClickListener(listener);
}
}

@ -1,3 +1,20 @@
/*
* Copyright 2018 Paul Schaub
*
* This code is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software Foundation,
* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*/
package de.vanitasvitae.slam.xmpp;
import org.jxmpp.jid.BareJid;

@ -1,3 +1,20 @@
/*
* Copyright 2018 Paul Schaub
*
* This code is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software Foundation,
* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*/
package de.vanitasvitae.slam.xmpp;
/**

@ -0,0 +1,49 @@
/*
* Copyright 2018 Paul Schaub
*
* This code is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software Foundation,
* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*/
package de.vanitasvitae.slam.xmpp;
/**
* Created by Paul Schaub on 13.02.18.
*/
public class Resource {
private final String resource, status, client, system;
public Resource(String resource, String status, String client, String system) {
this.resource = resource;
this.status = status;
this.client = client;
this.system = system;
}
public String getClient() {
return client;
}
public String getResource() {
return resource;
}
public String getStatus() {
return status;
}
public String getSystem() {
return system;
}
}

Binary file not shown.

After

Width:  |  Height:  |  Size: 248 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 270 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 962 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 982 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 193 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 205 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 648 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 661 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 316 B