Module Detail Overview Implementation #2

This commit is contained in:
Caesar2011
2018-06-06 14:45:43 +02:00
parent 0f6de85bcb
commit 3b0eb28b1e
37 changed files with 457 additions and 528 deletions

Binary file not shown.

View File

@@ -34,7 +34,7 @@ dependencies {
}) })
implementation 'com.android.support:appcompat-v7:27.1.1' implementation 'com.android.support:appcompat-v7:27.1.1'
implementation 'com.android.support:design:27.1.1' implementation 'com.android.support:design:27.1.1'
implementation 'com.android.support.constraint:constraint-layout:1.1.0' implementation 'com.android.support.constraint:constraint-layout:1.1.1'
implementation 'com.android.volley:volley:1.0.0' implementation 'com.android.volley:volley:1.0.0'
//noinspection GradleDependency //noinspection GradleDependency
implementation 'com.google.android.gms:play-services-auth:15.0.0' implementation 'com.google.android.gms:play-services-auth:15.0.0'
@@ -45,5 +45,6 @@ dependencies {
implementation 'org.jbundle.util.osgi.wrapped:org.jbundle.util.osgi.wrapped.org.apache.http.client:4.1.2' implementation 'org.jbundle.util.osgi.wrapped:org.jbundle.util.osgi.wrapped.org.apache.http.client:4.1.2'
implementation 'com.android.support:support-v4:27.1.1' implementation 'com.android.support:support-v4:27.1.1'
implementation 'org.jetbrains:annotations-java5:15.0' implementation 'org.jetbrains:annotations-java5:15.0'
implementation 'com.ms-square:expandableTextView:0.1.4'
implementation files('libs/jericho-html-3.4.jar') implementation files('libs/jericho-html-3.4.jar')
} }

View File

@@ -16,8 +16,8 @@
android:name=".MainActivity" android:name=".MainActivity"
android:label="@string/app_name"> android:label="@string/app_name">
<intent-filter> <intent-filter>
<action android:name="android.intent.action.VIEW" />
<action android:name="android.intent.action.MAIN" /> <action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" /> <category android:name="android.intent.category.LAUNCHER" />
</intent-filter> </intent-filter>
</activity> </activity>

View File

@@ -22,17 +22,11 @@ import de.sebse.fuplanner.fragments.LoginFragment;
import de.sebse.fuplanner.fragments.moddetails.ModDetailFragment; import de.sebse.fuplanner.fragments.moddetails.ModDetailFragment;
import de.sebse.fuplanner.fragments.ModulesFragment; import de.sebse.fuplanner.fragments.ModulesFragment;
import de.sebse.fuplanner.fragments.StartupFragment; import de.sebse.fuplanner.fragments.StartupFragment;
import de.sebse.fuplanner.services.GoogleAuth.ConnectedListener;
import de.sebse.fuplanner.services.GoogleAuth.Credentials; import de.sebse.fuplanner.services.GoogleAuth.Credentials;
import de.sebse.fuplanner.services.GoogleAuth.CredentialsListener;
import de.sebse.fuplanner.services.GoogleAuth.GoogleAuth; import de.sebse.fuplanner.services.GoogleAuth.GoogleAuth;
import de.sebse.fuplanner.services.KVV.KVV; import de.sebse.fuplanner.services.KVV.KVV;
import de.sebse.fuplanner.services.KVV.LoginToken;
import de.sebse.fuplanner.services.KVV.Modules; import de.sebse.fuplanner.services.KVV.Modules;
import de.sebse.fuplanner.tools.logging.Logger; import de.sebse.fuplanner.tools.logging.Logger;
import de.sebse.fuplanner.tools.network.NetworkCallback;
import de.sebse.fuplanner.tools.network.NetworkError;
import de.sebse.fuplanner.tools.network.NetworkErrorCallback;
public class MainActivity extends AppCompatActivity public class MainActivity extends AppCompatActivity
implements NavigationView.OnNavigationItemSelectedListener, implements NavigationView.OnNavigationItemSelectedListener,
@@ -55,7 +49,7 @@ public class MainActivity extends AppCompatActivity
DrawerLayout drawer = findViewById(R.id.drawer_layout); DrawerLayout drawer = findViewById(R.id.drawer_layout);
ActionBarDrawerToggle toggle = new ActionBarDrawerToggle( ActionBarDrawerToggle toggle = new ActionBarDrawerToggle(
this, drawer, toolbar, R.string.navigation_drawer_open, R.string.navigation_drawer_close); this, drawer, toolbar, R.string.navigation_drawer_open, R.string.navigation_drawer_close);
drawer.setDrawerListener(toggle); drawer.addDrawerListener(toggle);
toggle.syncState(); toggle.syncState();
NavigationView navigationView = findViewById(R.id.nav_view); NavigationView navigationView = findViewById(R.id.nav_view);
@@ -75,35 +69,23 @@ public class MainActivity extends AppCompatActivity
findViewById(R.id.app_bar_layout).setVisibility(View.GONE); findViewById(R.id.app_bar_layout).setVisibility(View.GONE);
this.getGoogleAuth().connect(new ConnectedListener() { this.getGoogleAuth().connect(() -> {
@Override
public void connected() {
// getGoogleAuth().setLoginState("***REMOVED***", "***REMOVED***"); // getGoogleAuth().setLoginState("***REMOVED***", "***REMOVED***");
getGoogleAuth().getLoginState(new CredentialsListener() { getGoogleAuth().getLoginState(credentials -> {
@Override
public void onCredentials(final Credentials credentials) {
if (credentials == null || credentials.getUsername() == null || credentials.getPassword() == null) { if (credentials == null || credentials.getUsername() == null || credentials.getPassword() == null) {
MainActivity.this.getKVV().endUpdate(); MainActivity.this.getKVV().endUpdate();
changeLoginState(null); changeLoginState(null);
return; return;
} }
MainActivity.this.getKVV().login(credentials.getUsername(), credentials.getPassword(), new NetworkCallback<LoginToken>() { MainActivity.this.getKVV().login(credentials.getUsername(), credentials.getPassword(), success -> {
@Override
public void onResponse(@NonNull LoginToken success) {
MainActivity.this.getKVV().endUpdate(); MainActivity.this.getKVV().endUpdate();
changeLoginState(credentials); changeLoginState(credentials);
} }, error -> {
}, new NetworkErrorCallback() {
@Override
public void onError(NetworkError error) {
log.e(error); log.e(error);
MainActivity.this.getKVV().endUpdate(); MainActivity.this.getKVV().endUpdate();
changeLoginState(null); changeLoginState(null);
}
}); });
}
}); });
}
}); });
} }
@@ -159,14 +141,11 @@ public class MainActivity extends AppCompatActivity
break; break;
case R.id.nav_logout: case R.id.nav_logout:
this.getKVV().logout(); this.getKVV().logout();
this.getGoogleAuth().getLoginState(new CredentialsListener() { this.getGoogleAuth().getLoginState(credentials -> {
@Override
public void onCredentials(Credentials credentials) {
if (credentials != null) { if (credentials != null) {
MainActivity.this.getGoogleAuth().deleteLoginState(credentials.getUsername(), credentials.getPassword()); MainActivity.this.getGoogleAuth().deleteLoginState(credentials.getUsername(), credentials.getPassword());
} }
MainActivity.this.changeLoginState(null); MainActivity.this.changeLoginState(null);
}
}); });
break; break;
} }
@@ -236,9 +215,7 @@ public class MainActivity extends AppCompatActivity
navigationView.getMenu().clear(); navigationView.getMenu().clear();
navigationView.inflateMenu(R.menu.activity_main_drawer_login); navigationView.inflateMenu(R.menu.activity_main_drawer_login);
navigationView.setCheckedItem(R.id.nav_modules); navigationView.setCheckedItem(R.id.nav_modules);
getKVV().getModuleList(new NetworkCallback<Modules>() { getKVV().getModuleList(success -> {
@Override
public void onResponse(@NonNull Modules success) {
log.d("Modules.get", success.size()); log.d("Modules.get", success.size());
//SubMenu moduleMenu = navigationView.getMenu().findItem(R.id.nav_modules).getSubMenu(); //SubMenu moduleMenu = navigationView.getMenu().findItem(R.id.nav_modules).getSubMenu();
int i = 0; int i = 0;
@@ -252,13 +229,7 @@ public class MainActivity extends AppCompatActivity
}); });
i++; i++;
} }
} }, error -> log.d("Modules.error", error));
}, new NetworkErrorCallback() {
@Override
public void onError(NetworkError error) {
log.d("Modules.error", error);
}
});
} }
} }
@@ -280,16 +251,8 @@ public class MainActivity extends AppCompatActivity
@Override @Override
public void onModulesFragmentInteraction(final int itemPosition) { public void onModulesFragmentInteraction(final int itemPosition) {
log.d("Item clicked", itemPosition); log.d("Item clicked", itemPosition);
getKVV().getModuleList(new NetworkCallback<Modules>() { getKVV().getModuleList(success -> log.d(success.get(itemPosition).title), error -> {
@Override
public void onResponse(@NonNull Modules success) {
log.d(success.get(itemPosition).title);
}
}, new NetworkErrorCallback() {
@Override
public void onError(NetworkError error) {
// TODO // TODO
}
}); });
FragmentTransaction fragmentTransaction = fragmentManager.beginTransaction(); FragmentTransaction fragmentTransaction = fragmentManager.beginTransaction();

View File

@@ -5,7 +5,6 @@ import android.content.Context;
import android.os.Bundle; import android.os.Bundle;
import android.support.annotation.NonNull; import android.support.annotation.NonNull;
import android.support.v4.app.Fragment; import android.support.v4.app.Fragment;
import android.util.Log;
import android.view.LayoutInflater; import android.view.LayoutInflater;
import android.view.View; import android.view.View;
import android.view.ViewGroup; import android.view.ViewGroup;
@@ -16,11 +15,7 @@ import de.sebse.fuplanner.R;
import de.sebse.fuplanner.services.GoogleAuth.Credentials; import de.sebse.fuplanner.services.GoogleAuth.Credentials;
import de.sebse.fuplanner.services.GoogleAuth.GoogleAuth; import de.sebse.fuplanner.services.GoogleAuth.GoogleAuth;
import de.sebse.fuplanner.services.KVV.KVV; import de.sebse.fuplanner.services.KVV.KVV;
import de.sebse.fuplanner.services.KVV.LoginToken;
import de.sebse.fuplanner.tools.logging.Logger; import de.sebse.fuplanner.tools.logging.Logger;
import de.sebse.fuplanner.tools.network.NetworkCallback;
import de.sebse.fuplanner.tools.network.NetworkError;
import de.sebse.fuplanner.tools.network.NetworkErrorCallback;
/** /**
* A simple {@link Fragment} subclass. * A simple {@link Fragment} subclass.
@@ -63,16 +58,14 @@ public class LoginFragment extends Fragment {
} }
@Override @Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, public View onCreateView(@NonNull LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) { Bundle savedInstanceState) {
// Inflate the layout for this fragment // Inflate the layout for this fragment
View v = inflater.inflate(R.layout.fragment_login, container, false); View v = inflater.inflate(R.layout.fragment_login, container, false);
View btn_login = v.findViewById(R.id.btn_login); View btn_login = v.findViewById(R.id.btn_login);
if (btn_login != null) { if (btn_login != null) {
btn_login.setOnClickListener(new View.OnClickListener() { btn_login.setOnClickListener(view -> {
@Override
public void onClick(View view) {
final ProgressDialog progressDialog = new ProgressDialog(LoginFragment.this.getContext(), final ProgressDialog progressDialog = new ProgressDialog(LoginFragment.this.getContext(),
R.style.FUTheme_Dialog); R.style.FUTheme_Dialog);
progressDialog.setIndeterminate(true); progressDialog.setIndeterminate(true);
@@ -92,9 +85,7 @@ public class LoginFragment extends Fragment {
final String password = input_pwd.getText().toString(); final String password = input_pwd.getText().toString();
final KVV kvv = ((MainActivity) LoginFragment.this.getActivity()).getKVV(); final KVV kvv = ((MainActivity) LoginFragment.this.getActivity()).getKVV();
final GoogleAuth gauth = ((MainActivity) LoginFragment.this.getActivity()).getGoogleAuth(); final GoogleAuth gauth = ((MainActivity) LoginFragment.this.getActivity()).getGoogleAuth();
kvv.login(username, password, new NetworkCallback<LoginToken>() { kvv.login(username, password, success -> {
@Override
public void onResponse(@NonNull LoginToken success) {
progressDialog.dismiss(); progressDialog.dismiss();
log.d("success", success.toString()); log.d("success", success.toString());
gauth.setLoginState(username, password); gauth.setLoginState(username, password);
@@ -102,17 +93,12 @@ public class LoginFragment extends Fragment {
Credentials cred = new Credentials(username, password); Credentials cred = new Credentials(username, password);
LoginFragment.this.mListener.onLoginFragmentInteraction(cred); LoginFragment.this.mListener.onLoginFragmentInteraction(cred);
} }
} }, error -> {
}, new NetworkErrorCallback() {
@Override
public void onError(NetworkError error) {
progressDialog.dismiss(); progressDialog.dismiss();
log.e("error", error); log.e("error", error);
}
}); });
} }
} }
}
}); });
} }

View File

@@ -13,11 +13,7 @@ import android.view.ViewGroup;
import de.sebse.fuplanner.MainActivity; import de.sebse.fuplanner.MainActivity;
import de.sebse.fuplanner.R; import de.sebse.fuplanner.R;
import de.sebse.fuplanner.services.KVV.Modules;
import de.sebse.fuplanner.tools.logging.Logger; import de.sebse.fuplanner.tools.logging.Logger;
import de.sebse.fuplanner.tools.network.NetworkCallback;
import de.sebse.fuplanner.tools.network.NetworkError;
import de.sebse.fuplanner.tools.network.NetworkErrorCallback;
/** /**
* A fragment representing a list of Items. * A fragment representing a list of Items.
@@ -75,18 +71,10 @@ public class ModulesFragment extends Fragment {
if (getActivity() != null) { if (getActivity() != null) {
((MainActivity) getActivity()).getKVV().getModuleList(new NetworkCallback<Modules>() { ((MainActivity) getActivity()).getKVV().getModuleList(success -> {
@Override
public void onResponse(@NonNull Modules success) {
log.d(success); log.d(success);
adapter.setModules(success); adapter.setModules(success);
} }, error -> Log.e("ModFrag", error.toString()));
}, new NetworkErrorCallback() {
@Override
public void onError(NetworkError error) {
Log.e("ModFrag", error.toString());
}
});
} }
} }
return view; return view;

View File

@@ -1,5 +1,6 @@
package de.sebse.fuplanner.fragments; package de.sebse.fuplanner.fragments;
import android.support.annotation.NonNull;
import android.support.v7.widget.RecyclerView; import android.support.v7.widget.RecyclerView;
import android.util.Log; import android.util.Log;
import android.view.LayoutInflater; import android.view.LayoutInflater;
@@ -31,30 +32,29 @@ public class ModulesRecyclerViewAdapter extends RecyclerView.Adapter<ModulesRecy
this.notifyDataSetChanged(); this.notifyDataSetChanged();
} }
@NonNull
@Override @Override
public ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) { public ViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) {
View view = LayoutInflater.from(parent.getContext()) View view = LayoutInflater.from(parent.getContext())
.inflate(R.layout.fragment_modules, parent, false); .inflate(R.layout.fragment_modules, parent, false);
return new ViewHolder(view); return new ViewHolder(view);
} }
@Override @Override
public void onBindViewHolder(final ViewHolder holder, int position) { public void onBindViewHolder(@NonNull final ViewHolder holder, int position) {
if (mValues == null) if (mValues == null)
return; return;
position = holder.getAdapterPosition();
holder.mItemPosition = position; holder.mItemPosition = position;
holder.mIdView.setText(mValues.get(position).semester); holder.mIdView.setText(mValues.get(position).semester);
holder.mContentView.setText(mValues.get(position).title); holder.mContentView.setText(mValues.get(position).title);
holder.mView.setOnClickListener(new View.OnClickListener() { holder.mView.setOnClickListener(v -> {
@Override
public void onClick(View v) {
if (null != mListener) { if (null != mListener) {
// Notify the active callbacks interface (the activity, if the // Notify the active callbacks interface (the activity, if the
// fragment is attached to one) that an item has been selected. // fragment is attached to one) that an item has been selected.
mListener.onModulesFragmentInteraction(holder.mItemPosition); mListener.onModulesFragmentInteraction(holder.mItemPosition);
} }
}
}); });
} }
@@ -77,8 +77,8 @@ public class ModulesRecyclerViewAdapter extends RecyclerView.Adapter<ModulesRecy
public ViewHolder(View view) { public ViewHolder(View view) {
super(view); super(view);
mView = view; mView = view;
mIdView = (TextView) view.findViewById(R.id.id); mIdView = view.findViewById(R.id.id);
mContentView = (TextView) view.findViewById(R.id.content); mContentView = view.findViewById(R.id.content);
} }
@Override @Override

View File

@@ -1,7 +1,5 @@
package de.sebse.fuplanner.fragments; package de.sebse.fuplanner.fragments;
import android.content.Context;
import android.net.Uri;
import android.os.Bundle; import android.os.Bundle;
import android.support.annotation.NonNull; import android.support.annotation.NonNull;
import android.support.v4.app.Fragment; import android.support.v4.app.Fragment;
@@ -13,9 +11,6 @@ import de.sebse.fuplanner.R;
/** /**
* A simple {@link Fragment} subclass. * A simple {@link Fragment} subclass.
* Activities that contain this fragment must implement the
* {@link StartupFragment.OnStartupFragmentInteractionListener} interface
* to handle interaction events.
* Use the {@link StartupFragment#newInstance} factory method to * Use the {@link StartupFragment#newInstance} factory method to
* create an instance of this fragment. * create an instance of this fragment.
*/ */

View File

@@ -1,7 +1,6 @@
package de.sebse.fuplanner.fragments.moddetails; package de.sebse.fuplanner.fragments.moddetails;
import android.content.Context; import android.content.Context;
import android.content.res.Resources;
import android.support.v4.app.Fragment; import android.support.v4.app.Fragment;
import android.support.v4.app.FragmentManager; import android.support.v4.app.FragmentManager;
import android.support.v4.app.FragmentStatePagerAdapter; import android.support.v4.app.FragmentStatePagerAdapter;

View File

@@ -2,6 +2,7 @@ package de.sebse.fuplanner.fragments.moddetails;
import android.os.Bundle; import android.os.Bundle;
import android.support.annotation.NonNull;
import android.support.v4.app.Fragment; import android.support.v4.app.Fragment;
import android.view.LayoutInflater; import android.view.LayoutInflater;
import android.view.View; import android.view.View;
@@ -54,7 +55,7 @@ public class ModDetailAnnounceFragment extends Fragment {
} }
@Override @Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, public View onCreateView(@NonNull LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) { Bundle savedInstanceState) {
// Inflate the layout for this fragment // Inflate the layout for this fragment
return inflater.inflate(R.layout.fragment_mod_detail_announce, container, false); return inflater.inflate(R.layout.fragment_mod_detail_announce, container, false);

View File

@@ -31,7 +31,6 @@ public class ModDetailFragment extends Fragment {
private int mItemPos; private int mItemPos;
private OnModuleDetailFragmentInteractionListener mListener; private OnModuleDetailFragmentInteractionListener mListener;
private ModDetailAdapter adapterViewPager;
private Logger log = new Logger(this); private Logger log = new Logger(this);
public ModDetailFragment() { public ModDetailFragment() {
@@ -71,8 +70,8 @@ public class ModDetailFragment extends Fragment {
log.d("on create view"); log.d("on create view");
View v = inflater.inflate(R.layout.fragment_mod_detail, container, false); View v = inflater.inflate(R.layout.fragment_mod_detail, container, false);
ViewPager vpPager = (ViewPager) v.findViewById(R.id.vpPager); ViewPager vpPager = v.findViewById(R.id.vpPager);
adapterViewPager = new ModDetailAdapter(getFragmentManager(), mItemPos, getContext()); ModDetailAdapter adapterViewPager = new ModDetailAdapter(getFragmentManager(), mItemPos, getContext());
vpPager.setAdapter(adapterViewPager); vpPager.setAdapter(adapterViewPager);
return v; return v;
} }

View File

@@ -1,26 +1,27 @@
package de.sebse.fuplanner.fragments.moddetails; package de.sebse.fuplanner.fragments.moddetails;
import android.icu.text.DateFormat;
import android.support.annotation.NonNull; import android.support.annotation.NonNull;
import android.support.v7.widget.RecyclerView; import android.support.v7.widget.RecyclerView;
import android.util.Log;
import android.view.LayoutInflater; import android.view.LayoutInflater;
import android.view.View; import android.view.View;
import android.view.ViewGroup; import android.view.ViewGroup;
import android.widget.TextView; import android.widget.TextView;
import java.util.Date; import com.ms.square.android.expandabletextview.ExpandableTextView;
import java.util.Locale;
import de.sebse.fuplanner.R; import de.sebse.fuplanner.R;
import de.sebse.fuplanner.fragments.ModulesFragment;
import de.sebse.fuplanner.fragments.ModulesRecyclerViewAdapter;
import de.sebse.fuplanner.services.KVV.Announcement; import de.sebse.fuplanner.services.KVV.Announcement;
import de.sebse.fuplanner.services.KVV.Assignment;
import de.sebse.fuplanner.services.KVV.Modules; import de.sebse.fuplanner.services.KVV.Modules;
import de.sebse.fuplanner.tools.Conversion; import de.sebse.fuplanner.tools.Conversion;
import de.sebse.fuplanner.tools.ui.CustomViewHolder; import de.sebse.fuplanner.tools.ui.CustomViewHolder;
public class ModDetailOverviewAdapter extends RecyclerView.Adapter<RecyclerView.ViewHolder> { public class ModDetailOverviewAdapter extends RecyclerView.Adapter<RecyclerView.ViewHolder> {
private static final int TYPE_HEADER = 0;
private static final int TYPE_DESCRIPTION = 1;
private static final int TYPE_ITEM = 2;
private static final int TYPE_SHOW_MORE = 3;
private Modules.Module mValue; private Modules.Module mValue;
//private final ModulesFragment.OnModulesFragmentInteractionListener mListener; //private final ModulesFragment.OnModulesFragmentInteractionListener mListener;
@@ -39,18 +40,22 @@ public class ModDetailOverviewAdapter extends RecyclerView.Adapter<RecyclerView.
public RecyclerView.ViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) { public RecyclerView.ViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) {
View view; View view;
switch (viewType) { switch (viewType) {
case 0: case TYPE_HEADER:
view = LayoutInflater.from(parent.getContext()) view = LayoutInflater.from(parent.getContext())
.inflate(R.layout.list_all_caption, parent, false); .inflate(R.layout.list_all_caption, parent, false);
return new HeaderViewHolder(view); return new HeaderViewHolder(view);
case 1: case TYPE_DESCRIPTION:
view = LayoutInflater.from(parent.getContext()) view = LayoutInflater.from(parent.getContext())
.inflate(R.layout.list_moddetails_description, parent, false); .inflate(R.layout.list_moddetails_description, parent, false);
return new DescriptionViewHolder(view); return new DescriptionViewHolder(view);
case 2: case TYPE_ITEM:
view = LayoutInflater.from(parent.getContext()) view = LayoutInflater.from(parent.getContext())
.inflate(R.layout.list_moddetails_announcements, parent, false); .inflate(R.layout.list_moddetails_announcements, parent, false);
return new AnnounceViewHolder(view); return new ItemViewHolder(view);
case TYPE_SHOW_MORE:
view = LayoutInflater.from(parent.getContext())
.inflate(R.layout.list_all_show_more, parent, false);
return new CustomViewHolder(view);
default: default:
//noinspection ConstantConditions //noinspection ConstantConditions
return null; return null;
@@ -62,39 +67,61 @@ public class ModDetailOverviewAdapter extends RecyclerView.Adapter<RecyclerView.
// Just as an example, return 0 or 2 depending on position // Just as an example, return 0 or 2 depending on position
// Note that unlike in ListView adapters, types don't have to be contiguous // Note that unlike in ListView adapters, types don't have to be contiguous
if (position < 3) if (position < 3)
return position % 2; return position % 2; // HEADER, DESCRIPTION, HEADER
else int count = 2;
return 2;
// Announcements
if (position <= count+getAnnounceCount(2))
return TYPE_ITEM;
count += getAnnounceCount(3);
if (position <= count)
return TYPE_SHOW_MORE;
// Assignments
count++;
if (position <= count)
return TYPE_HEADER;
count++;
if (position <= count+getAssignmentCount(2))
return TYPE_ITEM;
count += getAssignmentCount(3);
if (position <= count)
return TYPE_SHOW_MORE;
return 0;
} }
@Override @Override
public void onBindViewHolder(@NonNull final RecyclerView.ViewHolder holder, int position) { public void onBindViewHolder(@NonNull final RecyclerView.ViewHolder holder, int position) {
if (mValue == null) if (mValue == null)
return; return;
int announce_count = getAnnounceCount(2);
if (position == 0) { if (position == 0) {
HeaderViewHolder h = (HeaderViewHolder) holder; HeaderViewHolder h = (HeaderViewHolder) holder;
h.mCaption.setText(h.mView.getResources().getText(R.string.description)); h.mCaption.setText(R.string.description);
} else if (position == 1) { } else if (position == 1) {
DescriptionViewHolder d = (DescriptionViewHolder) holder; DescriptionViewHolder d = (DescriptionViewHolder) holder;
d.mText.setText(mValue.description); d.mText.setText(mValue.description);
//d.mText.setText(d.mView.getResources().getText(R.string.app_name));
} else if (position == 2) { } else if (position == 2) {
HeaderViewHolder h = (HeaderViewHolder) holder; HeaderViewHolder h = (HeaderViewHolder) holder;
h.mCaption.setText(h.mView.getResources().getString(R.string.announcements_count, getAnnounceCount())); h.mCaption.setText(h.mView.getResources().getString(R.string.announcements_count, getAnnounceCount()));
} else if (position <= announce_count+2) { } else if (position <= getAnnounceCount(2)+2) {
AnnounceViewHolder a = (AnnounceViewHolder) holder; ItemViewHolder a = (ItemViewHolder) holder;
Announcement announce = mValue.announcements.get(position - 3); Announcement announce = mValue.announcements.get(position - 3);
a.mTitle.setText(announce.getTitle()); a.mTitle.setText(announce.getTitle());
a.mPublisher.setText(announce.getCreatedBy()); a.mSubLeft.setText(announce.getCreatedBy());
a.mDate.setText(Conversion.getModifiedDate(announce.getCreatedOn())); a.mSubRight.setText(Conversion.getModifiedDate(announce.getCreatedOn()));
} else if (position <= getAnnounceCount(3)+getAssignmentCount(2)+3) {
ItemViewHolder a = (ItemViewHolder) holder;
Assignment assignment = mValue.assignments.get(position - 3);
a.mTitle.setText(assignment.getTitle());
a.mSubLeft.setText(assignment.getStatus());
a.mSubRight.setText(Conversion.getModifiedDate(assignment.getDueDate()));
} }
} }
@Override @Override
public int getItemCount() { public int getItemCount() {
if (mValue != null) { if (mValue != null) {
return 3+getAnnounceCount(); return 4+getAnnounceCount(3)+getAssignmentCount(3);
} }
return 0; return 0;
} }
@@ -109,6 +136,16 @@ public class ModDetailOverviewAdapter extends RecyclerView.Adapter<RecyclerView.
return Math.min(max, getAnnounceCount()); return Math.min(max, getAnnounceCount());
} }
private int getAssignmentCount() {
if (mValue.assignments != null)
return mValue.assignments.size();
return 0;
}
private int getAssignmentCount(int max) {
return Math.min(max, getAssignmentCount());
}
@@ -131,11 +168,11 @@ public class ModDetailOverviewAdapter extends RecyclerView.Adapter<RecyclerView.
} }
public class DescriptionViewHolder extends CustomViewHolder { public class DescriptionViewHolder extends CustomViewHolder {
final TextView mText; final ExpandableTextView mText;
DescriptionViewHolder(View view) { DescriptionViewHolder(View view) {
super(view); super(view);
mText = view.findViewById(R.id.description); mText = view.findViewById(R.id.expand_text_view);//.findViewById(R.id.description);
} }
@Override @Override
@@ -145,21 +182,21 @@ public class ModDetailOverviewAdapter extends RecyclerView.Adapter<RecyclerView.
} }
public class AnnounceViewHolder extends CustomViewHolder { public class ItemViewHolder extends CustomViewHolder {
final TextView mTitle; final TextView mTitle;
final TextView mPublisher; final TextView mSubLeft;
final TextView mDate; final TextView mSubRight;
AnnounceViewHolder(View view) { ItemViewHolder(View view) {
super(view); super(view);
mTitle = view.findViewById(R.id.title); mTitle = view.findViewById(R.id.title);
mPublisher = view.findViewById(R.id.publisher); mSubLeft = view.findViewById(R.id.sub_left);
mDate = view.findViewById(R.id.date); mSubRight = view.findViewById(R.id.sub_right);
} }
@Override @Override
public String toString() { public String toString() {
return super.toString() + " '" + mTitle.getText() + "' '" + mPublisher.getText() + "' '" + mDate.getText() + "'"; return super.toString() + " '" + mTitle.getText() + "' '" + mSubLeft.getText() + "' '" + mSubRight.getText() + "'";
} }
} }
} }

View File

@@ -7,20 +7,15 @@ import android.support.annotation.NonNull;
import android.support.v4.app.Fragment; import android.support.v4.app.Fragment;
import android.support.v7.widget.LinearLayoutManager; import android.support.v7.widget.LinearLayoutManager;
import android.support.v7.widget.RecyclerView; import android.support.v7.widget.RecyclerView;
import android.util.Log;
import android.view.LayoutInflater; import android.view.LayoutInflater;
import android.view.View; import android.view.View;
import android.view.ViewGroup; import android.view.ViewGroup;
import de.sebse.fuplanner.MainActivity; import de.sebse.fuplanner.MainActivity;
import de.sebse.fuplanner.R; import de.sebse.fuplanner.R;
import de.sebse.fuplanner.fragments.ModulesRecyclerViewAdapter;
import de.sebse.fuplanner.services.KVV.KVV; import de.sebse.fuplanner.services.KVV.KVV;
import de.sebse.fuplanner.services.KVV.Modules; import de.sebse.fuplanner.services.KVV.Modules;
import de.sebse.fuplanner.tools.logging.Logger; import de.sebse.fuplanner.tools.logging.Logger;
import de.sebse.fuplanner.tools.network.NetworkCallback;
import de.sebse.fuplanner.tools.network.NetworkError;
import de.sebse.fuplanner.tools.network.NetworkErrorCallback;
/** /**
* A simple {@link Fragment} subclass. * A simple {@link Fragment} subclass.
@@ -31,6 +26,7 @@ public class ModDetailOverviewFragment extends Fragment {
// TODO: Rename parameter arguments, choose names that match // TODO: Rename parameter arguments, choose names that match
// the fragment initialization parameters, e.g. ARG_ITEM_NUMBER // the fragment initialization parameters, e.g. ARG_ITEM_NUMBER
private static final String ARG_POSITION = "itemPosition"; private static final String ARG_POSITION = "itemPosition";
private static Logger slog = new Logger(ModDetailOverviewFragment.class);
// TODO: Rename and change types of parameters // TODO: Rename and change types of parameters
private int mItemPos; private int mItemPos;
@@ -54,8 +50,7 @@ public class ModDetailOverviewFragment extends Fragment {
Bundle args = new Bundle(); Bundle args = new Bundle();
args.putInt(ARG_POSITION, itemPosition); args.putInt(ARG_POSITION, itemPosition);
fragment.setArguments(args); fragment.setArguments(args);
String s = "ModDetailOverviewFragment".toString(); slog.d("new Instance");
Log.d(s, "new Instance");
return fragment; return fragment;
} }

View File

@@ -5,5 +5,5 @@ package de.sebse.fuplanner.services.GoogleAuth;
*/ */
public interface ConnectedListener { public interface ConnectedListener {
public void connected(); void connected();
} }

View File

@@ -5,5 +5,5 @@ package de.sebse.fuplanner.services.GoogleAuth;
*/ */
public interface CredentialsListener { public interface CredentialsListener {
public void onCredentials(Credentials credentials); void onCredentials(Credentials credentials);
} }

View File

@@ -2,7 +2,6 @@ package de.sebse.fuplanner.services.GoogleAuth;
import android.content.Intent; import android.content.Intent;
import android.content.IntentSender; import android.content.IntentSender;
import android.support.annotation.NonNull;
import android.support.annotation.Nullable; import android.support.annotation.Nullable;
import android.support.v4.app.FragmentActivity; import android.support.v4.app.FragmentActivity;
import android.util.Log; import android.util.Log;
@@ -10,7 +9,6 @@ import android.widget.Toast;
import com.google.android.gms.auth.api.credentials.Credential; import com.google.android.gms.auth.api.credentials.Credential;
import com.google.android.gms.auth.api.credentials.CredentialRequest; import com.google.android.gms.auth.api.credentials.CredentialRequest;
import com.google.android.gms.auth.api.credentials.CredentialRequestResponse;
import com.google.android.gms.auth.api.credentials.CredentialsClient; import com.google.android.gms.auth.api.credentials.CredentialsClient;
import com.google.android.gms.auth.api.credentials.CredentialsOptions; import com.google.android.gms.auth.api.credentials.CredentialsOptions;
import com.google.android.gms.common.ConnectionResult; import com.google.android.gms.common.ConnectionResult;
@@ -18,8 +16,6 @@ import com.google.android.gms.common.GoogleApiAvailability;
import com.google.android.gms.common.api.ApiException; import com.google.android.gms.common.api.ApiException;
import com.google.android.gms.common.api.CommonStatusCodes; import com.google.android.gms.common.api.CommonStatusCodes;
import com.google.android.gms.common.api.ResolvableApiException; import com.google.android.gms.common.api.ResolvableApiException;
import com.google.android.gms.tasks.OnCompleteListener;
import com.google.android.gms.tasks.Task;
import static android.app.Activity.RESULT_OK; import static android.app.Activity.RESULT_OK;
@@ -65,9 +61,7 @@ public class GoogleAuth {
.build(); .build();
mCredentialsClient.request(request).addOnCompleteListener(new OnCompleteListener<CredentialRequestResponse>() { mCredentialsClient.request(request).addOnCompleteListener(task -> {
@Override
public void onComplete(@NonNull Task<CredentialRequestResponse> task) {
if (task.isSuccessful()) { if (task.isSuccessful()) {
// Successfully read the credential without any user interaction, this // Successfully read the credential without any user interaction, this
// means there was only a single credential and the user has auto // means there was only a single credential and the user has auto
@@ -98,7 +92,6 @@ public class GoogleAuth {
Log.w(TAG, "Unexpected status code: " + ae.getStatusCode()); Log.w(TAG, "Unexpected status code: " + ae.getStatusCode());
} }
} }
}
}); });
} }
@@ -111,9 +104,7 @@ public class GoogleAuth {
Credential credential = new Credential.Builder(username) Credential credential = new Credential.Builder(username)
.setPassword(password) .setPassword(password)
.build(); .build();
mCredentialsClient.save(credential).addOnCompleteListener(new OnCompleteListener<Void>() { mCredentialsClient.save(credential).addOnCompleteListener(task -> {
@Override
public void onComplete(@NonNull Task<Void> task) {
if (task.isSuccessful()) { if (task.isSuccessful()) {
showToast("Credential saved."); showToast("Credential saved.");
return; return;
@@ -130,7 +121,6 @@ public class GoogleAuth {
Log.w(TAG, "Save failed.", e); Log.w(TAG, "Save failed.", e);
showToast("Credential Save Failed"); showToast("Credential Save Failed");
} }
}
}); });
} }
@@ -142,13 +132,10 @@ public class GoogleAuth {
Credential credential = new Credential.Builder(username) Credential credential = new Credential.Builder(username)
.setPassword(password) .setPassword(password)
.build(); .build();
mCredentialsClient.delete(credential).addOnCompleteListener(new OnCompleteListener<Void>() { mCredentialsClient.delete(credential).addOnCompleteListener(task -> {
@Override
public void onComplete(@NonNull Task<Void> task) {
if (task.isSuccessful()) { if (task.isSuccessful()) {
// Credential was deleted successfully // Credential was deleted successfully
} }
}
}); });
} }

View File

@@ -1,12 +1,8 @@
package de.sebse.fuplanner.services.KVV; package de.sebse.fuplanner.services.KVV;
import android.content.Context; import android.content.Context;
import android.support.annotation.NonNull;
import android.util.Log; import android.util.Log;
import com.android.volley.Response;
import com.android.volley.VolleyError;
import java.util.HashMap; import java.util.HashMap;
import java.util.regex.Matcher; import java.util.regex.Matcher;
import java.util.regex.Pattern; import java.util.regex.Pattern;
@@ -15,7 +11,6 @@ import de.sebse.fuplanner.tools.network.HTTPService;
import de.sebse.fuplanner.tools.network.NetworkCallback; import de.sebse.fuplanner.tools.network.NetworkCallback;
import de.sebse.fuplanner.tools.network.NetworkError; import de.sebse.fuplanner.tools.network.NetworkError;
import de.sebse.fuplanner.tools.network.NetworkErrorCallback; import de.sebse.fuplanner.tools.network.NetworkErrorCallback;
import de.sebse.fuplanner.tools.network.Result;
/** /**
* Created by sebastian on 24.10.17. * Created by sebastian on 24.10.17.
@@ -53,9 +48,7 @@ class KVVLogin extends HTTPService {
-> JSESSIONID 5c10406f-588c-4c16-96e9-c80d115417de.tomcat1 -> JSESSIONID 5c10406f-588c-4c16-96e9-c80d115417de.tomcat1
*/ */
private void startKVVSession(final NetworkCallback<HashMap<String, String>> callback, final NetworkErrorCallback errorCallback) { private void startKVVSession(final NetworkCallback<HashMap<String, String>> callback, final NetworkErrorCallback errorCallback) {
get("https://kvv.imp.fu-berlin.de/portal/login", null, new Response.Listener<Result>() { get("https://kvv.imp.fu-berlin.de/portal/login", null, response -> {
@Override
public void onResponse(Result response) {
String cookies = response.getHeaders().get("Set-Cookie"); String cookies = response.getHeaders().get("Set-Cookie");
if (cookies==null) { if (cookies==null) {
errorCallback.onError(new NetworkError(100101, -1, "Error on starting KVV session!")); errorCallback.onError(new NetworkError(100101, -1, "Error on starting KVV session!"));
@@ -69,13 +62,7 @@ class KVVLogin extends HTTPService {
return; return;
} }
callback.onResponse(object); callback.onResponse(object);
} }, error -> errorCallback.onError(new NetworkError(100100, error.networkResponse.statusCode, "Error on starting KVV session!")));
}, new Response.ErrorListener() {
@Override
public void onErrorResponse(VolleyError error) {
errorCallback.onError(new NetworkError(100100, error.networkResponse.statusCode, "Error on starting KVV session!"));
}
});
} }
/* /*
@@ -88,9 +75,7 @@ class KVVLogin extends HTTPService {
private void getSAMLRequest(String JSESSIONID, final NetworkCallback<HashMap<String, String>> callback, final NetworkErrorCallback errorCallback) { private void getSAMLRequest(String JSESSIONID, final NetworkCallback<HashMap<String, String>> callback, final NetworkErrorCallback errorCallback) {
HashMap<String, String> cookies = new HashMap<>(); HashMap<String, String> cookies = new HashMap<>();
cookies.put("JSESSIONID", JSESSIONID); cookies.put("JSESSIONID", JSESSIONID);
get("https://kvv.imp.fu-berlin.de/sakai-login-tool/container", cookies, new Response.Listener<Result>() { get("https://kvv.imp.fu-berlin.de/sakai-login-tool/container", cookies, response -> {
@Override
public void onResponse(Result response) {
String location = response.getHeaders().get("Location"); String location = response.getHeaders().get("Location");
if (location==null) { if (location==null) {
errorCallback.onError(new NetworkError(100111, -1, "Error on getting SAML request!")); errorCallback.onError(new NetworkError(100111, -1, "Error on getting SAML request!"));
@@ -99,13 +84,7 @@ class KVVLogin extends HTTPService {
HashMap<String, String> object = new HashMap<>(); HashMap<String, String> object = new HashMap<>();
object.put("Location", location); object.put("Location", location);
callback.onResponse(object); callback.onResponse(object);
} }, error -> errorCallback.onError(new NetworkError(100110, error.networkResponse.statusCode, "Error on getting SAML request!")));
}, new Response.ErrorListener() {
@Override
public void onErrorResponse(VolleyError error) {
errorCallback.onError(new NetworkError(100110, error.networkResponse.statusCode, "Error on getting SAML request!"));
}
});
} }
/* /*
@@ -117,9 +96,7 @@ class KVVLogin extends HTTPService {
-> ROUTEID .1 -> ROUTEID .1
*/ */
private void startIdentSession(String url, final NetworkCallback<HashMap<String, String>> callback, final NetworkErrorCallback errorCallback) { private void startIdentSession(String url, final NetworkCallback<HashMap<String, String>> callback, final NetworkErrorCallback errorCallback) {
get(url, null, new Response.Listener<Result>() { get(url, null, response -> {
@Override
public void onResponse(Result response) {
String cookies = response.getHeaders().get("Set-Cookie"); String cookies = response.getHeaders().get("Set-Cookie");
if (cookies==null) { if (cookies==null) {
errorCallback.onError(new NetworkError(100121, -1, "Error on starting Ident session!")); errorCallback.onError(new NetworkError(100121, -1, "Error on starting Ident session!"));
@@ -133,13 +110,7 @@ class KVVLogin extends HTTPService {
return; return;
} }
callback.onResponse(object); callback.onResponse(object);
} }, error -> errorCallback.onError(new NetworkError(100120, error.networkResponse.statusCode, "Error on starting Ident session!")));
}, new Response.ErrorListener() {
@Override
public void onErrorResponse(VolleyError error) {
errorCallback.onError(new NetworkError(100120, error.networkResponse.statusCode, "Error on starting Ident session!"));
}
});
} }
/* /*
@@ -160,34 +131,26 @@ class KVVLogin extends HTTPService {
HashMap<String, String> body = new HashMap<>(); HashMap<String, String> body = new HashMap<>();
body.put("j_username", username); body.put("j_username", username);
body.put("j_password", password); body.put("j_password", password);
post("https://identity.fu-berlin.de/idp-fub/Authn/UserPassword", cookies, body, new Response.Listener<Result>() { post("https://identity.fu-berlin.de/idp-fub/Authn/UserPassword", cookies, body, response -> {
@Override
public void onResponse(Result response) {
if (first) { if (first) {
callback.onResponse(new HashMap<String, String>()); callback.onResponse(new HashMap<>());
return; return;
} }
String cookies = response.getHeaders().get("Set-Cookie"); String cookies1 = response.getHeaders().get("Set-Cookie");
if (cookies==null) { if (cookies1 ==null) {
errorCallback.onError(new NetworkError(100131, -1, "Error on logging in to Identity Server!")); errorCallback.onError(new NetworkError(100131, -1, "Error on logging in to Identity Server!"));
return; return;
} }
HashMap<String, String> object; HashMap<String, String> object;
try { try {
object = getCookie(cookies, new String[]{"_idp_session"}); object = getCookie(cookies1, new String[]{"_idp_session"});
} catch (NoSuchFieldException e) { } catch (NoSuchFieldException e) {
errorCallback.onError(new NetworkError(100132, -1, "Error on logging in to Identity Server!")); errorCallback.onError(new NetworkError(100132, -1, "Error on logging in to Identity Server!"));
return; return;
} }
callback.onResponse(object); callback.onResponse(object);
} }, error -> errorCallback.onError(new NetworkError(100130, error.networkResponse.statusCode, "Error on logging in to Identity Server!")));
}, new Response.ErrorListener() {
@Override
public void onErrorResponse(VolleyError error) {
errorCallback.onError(new NetworkError(100130, error.networkResponse.statusCode, "Error on logging in to Identity Server!"));
}
});
} }
/* /*
@@ -205,9 +168,7 @@ class KVVLogin extends HTTPService {
cookies.put("_idp_authn_lc_key", _idp_authn_lc_key); cookies.put("_idp_authn_lc_key", _idp_authn_lc_key);
cookies.put("ROUTEID", ROUTEID); cookies.put("ROUTEID", ROUTEID);
cookies.put("_idp_session", _idp_session); cookies.put("_idp_session", _idp_session);
get("https://identity.fu-berlin.de/idp-fub/profile/SAML2/Redirect/SSO", cookies, new Response.Listener<Result>() { get("https://identity.fu-berlin.de/idp-fub/profile/SAML2/Redirect/SSO", cookies, response -> {
@Override
public void onResponse(Result response) {
HashMap<String, String> object = new HashMap<>(); HashMap<String, String> object = new HashMap<>();
Pattern pattern = Pattern.compile("ss&#x3a;mem&#x3a;([0-9a-f]+)"); Pattern pattern = Pattern.compile("ss&#x3a;mem&#x3a;([0-9a-f]+)");
@@ -227,13 +188,7 @@ class KVVLogin extends HTTPService {
object.put("SAMLResponse", matcher.group(1)); object.put("SAMLResponse", matcher.group(1));
callback.onResponse(object); callback.onResponse(object);
} }, error -> errorCallback.onError(new NetworkError(100140, error.networkResponse.statusCode, "Error on getting SAML response!")));
}, new Response.ErrorListener() {
@Override
public void onErrorResponse(VolleyError error) {
errorCallback.onError(new NetworkError(100140, error.networkResponse.statusCode, "Error on getting SAML response!"));
}
});
} }
@@ -251,11 +206,9 @@ class KVVLogin extends HTTPService {
HashMap<String, String> body = new HashMap<>(); HashMap<String, String> body = new HashMap<>();
body.put("RelayState", RelayState); body.put("RelayState", RelayState);
body.put("SAMLResponse", SAMLResponse); body.put("SAMLResponse", SAMLResponse);
post("https://kvv.imp.fu-berlin.de/Shibboleth.sso/SAML2/POST", cookies, body, new Response.Listener<Result>() { post("https://kvv.imp.fu-berlin.de/Shibboleth.sso/SAML2/POST", cookies, body, response -> {
@Override String cookies1 = response.getHeaders().get("Set-Cookie");
public void onResponse(Result response) { if (cookies1 ==null) {
String cookies = response.getHeaders().get("Set-Cookie");
if (cookies==null) {
errorCallback.onError(new NetworkError(100151, -1, "Error on starting KVV session!")); errorCallback.onError(new NetworkError(100151, -1, "Error on starting KVV session!"));
return; return;
} }
@@ -263,7 +216,7 @@ class KVVLogin extends HTTPService {
Pattern pattern = Pattern.compile("(_shibsession_[0-9a-f]+)=([^;]+);"); Pattern pattern = Pattern.compile("(_shibsession_[0-9a-f]+)=([^;]+);");
Matcher matcher = pattern.matcher(cookies); Matcher matcher = pattern.matcher(cookies1);
if (!matcher.find()) { if (!matcher.find()) {
errorCallback.onError(new NetworkError(100152, -1, "Error on starting Ident session!")); errorCallback.onError(new NetworkError(100152, -1, "Error on starting Ident session!"));
} }
@@ -271,13 +224,7 @@ class KVVLogin extends HTTPService {
object.put("shibsessionName", matcher.group(2)); object.put("shibsessionName", matcher.group(2));
callback.onResponse(object); callback.onResponse(object);
} }, error -> errorCallback.onError(new NetworkError(100150, error.networkResponse.statusCode, "Error on starting Ident session!")));
}, new Response.ErrorListener() {
@Override
public void onErrorResponse(VolleyError error) {
errorCallback.onError(new NetworkError(100150, error.networkResponse.statusCode, "Error on starting Ident session!"));
}
});
} }
@@ -288,17 +235,7 @@ class KVVLogin extends HTTPService {
_b1912c5a03d733a80bd3fee772bf68d4 _b1912c5a03d733a80bd3fee772bf68d4
*/ */
private void finishKVVlogin(LoginToken loginToken, final NetworkCallback<HashMap<String, String>> callback, final NetworkErrorCallback errorCallback) { private void finishKVVlogin(LoginToken loginToken, final NetworkCallback<HashMap<String, String>> callback, final NetworkErrorCallback errorCallback) {
get("https://kvv.imp.fu-berlin.de/sakai-login-tool/container", loginToken.getCookies(), new Response.Listener<Result>() { get("https://kvv.imp.fu-berlin.de/sakai-login-tool/container", loginToken.getCookies(), response -> callback.onResponse(new HashMap<>()), error -> errorCallback.onError(new NetworkError(100160, error.networkResponse.statusCode, "Cannot finish login process!")));
@Override
public void onResponse(Result response) {
callback.onResponse(new HashMap<String, String>());
}
}, new Response.ErrorListener() {
@Override
public void onErrorResponse(VolleyError error) {
errorCallback.onError(new NetworkError(100160, error.networkResponse.statusCode, "Cannot finish login process!"));
}
});
} }

View File

@@ -38,7 +38,7 @@ public class KVVModuleList extends HTTPService {
get("https://kvv.imp.fu-berlin.de/direct/site.json", token.getCookies(), response -> { get("https://kvv.imp.fu-berlin.de/direct/site.json", token.getCookies(), response -> {
String body = response.getParsed(); String body = response.getParsed();
if (body == null) { if (body == null) {
errorCallback.onError(new NetworkError(101101, 403, "No module list retreived!")); errorCallback.onError(new NetworkError(101101, 403, "No module list retrieved!"));
return; return;
} }
Modules modules = new Modules(); Modules modules = new Modules();
@@ -78,11 +78,14 @@ public class KVVModuleList extends HTTPService {
} }
public void getModule(int index, final NetworkCallback<Modules.Module> callback, final NetworkErrorCallback errorCallback) { public void getModule(int index, final NetworkCallback<Modules.Module> callback, final NetworkErrorCallback errorCallback) {
this.getModuleList(success -> { this.getModuleList(success -> callback.onResponse(success.get(index)), errorCallback);
callback.onResponse(success.get(index));
}, errorCallback);
} }
public void getAnnouncements(Modules.Module module, final NetworkCallback<Modules.Module> callback, final NetworkErrorCallback errorCallback) { public void getAnnouncements(Modules.Module module, final NetworkCallback<Modules.Module> callback, final NetworkErrorCallback errorCallback) {
queueModuleDetails.add(module.getID(), () -> { queueModuleDetails.add(module.getID(), () -> {
if (module.announcements != null) { if (module.announcements != null) {
@@ -103,7 +106,7 @@ public class KVVModuleList extends HTTPService {
get(String.format("https://kvv.imp.fu-berlin.de/direct/announcement/site/%s.json?n=999999&d=999999999", ID), token.getCookies(), response -> { get(String.format("https://kvv.imp.fu-berlin.de/direct/announcement/site/%s.json?n=999999&d=999999999", ID), token.getCookies(), response -> {
String body = response.getParsed(); String body = response.getParsed();
if (body == null) { if (body == null) {
errorCallback.onError(new NetworkError(101201, 403, "No announcements retreived!")); errorCallback.onError(new NetworkError(101201, 403, "No announcements retrieved!"));
return; return;
} }
ArrayList<Announcement> announcements = new ArrayList<>(); ArrayList<Announcement> announcements = new ArrayList<>();
@@ -129,4 +132,28 @@ public class KVVModuleList extends HTTPService {
callback.onResponse(announcements); callback.onResponse(announcements);
}, error -> errorCallback.onError(new NetworkError(101203, error.networkResponse.statusCode, "Cannot get announcements!"))); }, error -> errorCallback.onError(new NetworkError(101203, error.networkResponse.statusCode, "Cannot get announcements!")));
} }
public void getAssignments(Modules.Module module, final NetworkCallback<Modules.Module> callback, final NetworkErrorCallback errorCallback) {
queueModuleDetails.add(module.getID(), () -> {
if (module.assignments != null) {
callback.onResponse(module);
queueModuleDetails.next(module.getID());
return;
}
getAssignmentsUpgrade(module.getID(), success -> {
module.assignments = success;
callback.onResponse(module);
queueModuleDetails.next(module.getID());
}, errorCallback);
});
}
private void getAssignmentsUpgrade(String ID, final NetworkCallback<ArrayList<Assignment>> callback, final NetworkErrorCallback errorCallback) {
callback.onResponse(new ArrayList<Assignment>());
}
} }

View File

@@ -160,13 +160,13 @@ public class Modules /*extends EventEmitter<Triplet<Integer, Modules.UpgradeModu
int size = list.size(); int size = list.size();
do { do {
next++; next++;
} while (next < size && !accept(list.get(next))); } while (next < size && decline(list.get(next)));
if (next == size) if (next == size)
next = -1; next = -1;
} }
private boolean accept(Module ob){ private boolean decline(Module ob){
return ob.semester.equals(latestSemester); return !ob.semester.equals(latestSemester);
} }
}; };
} }
@@ -188,6 +188,7 @@ public class Modules /*extends EventEmitter<Triplet<Integer, Modules.UpgradeModu
public final String description; public final String description;
private final String ID; private final String ID;
public ArrayList<Announcement> announcements; public ArrayList<Announcement> announcements;
public ArrayList<Assignment> assignments;
/*private Module() { /*private Module() {
this(null, null, null, null, null); this(null, null, null, null, null);

View File

@@ -6,8 +6,6 @@ import android.util.Log;
import com.android.volley.AuthFailureError; import com.android.volley.AuthFailureError;
import com.android.volley.Request; import com.android.volley.Request;
import com.android.volley.RequestQueue; import com.android.volley.RequestQueue;
import com.android.volley.Response;
import com.android.volley.VolleyError;
import com.android.volley.VolleyLog; import com.android.volley.VolleyLog;
import com.android.volley.toolbox.StringRequest; import com.android.volley.toolbox.StringRequest;
import com.android.volley.toolbox.Volley; import com.android.volley.toolbox.Volley;
@@ -35,17 +33,7 @@ public class MensaPlan {
post.put("date", "2017-10-13"); post.put("date", "2017-10-13");
final String requestBody = post.toString(); final String requestBody = post.toString();
StringRequest request = new StringRequest(Request.Method.POST, "https://www.stw.berlin/xhr/speiseplan-wochentag.html", new Response.Listener<String>() { StringRequest request = new StringRequest(Request.Method.POST, "https://www.stw.berlin/xhr/speiseplan-wochentag.html", response -> Log.d("MensaPlan DDDD", response), error -> Log.d("MensaPlan EEEE", error.getMessage())) {
@Override
public void onResponse(String response) {
Log.d("MensaPlan DDDD", response);
}
}, new Response.ErrorListener() {
@Override
public void onErrorResponse(VolleyError error) {
Log.d("MensaPlan EEEE", error.getMessage());
}
}) {
@Override @Override
public String getBodyContentType() { public String getBodyContentType() {
return "application/json; charset=utf-8"; return "application/json; charset=utf-8";

View File

@@ -1,12 +1,9 @@
package de.sebse.fuplanner.tools; package de.sebse.fuplanner.tools;
import android.support.annotation.NonNull;
import java.util.HashMap; import java.util.HashMap;
import java.util.LinkedList; import java.util.LinkedList;
import de.sebse.fuplanner.tools.network.NetworkCallback; import de.sebse.fuplanner.tools.network.NetworkCallback;
import de.sebse.fuplanner.tools.network.NetworkError;
import de.sebse.fuplanner.tools.network.NetworkErrorCallback; import de.sebse.fuplanner.tools.network.NetworkErrorCallback;
public class AsyncQueue { public class AsyncQueue {

View File

@@ -1,5 +1,6 @@
package de.sebse.fuplanner.tools; package de.sebse.fuplanner.tools;
import android.annotation.SuppressLint;
import android.annotation.TargetApi; import android.annotation.TargetApi;
import android.os.Build; import android.os.Build;
import android.text.format.DateFormat; import android.text.format.DateFormat;
@@ -16,13 +17,14 @@ public class Conversion {
return getModifiedDate(Locale.getDefault(), modified); return getModifiedDate(Locale.getDefault(), modified);
} }
@SuppressLint("SimpleDateFormat")
public static String getModifiedDate(Locale locale, long modified) { public static String getModifiedDate(Locale locale, long modified) {
SimpleDateFormat dateFormat = null; SimpleDateFormat dateFormat;
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN_MR2) { if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN_MR2) {
dateFormat = new SimpleDateFormat(getDateFormat(locale)); dateFormat = new SimpleDateFormat(getDateFormat(locale));
} else { } else {
dateFormat = new SimpleDateFormat("MMM/dd/yyyy hh:mm:ss aa"); dateFormat = new SimpleDateFormat("MMM/dd/yyyy hh:mm:ss aa", locale);
} }
return dateFormat.format(new Date(modified)); return dateFormat.format(new Date(modified));

View File

@@ -1,7 +1,5 @@
package de.sebse.fuplanner.tools; package de.sebse.fuplanner.tools;
import android.support.annotation.NonNull;
import org.intellij.lang.annotations.Language; import org.intellij.lang.annotations.Language;
import java.util.Iterator; import java.util.Iterator;
@@ -26,10 +24,7 @@ public class Regex {
public static Iterable<MatchResult> allMatches(@Language("Regexp") String regex, final CharSequence input) { public static Iterable<MatchResult> allMatches(@Language("Regexp") String regex, final CharSequence input) {
final Pattern pattern = Pattern.compile(regex, Pattern.DOTALL); final Pattern pattern = Pattern.compile(regex, Pattern.DOTALL);
return new Iterable<MatchResult>() { return () -> new Iterator<MatchResult>() {
@NonNull
public Iterator<MatchResult> iterator() {
return new Iterator<MatchResult>() {
// Use a matcher internally. // Use a matcher internally.
final Matcher matcher = pattern.matcher(input); final Matcher matcher = pattern.matcher(input);
// Keep a match around that supports any interleaving of hasNext/next calls. // Keep a match around that supports any interleaving of hasNext/next calls.
@@ -58,6 +53,4 @@ public class Regex {
public void remove() { throw new UnsupportedOperationException(); } public void remove() { throw new UnsupportedOperationException(); }
}; };
} }
};
}
} }

View File

@@ -37,7 +37,8 @@ public class BetterHurlStack extends HurlStack {
private final UrlRewriter mUrlRewriter; private final UrlRewriter mUrlRewriter;
private final SSLSocketFactory mSslSocketFactory; private final SSLSocketFactory mSslSocketFactory;
private boolean followRedirects; @SuppressWarnings({"unused", "FieldCanBeLocal"})
private boolean followRedirects; // TODO auto-redirect
BetterHurlStack() { BetterHurlStack() {
this(true); this(true);
@@ -130,7 +131,7 @@ public class BetterHurlStack extends HurlStack {
/** /**
* Initializes an {@link HttpEntity} from the given {@link HttpURLConnection}. * Initializes an {@link HttpEntity} from the given {@link HttpURLConnection}.
* @param connection * @param connection A http connection
* @return an HttpEntity populated with data from <code>connection</code>. * @return an HttpEntity populated with data from <code>connection</code>.
*/ */
private static HttpEntity entityFromConnection(HttpURLConnection connection) { private static HttpEntity entityFromConnection(HttpURLConnection connection) {

View File

@@ -2,7 +2,6 @@ package de.sebse.fuplanner.tools.network;
import android.content.Context; import android.content.Context;
import android.support.annotation.Nullable; import android.support.annotation.Nullable;
import android.util.Log;
import com.android.volley.AuthFailureError; import com.android.volley.AuthFailureError;
import com.android.volley.NetworkResponse; import com.android.volley.NetworkResponse;

View File

@@ -17,7 +17,8 @@
android:layout_width="128dp" android:layout_width="128dp"
android:layout_height="128dp" android:layout_height="128dp"
android:layout_marginBottom="24dp" android:layout_marginBottom="24dp"
android:layout_gravity="center_horizontal" /> android:layout_gravity="center_horizontal"
android:contentDescription="@string/cd_ic_launcher"/>
<!-- Email Label --> <!-- Email Label -->
<android.support.design.widget.TextInputLayout <android.support.design.widget.TextInputLayout
@@ -29,7 +30,7 @@
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:inputType="textEmailAddress" android:inputType="textEmailAddress"
android:hint="Username" /> android:hint="@string/username" />
</android.support.design.widget.TextInputLayout> </android.support.design.widget.TextInputLayout>
<!-- Password Label --> <!-- Password Label -->
@@ -42,7 +43,7 @@
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:inputType="textPassword" android:inputType="textPassword"
android:hint="Password"/> android:hint="@string/password"/>
</android.support.design.widget.TextInputLayout> </android.support.design.widget.TextInputLayout>
<android.support.v7.widget.AppCompatButton <android.support.v7.widget.AppCompatButton
@@ -52,7 +53,7 @@
android:layout_marginTop="24dp" android:layout_marginTop="24dp"
android:layout_marginBottom="24dp" android:layout_marginBottom="24dp"
android:padding="12dp" android:padding="12dp"
android:text="Login"/> android:text="@string/log_in"/>
</LinearLayout> </LinearLayout>

View File

@@ -9,6 +9,6 @@
<TextView <TextView
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="match_parent" android:layout_height="match_parent"
android:text="Announcement fragment" /> android:text="@string/lorem_ipsum_100" />
</FrameLayout> </FrameLayout>

View File

@@ -10,6 +10,7 @@
android:layout_width="@android:dimen/thumbnail_width" android:layout_width="@android:dimen/thumbnail_width"
android:layout_height="@android:dimen/thumbnail_height" android:layout_height="@android:dimen/thumbnail_height"
android:layout_gravity="center" android:layout_gravity="center"
android:src="@mipmap/ic_launcher" /> android:src="@mipmap/ic_launcher"
android:contentDescription="@string/cd_ic_launcher"/>
</FrameLayout> </FrameLayout>

View File

@@ -1,14 +1,15 @@
<?xml version="1.0" encoding="utf-8"?> <?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="wrap_content" xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:orientation="horizontal"> android:orientation="horizontal">
<TextView <TextView
android:id="@+id/caption" android:id="@+id/caption"
android:layout_width="wrap_content" android:layout_width="match_parent"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:layout_margin="@dimen/text_margin" android:layout_margin="@dimen/text_margin"
android:text="Caption" tools:text="Caption"
android:textAppearance="@style/Base.TextAppearance.AppCompat.Headline" /> android:textAppearance="@style/Base.TextAppearance.AppCompat.Headline" />
</LinearLayout> </LinearLayout>

View File

@@ -0,0 +1,19 @@
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="horizontal">
<TextView
android:id="@+id/caption"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_margin="@dimen/text_margin"
android:text="@string/show_all"
android:textStyle="bold"
android:typeface="sans"
android:gravity="center"
android:textColor="@color/colorFUSecondary"
/>
</LinearLayout>

View File

@@ -1,7 +1,7 @@
<?xml version="1.0" encoding="utf-8"?> <?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android" <RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools" xmlns:tools="http://schemas.android.com/tools"
android:layout_width="fill_parent" android:layout_width="match_parent"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:orientation="horizontal" android:orientation="horizontal"
android:padding="5dip" > android:padding="5dip" >
@@ -15,21 +15,21 @@
tools:text="Test this new stuff!" /> tools:text="Test this new stuff!" />
<TextView <TextView
android:id="@+id/publisher" android:id="@+id/sub_left"
android:layout_width="wrap_content" android:layout_width="wrap_content"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:layout_below="@id/title" android:layout_below="@id/title"
android:layout_marginTop="5dip" android:layout_marginTop="5dip"
android:textColor="#343434" android:textColor="#343434"
android:textSize="12sp" android:textSize="12sp"
tools:text="Peter Müller" /> tools:text="Peter Bauer" />
<TextView <TextView
android:id="@+id/date" android:id="@+id/sub_right"
android:layout_width="wrap_content" android:layout_width="wrap_content"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:layout_alignBaseline="@+id/publisher" android:layout_alignBaseline="@id/sub_left"
android:layout_alignBottom="@+id/publisher" android:layout_alignBottom="@id/sub_left"
android:textColor="#343434" android:textColor="#343434"
android:textSize="12sp" android:textSize="12sp"
android:layout_alignParentEnd="true" android:layout_alignParentEnd="true"

View File

@@ -1,14 +1,41 @@
<?xml version="1.0" encoding="utf-8"?> <?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="wrap_content" android:layout_width="match_parent"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:orientation="horizontal"> android:orientation="horizontal">
<!-- sample xml -->
<com.ms.square.android.expandabletextview.ExpandableTextView
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:expandableTextView="http://schemas.android.com/apk/res-auto"
android:id="@+id/expand_text_view"
android:layout_width="match_parent"
android:layout_height="wrap_content"
expandableTextView:maxCollapsedLines="4"
expandableTextView:animDuration="200">
<TextView <TextView
android:id="@id/expandable_text"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginLeft="10dp"
android:layout_marginRight="10dp"
android:textSize="16sp"
android:textColor="#666666" />
<ImageButton
android:id="@id/expand_collapse"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:padding="16dp"
android:layout_gravity="end|bottom"
android:background="@android:color/transparent"
android:contentDescription="@string/description" />
</com.ms.square.android.expandabletextview.ExpandableTextView>
<!--<TextView
android:id="@+id/description" android:id="@+id/description"
android:layout_width="wrap_content" android:layout_width="wrap_content"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:layout_margin="@dimen/text_margin" android:layout_margin="@dimen/text_margin"
android:text="@string/lorem_ipsum_100" android:text="@string/lorem_ipsum_100"
android:textAppearance="?attr/textAppearanceListItem" /> android:textAppearance="?attr/textAppearanceListItem" />-->
</LinearLayout> </LinearLayout>

View File

@@ -1,6 +1,7 @@
<?xml version="1.0" encoding="utf-8"?> <?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto" xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="@dimen/nav_header_height" android:layout_height="@dimen/nav_header_height"
android:background="@drawable/side_nav_bar" android:background="@drawable/side_nav_bar"
@@ -17,7 +18,7 @@
android:layout_width="wrap_content" android:layout_width="wrap_content"
android:layout_height="wrap_content" android:layout_height="wrap_content"
style="@style/Widget.AppCompat.Button.Colored" style="@style/Widget.AppCompat.Button.Colored"
android:text="Login" android:text="@string/log_in"
android:visibility="gone" /> android:visibility="gone" />
@@ -27,14 +28,15 @@
android:layout_width="wrap_content" android:layout_width="wrap_content"
android:layout_height="wrap_content" android:layout_height="wrap_content"
app:srcCompat="@mipmap/ic_launcher" app:srcCompat="@mipmap/ic_launcher"
android:visibility="gone" /> android:visibility="gone"
android:contentDescription="@string/cd_ic_launcher"/>
<TextView <TextView
android:id="@+id/login_name" android:id="@+id/login_name"
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:paddingTop="@dimen/nav_header_vertical_spacing" android:paddingTop="@dimen/nav_header_vertical_spacing"
android:text="Android Studio" tools:text="Android Studio"
android:textAppearance="@style/TextAppearance.AppCompat.Body1" android:textAppearance="@style/TextAppearance.AppCompat.Body1"
android:visibility="gone" /> android:visibility="gone" />
</LinearLayout> </LinearLayout>

View File

@@ -1,29 +0,0 @@
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:layout_width="match_parent"
android:layout_height="@dimen/nav_header_height"
android:background="@drawable/side_nav_bar"
android:gravity="bottom"
android:orientation="vertical"
android:paddingBottom="@dimen/activity_vertical_margin"
android:paddingLeft="@dimen/activity_horizontal_margin"
android:paddingRight="@dimen/activity_horizontal_margin"
android:paddingTop="@dimen/activity_vertical_margin"
android:theme="@style/ThemeOverlay.AppCompat.Dark">
<ImageView
android:id="@+id/imageView"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
app:srcCompat="@mipmap/ic_launcher" />
<TextView
android:id="@+id/login_name"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:paddingTop="@dimen/nav_header_vertical_spacing"
android:text="Android Studio"
android:textAppearance="@style/TextAppearance.AppCompat.Body1" />
</LinearLayout>

View File

@@ -5,15 +5,15 @@
<item <item
android:id="@+id/nav_dining" android:id="@+id/nav_dining"
android:icon="@drawable/ic_local_dining" android:icon="@drawable/ic_local_dining"
android:title="Mensaplan" /> android:title="@string/canteen_plan" />
</group> </group>
<item android:title="Optionen"> <item android:title="@string/options">
<menu> <menu>
<item <item
android:id="@+id/nav_share" android:id="@+id/nav_share"
android:icon="@drawable/ic_menu_share" android:icon="@drawable/ic_menu_share"
android:title="Teilen"/> android:title="@string/share"/>
</menu> </menu>
</item> </item>

View File

@@ -5,37 +5,37 @@
<item <item
android:id="@+id/nav_schedule" android:id="@+id/nav_schedule"
android:icon="@drawable/ic_event" android:icon="@drawable/ic_event"
android:title="Stundenplan" android:title="@string/schedule"
android:orderInCategory="10"/> android:orderInCategory="10"/>
<item <item
android:id="@+id/nav_modules" android:id="@+id/nav_modules"
android:icon="@drawable/ic_apps" android:icon="@drawable/ic_apps"
android:title="Module" android:title="@string/events"
android:orderInCategory="100" /> android:orderInCategory="100" />
<item <item
android:id="@+id/nav_dining" android:id="@+id/nav_dining"
android:icon="@drawable/ic_local_dining" android:icon="@drawable/ic_local_dining"
android:title="Mensaplan" android:title="@string/canteen_plan"
android:orderInCategory="200"/> android:orderInCategory="200"/>
<item <item
android:id="@+id/nav_settings" android:id="@+id/nav_settings"
android:icon="@drawable/ic_settings" android:icon="@drawable/ic_settings"
android:title="Einstellungen" android:title="@string/settings"
android:orderInCategory="300"/> android:orderInCategory="300"/>
</group> </group>
<item android:title="Optionen" <item android:title="@string/options"
android:orderInCategory="499"> android:orderInCategory="499">
<menu> <menu>
<item <item
android:id="@+id/nav_logout" android:id="@+id/nav_logout"
android:icon="@drawable/ic_exit_to_app" android:icon="@drawable/ic_exit_to_app"
android:title="Logout" android:title="@string/log_out"
android:orderInCategory="500"/> android:orderInCategory="500"/>
<item <item
android:id="@+id/nav_share" android:id="@+id/nav_share"
android:icon="@drawable/ic_menu_share" android:icon="@drawable/ic_menu_share"
android:title="Teilen" android:title="@string/share"
android:orderInCategory="600"/> android:orderInCategory="600"/>
</menu> </menu>
</item> </item>

View File

@@ -7,10 +7,21 @@
<string name="action_settings">Settings</string> <string name="action_settings">Settings</string>
<!-- TODO: Remove or change this placeholder text --> <!-- TODO: Remove or change this placeholder text -->
<string name="hello_blank_fragment">Hello blank fragment</string>
<string name="overview">Overview</string> <string name="overview">Overview</string>
<string name="announcements">Announcements</string> <string name="announcements">Announcements</string>
<string name="lorem_ipsum_100">Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet.</string> <string name="lorem_ipsum_100">Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet.</string>
<string name="description">Description</string> <string name="description">Description</string>
<string name="announcements_count">Announcements (%1$d)</string> <string name="announcements_count">Announcements (%1$d)</string>
<string name="cd_ic_launcher">App Icon</string>
<string name="schedule">Schedule</string>
<string name="events">Events</string>
<string name="canteen_plan">Canteen Plan</string>
<string name="settings">Settings</string>
<string name="options">Options</string>
<string name="log_out">Log out</string>
<string name="share">Share</string>
<string name="log_in">Log in</string>
<string name="username">Username</string>
<string name="password">Password</string>
<string name="show_all">Show All</string>
</resources> </resources>