Merge remote-tracking branch 'origin/master'

# Conflicts:
#	app/src/main/res/values/strings.xml
This commit is contained in:
Joshua
2018-07-10 10:47:56 +02:00
26 changed files with 759 additions and 232 deletions

2
.idea/misc.xml generated
View File

@@ -25,5 +25,5 @@
</value> </value>
</option> </option>
</component> </component>
<component name="ProjectRootManager" version="2" languageLevel="JDK_1_8" default="true" project-jdk-name="1.8 (2)" project-jdk-type="JavaSDK" /> <component name="ProjectRootManager" version="2" languageLevel="JDK_1_8" default="true" project-jdk-name="1.8" project-jdk-type="JavaSDK" />
</project> </project>

2
.idea/modules.xml generated
View File

@@ -2,7 +2,7 @@
<project version="4"> <project version="4">
<component name="ProjectModuleManager"> <component name="ProjectModuleManager">
<modules> <modules>
<module fileurl="file://$PROJECT_DIR$/.idea/FUPlanner.iml" filepath="$PROJECT_DIR$/.idea/FUPlanner.iml" /> <module fileurl="file://$PROJECT_DIR$/FUPlanner.iml" filepath="$PROJECT_DIR$/FUPlanner.iml" />
<module fileurl="file://$PROJECT_DIR$/app/app.iml" filepath="$PROJECT_DIR$/app/app.iml" /> <module fileurl="file://$PROJECT_DIR$/app/app.iml" filepath="$PROJECT_DIR$/app/app.iml" />
</modules> </modules>
</component> </component>

1
.idea/vcs.xml generated
View File

@@ -2,6 +2,5 @@
<project version="4"> <project version="4">
<component name="VcsDirectoryMappings"> <component name="VcsDirectoryMappings">
<mapping directory="" vcs="Git" /> <mapping directory="" vcs="Git" />
<mapping directory="$PROJECT_DIR$" vcs="Git" />
</component> </component>
</project> </project>

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.1' implementation 'com.android.support.constraint:constraint-layout:1.1.2'
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'
@@ -47,5 +47,7 @@ dependencies {
implementation 'org.jetbrains:annotations-java5:15.0' implementation 'org.jetbrains:annotations-java5:15.0'
implementation 'com.github.quivr:android-week-view:2.0.2'//com.github.alamkanak:android-week-view:1.2.6 implementation 'com.github.quivr:android-week-view:2.0.2'//com.github.alamkanak:android-week-view:1.2.6
implementation 'com.ms-square:expandableTextView:0.1.4' implementation 'com.ms-square:expandableTextView:0.1.4'
// https://github.com/bignerdranch/expandable-recycler-view
implementation 'com.bignerdranch.android:expandablerecyclerview:3.0.0-RC1'
implementation files('libs/jericho-html-3.4.jar') implementation files('libs/jericho-html-3.4.jar')
} }

View File

@@ -75,16 +75,16 @@ public class MainActivity extends AppCompatActivity
getGoogleAuth().getLoginState(credentials -> { getGoogleAuth().getLoginState(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); toLogoutState();
return; return;
} }
MainActivity.this.getKVV().login(credentials.getUsername(), credentials.getPassword(), success -> { MainActivity.this.getKVV().login(credentials.getUsername(), credentials.getPassword(), success -> {
MainActivity.this.getKVV().endUpdate(); MainActivity.this.getKVV().endUpdate();
changeLoginState(credentials); toLoginState(credentials);
}, error -> { }, error -> {
log.e(error); log.e(error);
MainActivity.this.getKVV().endUpdate(); MainActivity.this.getKVV().endUpdate();
changeLoginState(null); toLogoutState();
}); });
}); });
}); });
@@ -149,7 +149,7 @@ public class MainActivity extends AppCompatActivity
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.toLogoutState();
}); });
break; break;
} }
@@ -187,56 +187,60 @@ public class MainActivity extends AppCompatActivity
return this.mKVV; return this.mKVV;
} }
private void changeLoginState(Credentials credentials) { private void toLoginState(Credentials credentials) {
log.d("change login state");
if (credentials == null) { if (credentials == null) {
log.d("null"); toLogoutState();
FragmentTransaction fragmentTransaction = fragmentManager.beginTransaction();
fragmentTransaction.replace(R.id.fragcontainer, LoginFragment.newInstance());
fragmentTransaction.commit();
findViewById(R.id.app_bar_layout).setVisibility(View.VISIBLE);
NavigationView navigationView = findViewById(R.id.nav_view);
View header = navigationView.getHeaderView(0);
header.findViewById(R.id.imageView).setVisibility(View.GONE);
header.findViewById(R.id.login_name).setVisibility(View.GONE);
header.findViewById(R.id.login_page).setVisibility(View.VISIBLE);
navigationView.getMenu().clear();
navigationView.inflateMenu(R.menu.activity_main_drawer);
} else { } else {
log.d(credentials.getUsername()); toLoginState(credentials.getUsername());
FragmentTransaction fragmentTransaction = fragmentManager.beginTransaction();
fragmentTransaction.replace(R.id.fragcontainer, ModulesFragment.newInstance());
fragmentTransaction.commit();
findViewById(R.id.app_bar_layout).setVisibility(View.VISIBLE);
final NavigationView navigationView = findViewById(R.id.nav_view);
View header = navigationView.getHeaderView(0);
header.findViewById(R.id.imageView).setVisibility(View.VISIBLE);
header.findViewById(R.id.login_name).setVisibility(View.VISIBLE);
header.findViewById(R.id.login_page).setVisibility(View.GONE);
navigationView.getMenu().clear();
navigationView.inflateMenu(R.menu.activity_main_drawer_login);
navigationView.setCheckedItem(R.id.nav_modules);
getKVV().getModuleList(success -> {
log.d("Modules.get", success.size());
//SubMenu moduleMenu = navigationView.getMenu().findItem(R.id.nav_modules).getSubMenu();
int i = 0;
for (Iterator<Modules.Module> it = success.latestSemesterIterator(); it.hasNext(); ) {
Modules.Module module = it.next();
MenuItem menuItem = navigationView.getMenu().add(Menu.NONE, Menu.NONE, 101 + i, module.title);
final int finalI = i;
menuItem.setOnMenuItemClickListener(item -> {
onModulesFragmentInteraction(finalI);
return false;
});
i++;
}
}, error -> log.d("Modules.error", error));
} }
} }
private void toLogoutState() {
FragmentTransaction fragmentTransaction = fragmentManager.beginTransaction();
fragmentTransaction.replace(R.id.fragcontainer, LoginFragment.newInstance());
fragmentTransaction.commit();
findViewById(R.id.app_bar_layout).setVisibility(View.VISIBLE);
NavigationView navigationView = findViewById(R.id.nav_view);
View header = navigationView.getHeaderView(0);
header.findViewById(R.id.imageView).setVisibility(View.GONE);
header.findViewById(R.id.login_name).setVisibility(View.GONE);
header.findViewById(R.id.login_page).setVisibility(View.VISIBLE);
navigationView.getMenu().clear();
navigationView.inflateMenu(R.menu.activity_main_drawer);
}
private void toLoginState(String username) {
FragmentTransaction fragmentTransaction = fragmentManager.beginTransaction();
fragmentTransaction.replace(R.id.fragcontainer, ModulesFragment.newInstance());
fragmentTransaction.commit();
findViewById(R.id.app_bar_layout).setVisibility(View.VISIBLE);
final NavigationView navigationView = findViewById(R.id.nav_view);
View header = navigationView.getHeaderView(0);
header.findViewById(R.id.imageView).setVisibility(View.VISIBLE);
header.findViewById(R.id.login_name).setVisibility(View.VISIBLE);
header.findViewById(R.id.login_page).setVisibility(View.GONE);
navigationView.getMenu().clear();
navigationView.inflateMenu(R.menu.activity_main_drawer_login);
navigationView.setCheckedItem(R.id.nav_modules);
getKVV().getModuleList(success -> {
log.d("Modules.get", success.size());
//SubMenu moduleMenu = navigationView.getMenu().findItem(R.id.nav_modules).getSubMenu();
int i = 0;
for (Iterator<Modules.Module> it = success.latestSemesterIterator(); it.hasNext(); ) {
Modules.Module module = it.next();
MenuItem menuItem = navigationView.getMenu().add(Menu.NONE, Menu.NONE, 101 + i, module.title);
final int finalI = i;
menuItem.setOnMenuItemClickListener(item -> {
onModulesFragmentInteraction(finalI);
return false;
});
i++;
}
}, error -> log.e("Modules.error", error));
}
@@ -248,8 +252,8 @@ public class MainActivity extends AppCompatActivity
@Override @Override
public void onLoginFragmentInteraction(Credentials credentials) { public void onLoginFragmentInteraction(String username) {
changeLoginState(credentials); toLoginState(username);
} }
@Override @Override

View File

@@ -8,13 +8,17 @@ import android.support.v4.app.Fragment;
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.Button;
import android.widget.EditText; import android.widget.EditText;
import java.io.IOException;
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.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.types.Modules;
import de.sebse.fuplanner.tools.logging.Logger; import de.sebse.fuplanner.tools.logging.Logger;
/** /**
@@ -26,11 +30,6 @@ import de.sebse.fuplanner.tools.logging.Logger;
* create an instance of this fragment. * create an instance of this fragment.
*/ */
public class LoginFragment extends Fragment { public class LoginFragment extends Fragment {
// TODO: Rename parameter arguments, choose names that match
// the fragment initialization parameters, e.g. ARG_ITEM_NUMBER
// TODO: Rename and change types of parameters
private OnLoginFragmentInteractionListener mListener; private OnLoginFragmentInteractionListener mListener;
private Logger log = new Logger(this); private Logger log = new Logger(this);
@@ -44,7 +43,6 @@ public class LoginFragment extends Fragment {
* *
* @return A new instance of fragment LoginFragment. * @return A new instance of fragment LoginFragment.
*/ */
// TODO: Rename and change types and number of parameters
public static LoginFragment newInstance() { public static LoginFragment newInstance() {
LoginFragment fragment = new LoginFragment(); LoginFragment fragment = new LoginFragment();
Bundle args = new Bundle(); Bundle args = new Bundle();
@@ -61,47 +59,57 @@ public class LoginFragment extends Fragment {
public View onCreateView(@NonNull 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); try {
if (btn_login != null) { Context context = getContext();
btn_login.setOnClickListener(view -> { if (context != null) {
final ProgressDialog progressDialog = new ProgressDialog(LoginFragment.this.getContext(), Modules modules = Modules.load(context);
R.style.FUTheme_Dialog); if (modules != null) {
progressDialog.setIndeterminate(true); Button offline_btn = v.findViewById(R.id.btn_offline);
progressDialog.setMessage("Authenticating..."); offline_btn.setVisibility(View.VISIBLE);
progressDialog.show(); offline_btn.setText(v.getResources().getString(R.string.enter_offline_mode, modules.getUsername()));
offline_btn.setOnClickListener(v1 -> mListener.onLoginFragmentInteraction(modules.getUsername()));
EditText input_usr = ((View) view.getParent()).findViewById(R.id.input_username);
EditText input_pwd = ((View) view.getParent()).findViewById(R.id.input_password);
if (input_usr != null) {
if (input_pwd != null) {
if (LoginFragment.this.getActivity() == null) {
log.e("Login fragment has no activity!");
return;
}
final String username = input_usr.getText().toString();
final String password = input_pwd.getText().toString();
final KVV kvv = ((MainActivity) LoginFragment.this.getActivity()).getKVV();
final GoogleAuth gauth = ((MainActivity) LoginFragment.this.getActivity()).getGoogleAuth();
kvv.login(username, password, success -> {
progressDialog.dismiss();
log.d("success", success.toString());
gauth.setLoginState(username, password);
if (LoginFragment.this.mListener != null) {
Credentials cred = new Credentials(username, password);
LoginFragment.this.mListener.onLoginFragmentInteraction(cred);
}
}, error -> {
progressDialog.dismiss();
log.e("error", error);
});
}
} }
}); }
} catch (IOException e) {
e.printStackTrace();
} catch (ClassNotFoundException e) {
e.printStackTrace();
} }
View btn_login = v.findViewById(R.id.btn_login);
btn_login.setOnClickListener(view -> {
final ProgressDialog progressDialog = new ProgressDialog(LoginFragment.this.getContext(),
R.style.FUTheme_Dialog);
progressDialog.setIndeterminate(true);
progressDialog.setMessage("Authenticating...");
progressDialog.show();
EditText input_usr = ((View) view.getParent()).findViewById(R.id.input_username);
EditText input_pwd = ((View) view.getParent()).findViewById(R.id.input_password);
if (input_usr != null) {
if (input_pwd != null) {
if (LoginFragment.this.getActivity() == null) {
log.e("Login fragment has no activity!");
return;
}
String username = input_usr.getText().toString();
String password = input_pwd.getText().toString();
KVV kvv = ((MainActivity) getActivity()).getKVV();
GoogleAuth gauth = ((MainActivity) getActivity()).getGoogleAuth();
kvv.login(username, password, success -> {
progressDialog.dismiss();
gauth.setLoginState(username, password);
if (mListener != null)
mListener.onLoginFragmentInteraction(username);
}, error -> {
progressDialog.dismiss();
log.e("Error on KVV login!", error);
});
}
}
});
return v; return v;
} }
@@ -135,7 +143,6 @@ public class LoginFragment extends Fragment {
* >Communicating with Other Fragments</a> for more information. * >Communicating with Other Fragments</a> for more information.
*/ */
public interface OnLoginFragmentInteractionListener { public interface OnLoginFragmentInteractionListener {
// TODO: Update argument type and name void onLoginFragmentInteraction(String username);
void onLoginFragmentInteraction(Credentials credentials);
} }
} }

View File

@@ -45,7 +45,6 @@ public class ModulesFragment extends Fragment {
public static ModulesFragment newInstance() { public static ModulesFragment newInstance() {
ModulesFragment fragment = new ModulesFragment(); ModulesFragment fragment = new ModulesFragment();
Bundle args = new Bundle(); Bundle args = new Bundle();
/*args.putInt(ARG_COLUMN_COUNT, columnCount);*/
fragment.setArguments(args); fragment.setArguments(args);
return fragment; return fragment;
} }
@@ -53,10 +52,6 @@ public class ModulesFragment extends Fragment {
@Override @Override
public void onCreate(Bundle savedInstanceState) { public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState); super.onCreate(savedInstanceState);
/*if (getArguments() != null) {
mColumnCount = getArguments().getInt(ARG_COLUMN_COUNT);
}*/
} }
@Override @Override

View File

@@ -17,25 +17,25 @@ class ModDetailAdapter extends FragmentStatePagerAdapter {
super(fm); super(fm);
this.mContext = context; this.mContext = context;
this.mItemPos = itemPosition; this.mItemPos = itemPosition;
log.d("constructor");
} }
// Returns total number of pages // Returns total number of pages
@Override @Override
public int getCount() { public int getCount() {
return 2; return 3;
} }
// Returns the fragment to display for that page // Returns the fragment to display for that page
@Override @Override
public Fragment getItem(int position) { public Fragment getItem(int position) {
log.d("getItem");
switch (position) { switch (position) {
case 0: // Fragment # 0 - This will show FirstFragment case 0:
return ModDetailOverviewFragment.newInstance(mItemPos); return ModDetailOverviewFragment.newInstance(mItemPos);
case 1: // Fragment # 0 - This will show FirstFragment different title case 1:
return ModDetailAnnounceFragment.newInstance(mItemPos); return ModDetailAnnounceFragment.newInstance(mItemPos);
case 2:
return ModDetailAssignmentFragment.newInstance(mItemPos);
default: default:
return null; return null;
} }
@@ -49,6 +49,8 @@ class ModDetailAdapter extends FragmentStatePagerAdapter {
return this.mContext.getResources().getString(R.string.overview); return this.mContext.getResources().getString(R.string.overview);
case 1: case 1:
return this.mContext.getResources().getString(R.string.announcements); return this.mContext.getResources().getString(R.string.announcements);
case 2:
return this.mContext.getResources().getString(R.string.assignments);
default: default:
return ""; return "";
} }

View File

@@ -0,0 +1,108 @@
package de.sebse.fuplanner.fragments.moddetails;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.BaseExpandableListAdapter;
import android.widget.TextView;
import de.sebse.fuplanner.R;
import de.sebse.fuplanner.services.KVV.types.Announcement;
import de.sebse.fuplanner.services.KVV.types.Modules;
import de.sebse.fuplanner.tools.Conversion;
import de.sebse.fuplanner.tools.ui.ItemViewHolder;
import de.sebse.fuplanner.tools.ui.StringViewHolder;
public class ModDetailAnnounceAdapter extends BaseExpandableListAdapter {
private Modules.Module mModule = null;
@Override
public String getChild(int groupPosition, int childPosititon) {
return this.getGroup(groupPosition).getBody();
}
@Override
public long getChildId(int groupPosition, int childPosition) {
return childPosition;
}
@Override
public View getChildView(int groupPosition, final int childPosition,
boolean isLastChild, View convertView, ViewGroup parent) {
final String childText = getChild(groupPosition, childPosition);
if (convertView == null) {
convertView = LayoutInflater.from(parent.getContext())
.inflate(R.layout.list_all_string, parent, false);
}
StringViewHolder itemHolder = new StringViewHolder(convertView);
itemHolder.mString.setText(childText);
return convertView;
}
@Override
public int getChildrenCount(int groupPosition) {
return 1;
}
@Override
public Announcement getGroup(int groupPosition) {
if (this.mModule != null && this.mModule.announcements != null)
return this.mModule.announcements.get(groupPosition);
else
return null;
}
@Override
public int getGroupCount() {
if (this.mModule != null && this.mModule.announcements != null)
return this.mModule.announcements.size();
else
return 0;
}
@Override
public long getGroupId(int groupPosition) {
return groupPosition;
}
@Override
public View getGroupView(int groupPosition, boolean isExpanded,
View convertView, ViewGroup parent) {
Announcement announce = getGroup(groupPosition);
if (convertView == null) {
convertView = LayoutInflater.from(parent.getContext())
.inflate(R.layout.list_all_items, parent, false);
}
ItemViewHolder itemHolder = new ItemViewHolder(convertView);
itemHolder.mTitle.setText(announce.getTitle());
itemHolder.mSubLeft.setText(announce.getCreatedBy());
itemHolder.mSubRight.setText(Conversion.getModifiedDateTime(announce.getCreatedOn()));
return convertView;
}
@Override
public boolean hasStableIds() {
return false;
}
@Override
public boolean isChildSelectable(int groupPosition, int childPosition) {
return false;
}
public void setModule(Modules.Module module) {
this.mModule = module;
this.setModule();
}
public void setModule() {
this.notifyDataSetChanged();
}
}

View File

@@ -1,14 +1,22 @@
package de.sebse.fuplanner.fragments.moddetails; package de.sebse.fuplanner.fragments.moddetails;
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.support.v4.widget.SwipeRefreshLayout;
import android.support.v7.widget.LinearLayoutManager;
import android.support.v7.widget.RecyclerView;
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.ExpandableListView;
import de.sebse.fuplanner.MainActivity;
import de.sebse.fuplanner.R; import de.sebse.fuplanner.R;
import de.sebse.fuplanner.services.KVV.KVV;
import de.sebse.fuplanner.services.KVV.types.Modules;
import de.sebse.fuplanner.tools.logging.Logger; import de.sebse.fuplanner.tools.logging.Logger;
/** /**
@@ -24,6 +32,8 @@ public class ModDetailAnnounceFragment extends Fragment {
// TODO: Rename and change types of parameters // TODO: Rename and change types of parameters
private int mItemPos; private int mItemPos;
private Logger log = new Logger(this); private Logger log = new Logger(this);
private ModDetailAnnounceAdapter adapter;
private SwipeRefreshLayout swipeLayout;
public ModDetailAnnounceFragment() { public ModDetailAnnounceFragment() {
@@ -58,7 +68,41 @@ public class ModDetailAnnounceFragment extends Fragment {
public View onCreateView(@NonNull 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); View view = inflater.inflate(R.layout.fragment_mod_detail_announce, container, false);
// Set the adapter
Context context = view.getContext();
ExpandableListView expandableListView = view.findViewById(R.id.list);
//expandableListView.setLayoutManager(new LinearLayoutManager(context));
adapter = new ModDetailAnnounceAdapter();
expandableListView.setAdapter(adapter);
// Getting SwipeContainerLayout
swipeLayout = view.findViewById(R.id.swipe_container);
// Adding Listener
swipeLayout.setOnRefreshListener(() -> refresh(true));
refresh(false);
return view;
}
private void refresh(boolean forceRefresh) {
if (getActivity() != null) {
KVV kvv = ((MainActivity) getActivity()).getKVV();
kvv.getModuleList((Modules success) -> {
Modules.Module module = success.get(mItemPos);
adapter.setModule(module);
kvv.getModuleAnnouncements(module, success1 -> {
adapter.setModule();
swipeLayout.setRefreshing(false);
}, error -> {
swipeLayout.setRefreshing(false);
log.e(error);
});
}, error -> {
swipeLayout.setRefreshing(false);
log.e(error);
}, forceRefresh);
}
} }
} }

View File

@@ -0,0 +1,117 @@
package de.sebse.fuplanner.fragments.moddetails;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.BaseExpandableListAdapter;
import de.sebse.fuplanner.R;
import de.sebse.fuplanner.services.KVV.types.Announcement;
import de.sebse.fuplanner.services.KVV.types.Assignment;
import de.sebse.fuplanner.services.KVV.types.Modules;
import de.sebse.fuplanner.tools.Conversion;
import de.sebse.fuplanner.tools.ui.ItemViewHolder;
import de.sebse.fuplanner.tools.ui.StringViewHolder;
public class ModDetailAssignmentAdapter extends BaseExpandableListAdapter {
private Modules.Module mModule = null;
@Override
public String getChild(int groupPosition, int childPosititon) {
StringBuilder sb = new StringBuilder();
for (String s : this.getGroup(groupPosition).getUrls())
{
sb.append(s);
sb.append("\n");
}
return sb.toString();
}
@Override
public long getChildId(int groupPosition, int childPosition) {
return childPosition;
}
@Override
public View getChildView(int groupPosition, final int childPosition,
boolean isLastChild, View convertView, ViewGroup parent) {
final String childText = getChild(groupPosition, childPosition);
if (convertView == null) {
convertView = LayoutInflater.from(parent.getContext())
.inflate(R.layout.list_all_string, parent, false);
}
StringViewHolder itemHolder = new StringViewHolder(convertView);
itemHolder.mString.setText(childText);
return convertView;
}
@Override
public int getChildrenCount(int groupPosition) {
return 1;
}
@Override
public Assignment getGroup(int groupPosition) {
if (this.mModule != null && this.mModule.assignments != null)
return this.mModule.assignments.get(groupPosition);
else
return null;
}
@Override
public int getGroupCount() {
if (this.mModule != null && this.mModule.assignments != null)
return this.mModule.assignments.size();
else
return 0;
}
@Override
public long getGroupId(int groupPosition) {
return groupPosition;
}
@Override
public View getGroupView(int groupPosition, boolean isExpanded,
View convertView, ViewGroup parent) {
Assignment assignment = getGroup(groupPosition);
if (convertView == null) {
convertView = LayoutInflater.from(parent.getContext())
.inflate(R.layout.list_all_items, parent, false);
}
ItemViewHolder itemHolder = new ItemViewHolder(convertView);
itemHolder.mTitle.setText(assignment.getTitle());
if(assignment.isOpen())
itemHolder.mSubLeft.setText(itemHolder.mView.getResources().getText(R.string.open));
else
itemHolder.mSubLeft.setText(itemHolder.mView.getResources().getText(R.string.close));
itemHolder.mSubRight.setText(Conversion.getModifiedDateTime(assignment.getDueDate()));
return convertView;
}
@Override
public boolean hasStableIds() {
return false;
}
@Override
public boolean isChildSelectable(int groupPosition, int childPosition) {
return false;
}
public void setModule(Modules.Module module) {
this.mModule = module;
this.setModule();
}
public void setModule() {
this.notifyDataSetChanged();
}
}

View File

@@ -0,0 +1,106 @@
package de.sebse.fuplanner.fragments.moddetails;
import android.content.Context;
import android.os.Bundle;
import android.support.annotation.NonNull;
import android.support.v4.app.Fragment;
import android.support.v4.widget.SwipeRefreshLayout;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.ExpandableListView;
import de.sebse.fuplanner.MainActivity;
import de.sebse.fuplanner.R;
import de.sebse.fuplanner.services.KVV.KVV;
import de.sebse.fuplanner.services.KVV.types.Modules;
import de.sebse.fuplanner.tools.logging.Logger;
/**
* A simple {@link Fragment} subclass.
* Use the {@link ModDetailAssignmentFragment#newInstance} factory method to
* create an instance of this fragment.
*/
public class ModDetailAssignmentFragment extends Fragment {
// TODO: Rename parameter arguments, choose names that match
// the fragment initialization parameters, e.g. ARG_ITEM_NUMBER
private static final String ARG_POSITION = "itemPosition";
// TODO: Rename and change types of parameters
private int mItemPos;
private Logger log = new Logger(this);
private ModDetailAssignmentAdapter adapter;
private SwipeRefreshLayout swipeLayout;
public ModDetailAssignmentFragment() {
// Required empty public constructor
}
/**
* Use this factory method to create a new instance of
* this fragment using the provided parameters.
*
* @param itemPosition Item position in module list.
* @return A new instance of fragment ModDetailAnnounceFragment.
*/
// TODO: Rename and change types and number of parameters
public static ModDetailAssignmentFragment newInstance(int itemPosition) {
ModDetailAssignmentFragment fragment = new ModDetailAssignmentFragment();
Bundle args = new Bundle();
args.putInt(ARG_POSITION, itemPosition);
fragment.setArguments(args);
return fragment;
}
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
if (getArguments() != null) {
mItemPos = getArguments().getInt(ARG_POSITION);
}
}
@Override
public View onCreateView(@NonNull LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
// Inflate the layout for this fragment
View view = inflater.inflate(R.layout.fragment_mod_detail_announce, container, false);
// Set the adapter
Context context = view.getContext();
ExpandableListView expandableListView = view.findViewById(R.id.list);
//expandableListView.setLayoutManager(new LinearLayoutManager(context));
adapter = new ModDetailAssignmentAdapter();
expandableListView.setAdapter(adapter);
// Getting SwipeContainerLayout
swipeLayout = view.findViewById(R.id.swipe_container);
// Adding Listener
swipeLayout.setOnRefreshListener(() -> refresh(true));
refresh(false);
return view;
}
private void refresh(boolean forceRefresh) {
if (getActivity() != null) {
KVV kvv = ((MainActivity) getActivity()).getKVV();
kvv.getModuleList((Modules success) -> {
Modules.Module module = success.get(mItemPos);
adapter.setModule(module);
kvv.getModuleAssignments(module, success1 -> {
adapter.setModule();
swipeLayout.setRefreshing(false);
}, error -> {
swipeLayout.setRefreshing(false);
log.e(error);
});
}, error -> {
swipeLayout.setRefreshing(false);
log.e(error);
}, forceRefresh);
}
}
}

View File

@@ -94,8 +94,14 @@ public class ModDetailOverviewFragment extends Fragment {
adapter.setModule(); adapter.setModule();
if (pair.second) if (pair.second)
swipeLayout.setRefreshing(false); swipeLayout.setRefreshing(false);
}, error -> log.e(error)); }, error -> {
}, error -> log.e(error), forceRefresh); swipeLayout.setRefreshing(false);
log.e(error);
});
}, error -> {
swipeLayout.setRefreshing(false);
log.e(error);
}, forceRefresh);
} }
} }

View File

@@ -10,6 +10,7 @@ import java.util.HashMap;
import de.sebse.fuplanner.services.KVV.types.LoginToken; import de.sebse.fuplanner.services.KVV.types.LoginToken;
import de.sebse.fuplanner.services.KVV.types.Modules; import de.sebse.fuplanner.services.KVV.types.Modules;
import de.sebse.fuplanner.tools.logging.Logger;
import de.sebse.fuplanner.tools.network.NetworkCallback; import de.sebse.fuplanner.tools.network.NetworkCallback;
import de.sebse.fuplanner.tools.network.NetworkErrorCallback; import de.sebse.fuplanner.tools.network.NetworkErrorCallback;
@@ -23,8 +24,10 @@ public class KVV {
private boolean isUpdating; private boolean isUpdating;
private ArrayList<LastTokenCallback> updatingList; private ArrayList<LastTokenCallback> updatingList;
private HashMap<String, Object> addons = new HashMap<>(); private HashMap<String, Object> addons = new HashMap<>();
private Logger log = new Logger(this);
public KVV(Context context) { public KVV(Context context) {
log.d("new kvv");
this.context = context; this.context = context;
this.isUpdating = false; this.isUpdating = false;
this.updatingList = new ArrayList<>(); this.updatingList = new ArrayList<>();
@@ -42,7 +45,7 @@ public class KVV {
lastToken = null; lastToken = null;
KVVModuleList modules = (KVVModuleList) addons.get("modules"); KVVModuleList modules = (KVVModuleList) addons.get("modules");
if (modules != null) { if (modules != null) {
modules.deleteModules(this.context); modules.deleteModulesOffline(this.context);
} }
addons.clear(); addons.clear();
} }
@@ -118,7 +121,7 @@ public class KVV {
private<T> NetworkCallback<T> saveOnCallback(KVVModuleList modules, NetworkCallback<T> callback){ private<T> NetworkCallback<T> saveOnCallback(KVVModuleList modules, NetworkCallback<T> callback){
return (success -> { return (success -> {
try { try {
modules.saveModules(this.context); modules.saveModulesOffline(this.context);
} catch (IOException e) { } catch (IOException e) {
e.printStackTrace(); e.printStackTrace();
} }

View File

@@ -23,6 +23,7 @@ import de.sebse.fuplanner.services.KVV.types.Gradebook;
import de.sebse.fuplanner.services.KVV.types.Lecturer; import de.sebse.fuplanner.services.KVV.types.Lecturer;
import de.sebse.fuplanner.services.KVV.types.LoginToken; import de.sebse.fuplanner.services.KVV.types.LoginToken;
import de.sebse.fuplanner.services.KVV.types.Modules; import de.sebse.fuplanner.services.KVV.types.Modules;
import de.sebse.fuplanner.tools.AssignmentList;
import de.sebse.fuplanner.tools.AsyncQueue; import de.sebse.fuplanner.tools.AsyncQueue;
import de.sebse.fuplanner.tools.EventList; import de.sebse.fuplanner.tools.EventList;
import de.sebse.fuplanner.tools.Regex; import de.sebse.fuplanner.tools.Regex;
@@ -44,7 +45,9 @@ public class KVVModuleList extends HTTPService {
super(context); super(context);
this.token = token; this.token = token;
try { try {
this.moduleList = Modules.load(context); Modules modules = Modules.load(context);
if (token == null || modules.getUsername().equals(token.getUsername()))
this.moduleList = modules;
} catch (IOException e) { } catch (IOException e) {
e.printStackTrace(); e.printStackTrace();
} catch (ClassNotFoundException e) { } catch (ClassNotFoundException e) {
@@ -56,7 +59,9 @@ public class KVVModuleList extends HTTPService {
public void getModuleList(final NetworkCallback<Modules> callback, final NetworkErrorCallback errorCallback, boolean forceRefresh) { public void getModuleList(final NetworkCallback<Modules> callback, final NetworkErrorCallback errorCallback, boolean forceRefresh) {
log.d("getModuleList");
queueModuleDetails.add("list", () -> { queueModuleDetails.add("list", () -> {
log.d("getModuleList start", forceRefresh);
if (this.moduleList != null && !forceRefresh) { if (this.moduleList != null && !forceRefresh) {
callback.onResponse(this.moduleList); callback.onResponse(this.moduleList);
queueModuleDetails.next("list"); queueModuleDetails.next("list");
@@ -66,18 +71,22 @@ public class KVVModuleList extends HTTPService {
this.moduleList = success; this.moduleList = success;
callback.onResponse(this.moduleList); callback.onResponse(this.moduleList);
queueModuleDetails.next("list"); queueModuleDetails.next("list");
}, errorCallback); }, queueModuleDetails.check("list", errorCallback));
}); });
} }
public void getModuleListUpgrade(final NetworkCallback<Modules> callback, final NetworkErrorCallback errorCallback) { private void getModuleListUpgrade(final NetworkCallback<Modules> callback, final NetworkErrorCallback errorCallback) {
if (token == null) {
errorCallback.onError(new NetworkError(101105, 500, "Currently running in offline mode!"));
return;
}
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 retrieved!")); errorCallback.onError(new NetworkError(101101, 403, "No module list retrieved!"));
return; return;
} }
Modules modules = new Modules(); Modules modules = new Modules(token.getUsername());
try { try {
JSONObject json = new JSONObject(body); JSONObject json = new JSONObject(body);
JSONArray sites = json.getJSONArray("site_collection"); JSONArray sites = json.getJSONArray("site_collection");
@@ -112,12 +121,12 @@ public class KVVModuleList extends HTTPService {
}, error -> errorCallback.onError(new NetworkError(101104, error.networkResponse.statusCode, "Cannot get module list!"))); }, error -> errorCallback.onError(new NetworkError(101104, error.networkResponse.statusCode, "Cannot get module list!")));
} }
public void deleteModules(Context context) { public void deleteModulesOffline(Context context) {
if (this.moduleList != null) if (this.moduleList != null)
this.moduleList.delete(context); this.moduleList.delete(context);
} }
public void saveModules(Context context) throws IOException { public void saveModulesOffline(Context context) throws IOException {
if (this.moduleList != null) if (this.moduleList != null)
this.moduleList.save(context); this.moduleList.save(context);
} }
@@ -134,11 +143,11 @@ public class KVVModuleList extends HTTPService {
public void getModuleDetails(Modules.Module module, final NetworkCallback<Pair<Modules.Module, Boolean>> callback, final NetworkErrorCallback errorCallback, boolean forceRefresh) { public void getModuleDetails(Modules.Module module, final NetworkCallback<Pair<Modules.Module, Boolean>> callback, final NetworkErrorCallback errorCallback, boolean forceRefresh) {
AtomicInteger returns = new AtomicInteger(0); AtomicInteger returns = new AtomicInteger(0);
AtomicReference<NetworkError> lastError = new AtomicReference<>(null); AtomicReference<NetworkError> lastError = new AtomicReference<>(null);
final int items = 4; final AtomicInteger items = new AtomicInteger(0);
NetworkCallback<Modules.Module> successCb = success -> { NetworkCallback<Modules.Module> successCb = success -> {
returns.getAndIncrement(); returns.getAndIncrement();
callback.onResponse(Pair.create(module, false)); callback.onResponse(Pair.create(module, false));
if (returns.get() == items) { if (returns.get() == items.get()) {
callback.onResponse(Pair.create(module, true)); callback.onResponse(Pair.create(module, true));
if (lastError.get() != null) if (lastError.get() != null)
errorCallback.onError(lastError.get()); errorCallback.onError(lastError.get());
@@ -147,7 +156,7 @@ public class KVVModuleList extends HTTPService {
NetworkErrorCallback errorCb = error -> { NetworkErrorCallback errorCb = error -> {
lastError.set(error); lastError.set(error);
returns.getAndIncrement(); returns.getAndIncrement();
if (returns.get() == items) { if (returns.get() == items.get()) {
callback.onResponse(Pair.create(module, true)); callback.onResponse(Pair.create(module, true));
if (lastError.get() != null) if (lastError.get() != null)
errorCallback.onError(lastError.get()); errorCallback.onError(lastError.get());
@@ -159,8 +168,7 @@ public class KVVModuleList extends HTTPService {
() -> this.getAnnouncements(module, successCb, errorCb, forceRefresh), () -> this.getAnnouncements(module, successCb, errorCb, forceRefresh),
() -> this.getGradebook(module, successCb, errorCb, forceRefresh) () -> this.getGradebook(module, successCb, errorCb, forceRefresh)
}; };
//noinspection ConstantConditions items.set(methods.length);
if (methods.length != items) throw new AssertionError();
for (Runnable method: methods) { for (Runnable method: methods) {
method.run(); method.run();
} }
@@ -182,12 +190,15 @@ public class KVVModuleList extends HTTPService {
module.announcements = success; module.announcements = success;
callback.onResponse(module); callback.onResponse(module);
queueModuleDetails.next(module.getID()); queueModuleDetails.next(module.getID());
}, errorCallback); }, queueModuleDetails.check(module.getID(), errorCallback));
}); });
} }
private void getAnnouncementsUpgrade(String ID, final NetworkCallback<ArrayList<Announcement>> callback, final NetworkErrorCallback errorCallback) { private void getAnnouncementsUpgrade(String ID, final NetworkCallback<ArrayList<Announcement>> callback, final NetworkErrorCallback errorCallback) {
//log.d("SITE GET URL", String.format("https://kvv.imp.fu-berlin.de/direct/announcement/site/%s.json?n=999999&d=999999999", ID)); if (token == null) {
errorCallback.onError(new NetworkError(101204, 500, "Currently running in offline mode!"));
return;
}
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) {
@@ -233,18 +244,22 @@ public class KVVModuleList extends HTTPService {
module.assignments = success; module.assignments = success;
callback.onResponse(module); callback.onResponse(module);
queueModuleDetails.next(module.getID()); queueModuleDetails.next(module.getID());
}, errorCallback); }, queueModuleDetails.check(module.getID(), errorCallback));
}); });
} }
private void getAssignmentsUpgrade(String ID, final NetworkCallback<ArrayList<Assignment>> callback, final NetworkErrorCallback errorCallback) { private void getAssignmentsUpgrade(String ID, final NetworkCallback<AssignmentList> callback, final NetworkErrorCallback errorCallback) {
if (token == null) {
errorCallback.onError(new NetworkError(101304, 500, "Currently running in offline mode!"));
return;
}
get(String.format("https://kvv.imp.fu-berlin.de/direct/assignment/site/%s.json", ID), token.getCookies(), response ->{ get(String.format("https://kvv.imp.fu-berlin.de/direct/assignment/site/%s.json", ID), token.getCookies(), response ->{
String body = response.getParsed(); String body = response.getParsed();
if (body == null) { if (body == null) {
errorCallback.onError(new NetworkError(101301, 403, "No assignments retrieved!")); errorCallback.onError(new NetworkError(101301, 403, "No assignments retrieved!"));
return; return;
} }
ArrayList<Assignment> assignments = new ArrayList<>(); AssignmentList assignments = new AssignmentList();
try { try {
JSONObject json = new JSONObject(body); JSONObject json = new JSONObject(body);
JSONArray sites = json.getJSONArray("assignment_collection"); JSONArray sites = json.getJSONArray("assignment_collection");
@@ -272,7 +287,7 @@ public class KVVModuleList extends HTTPService {
assignments.add(0, new Assignment(id, title, dueTime, gradebookItemName, gradeScale, urls)); assignments.add(0, new Assignment(id, title, dueTime, gradebookItemName, gradeScale, urls));
} }
} catch (JSONException e) { } catch (JSONException e) {
errorCallback.onError(new NetworkError(101306, 403, "Cannot parse announcements!")); errorCallback.onError(new NetworkError(101302, 403, "Cannot parse announcements!"));
return; return;
} }
callback.onResponse(assignments); callback.onResponse(assignments);
@@ -297,12 +312,15 @@ public class KVVModuleList extends HTTPService {
module.events = success; module.events = success;
callback.onResponse(module); callback.onResponse(module);
queueModuleDetails.next(module.getID()); queueModuleDetails.next(module.getID());
}, errorCallback); }, queueModuleDetails.check(module.getID(), errorCallback));
}); });
} }
private void getEventsUpgrade(String ID, final NetworkCallback<EventList> callback, final NetworkErrorCallback errorCallback) { private void getEventsUpgrade(String ID, final NetworkCallback<EventList> callback, final NetworkErrorCallback errorCallback) {
//https://kvv.imp.fu-berlin.de/direct/calendar/site/91c6e9cc-58eb-486d-ab99-a22a40997d1b.json if (token == null) {
errorCallback.onError(new NetworkError(101404, 500, "Currently running in offline mode!"));
return;
}
get(String.format("https://kvv.imp.fu-berlin.de/direct/calendar/site/%s.json", ID), token.getCookies(), response -> { get(String.format("https://kvv.imp.fu-berlin.de/direct/calendar/site/%s.json", ID), token.getCookies(), response -> {
String body = response.getParsed(); String body = response.getParsed();
if (body == null) { if (body == null) {
@@ -348,11 +366,15 @@ public class KVVModuleList extends HTTPService {
module.gradebook = success; module.gradebook = success;
callback.onResponse(module); callback.onResponse(module);
queueModuleDetails.next(module.getID()); queueModuleDetails.next(module.getID());
}, errorCallback); }, queueModuleDetails.check(module.getID(), errorCallback));
}); });
} }
private void getGradebookUpgrade(String ID, final NetworkCallback<ArrayList<Gradebook>> callback, final NetworkErrorCallback errorCallback) { private void getGradebookUpgrade(String ID, final NetworkCallback<ArrayList<Gradebook>> callback, final NetworkErrorCallback errorCallback) {
if (token == null) {
errorCallback.onError(new NetworkError(101104, 500, "Currently running in offline mode!"));
return;
}
get(String.format("https://kvv.imp.fu-berlin.de/direct/gradebook/site/%s.json", ID ), token.getCookies(), response ->{ get(String.format("https://kvv.imp.fu-berlin.de/direct/gradebook/site/%s.json", ID ), token.getCookies(), response ->{
String body = response.getParsed(); String body = response.getParsed();
if (body == null) { if (body == null) {
@@ -365,22 +387,20 @@ public class KVVModuleList extends HTTPService {
JSONArray sites = json.getJSONArray("assignments"); JSONArray sites = json.getJSONArray("assignments");
for (int i = 0; i < sites.length(); i++) { for (int i = 0; i < sites.length(); i++) {
//log.d("gradebook FOUND!", i);
JSONObject site = sites.getJSONObject(i); JSONObject site = sites.getJSONObject(i);
String grade = site.optString("grade", null); String grade = site.optString("grade", null);
String itemName = site.optString("itemName", null); String itemName = site.optString("itemName", null);
double maxPoints = site.optDouble("points", -1); double maxPoints = site.optDouble("points", -1);
//log.d("Gradebook:",itemName, grade, maxPoints);
gradebook.add(0, new Gradebook(itemName, grade, maxPoints)); gradebook.add(0, new Gradebook(itemName, grade, maxPoints));
} }
}catch (JSONException e) { }catch (JSONException e) {
errorCallback.onError(new NetworkError(101504, 403, "Cannot parse gradebook for announcements!")); errorCallback.onError(new NetworkError(101502, 403, "Cannot parse gradebook for announcements!"));
return; return;
} }
callback.onResponse(gradebook); callback.onResponse(gradebook);
}, error -> errorCallback.onError(new NetworkError(101505, error.networkResponse.statusCode, "Cannot get gradebook for assignments!"))); }, error -> errorCallback.onError(new NetworkError(101503, error.networkResponse.statusCode, "Cannot get gradebook for assignments!")));
} }

View File

@@ -13,6 +13,7 @@ import java.util.ArrayList;
import java.util.HashSet; import java.util.HashSet;
import java.util.Iterator; import java.util.Iterator;
import de.sebse.fuplanner.tools.AssignmentList;
import de.sebse.fuplanner.tools.Compare; import de.sebse.fuplanner.tools.Compare;
import de.sebse.fuplanner.tools.EventList; import de.sebse.fuplanner.tools.EventList;
import de.sebse.fuplanner.tools.Regex; import de.sebse.fuplanner.tools.Regex;
@@ -26,10 +27,12 @@ import de.sebse.fuplanner.tools.logging.Logger;
public class Modules implements Iterable<Modules.Module>, Serializable { public class Modules implements Iterable<Modules.Module>, Serializable {
private final SortedModuleList list; private final SortedModuleList list;
private String latestSemester = null; private String latestSemester = null;
private String username = null;
private transient Logger log = new Logger(this); private transient Logger log = new Logger(this);
private static final String FILE_NAME = "ModuleListSaving"; private static final String FILE_NAME = "ModuleListSaving";
public Modules() { public Modules(String username) {
this.username = username;
this.list = new SortedModuleList(); this.list = new SortedModuleList();
} }
@@ -174,6 +177,10 @@ public class Modules implements Iterable<Modules.Module>, Serializable {
context.deleteFile(FILE_NAME); context.deleteFile(FILE_NAME);
} }
public String getUsername() {
return username;
}
public class Module implements Serializable { public class Module implements Serializable {
public final String semester; public final String semester;
public final HashSet<String> lvNumber; public final HashSet<String> lvNumber;
@@ -183,7 +190,7 @@ public class Modules implements Iterable<Modules.Module>, Serializable {
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; public AssignmentList assignments;
public EventList events; public EventList events;
public ArrayList<Gradebook> gradebook; public ArrayList<Gradebook> gradebook;

View File

@@ -0,0 +1,19 @@
package de.sebse.fuplanner.tools;
import de.sebse.fuplanner.services.KVV.types.Assignment;
import de.sebse.fuplanner.tools.logging.Logger;
public class AssignmentList extends DateSortedList<Assignment> {
@Override
long getDateByItem(Assignment item) {
Logger log = new Logger(this);
log.d(item.getTitle(), Conversion.getModifiedDateTime(item.getDueDate()));
return item.getDueDate();
}
@Override
public boolean reversed() {
return true;
}
}

View File

@@ -3,6 +3,7 @@ package de.sebse.fuplanner.tools;
import java.util.HashMap; import java.util.HashMap;
import java.util.LinkedList; import java.util.LinkedList;
import de.sebse.fuplanner.tools.logging.Logger;
import de.sebse.fuplanner.tools.network.NetworkCallback; import de.sebse.fuplanner.tools.network.NetworkCallback;
import de.sebse.fuplanner.tools.network.NetworkErrorCallback; import de.sebse.fuplanner.tools.network.NetworkErrorCallback;

View File

@@ -0,0 +1,108 @@
package de.sebse.fuplanner.tools;
import java.util.ArrayList;
import java.util.Calendar;
import java.util.Collections;
import java.util.Iterator;
import de.sebse.fuplanner.services.KVV.types.Event;
public abstract class DateSortedList<T> extends ArrayList<T> {
private int split = -1;
public T getPast(int index) {
if (split < 0)
sort();
if (index >= split)
throw new ArrayIndexOutOfBoundsException(String.format("Index %d out of bounds! Only %d past events found!", index, split));
if (reversed())
index = sizePast() - index - 1;
return this.get(index);
}
public T getUpcoming(int index) {
if (split < 0)
sort();
index += split;
if (index >= this.size())
throw new ArrayIndexOutOfBoundsException(String.format("Index %d out of bounds! Only %d upcoming events found!", index-split, this.size()-split));
if (reversed())
index = sizeUpcoming() - index - 1;
return this.get(index);
}
@Override
public T get(int index) {
if (split < 0)
sort();
if (reversed())
index = size() - index - 1;
return super.get(index);
}
public int sizePast() {
if (split < 0)
sort();
return split;
}
public int sizeUpcoming() {
if (split < 0)
sort();
return this.size()-split;
}
public boolean add(T event) {
split = -1;
return super.add(event);
}
public void sort() {
Collections.sort(this, ((e1, e2) -> Long.compare(getDateByItem(e1), getDateByItem(e2))));
long now = System.currentTimeMillis();
split = 0;
for (T event: this) {
if (getDateByItem(event) < now)
split++;
else
break;
}
}
public Iterator<T> getEventsOfMonth(int year, int month) {
if (split < 0)
sort();
final int[] i = {0};
Calendar minC = Calendar.getInstance();
minC.set(year, month-1, 1, 0, 0);
Calendar maxC = Calendar.getInstance();
maxC.set(year, month, 1, 0, 0);
for (; i[0] < this.size(); i[0]++) {
if (getDateByItem(this.get(i[0])) > minC.getTimeInMillis()) {
break;
}
}
return new Iterator<T>() {
@Override
public boolean hasNext() {
return i[0] < DateSortedList.this.size() && getDateByItem(DateSortedList.this.get(i[0])) < maxC.getTimeInMillis();
}
@Override
public T next() {
if (hasNext()) {
return DateSortedList.this.get(i[0]++);
} else {
return null;
}
}
};
}
public boolean reversed() {
return false;
}
abstract long getDateByItem(T item);
}

View File

@@ -1,88 +1,11 @@
package de.sebse.fuplanner.tools; package de.sebse.fuplanner.tools;
import java.util.ArrayList;
import java.util.Calendar;
import java.util.Collections;
import java.util.Iterator;
import de.sebse.fuplanner.services.KVV.types.Event; import de.sebse.fuplanner.services.KVV.types.Event;
public class EventList extends ArrayList<Event> { public class EventList extends DateSortedList<Event> {
private int split = 0;
public Event getPast(int index) { @Override
if (split < 0) long getDateByItem(Event item) {
sort(); return item.getEndDate();
if (index >= split)
throw new ArrayIndexOutOfBoundsException(String.format("Index %d out of bounds! Only %d past events found!", index, split));
return this.get(index);
}
public Event getUpcoming(int index) {
if (split < 0)
sort();
index += split;
if (index >= this.size())
throw new ArrayIndexOutOfBoundsException(String.format("Index %d out of bounds! Only %d upcoming events found!", index-split, this.size()-split));
return this.get(index);
}
public int sizePast() {
if (split < 0)
sort();
return split;
}
public int sizeUpcoming() {
if (split < 0)
sort();
return this.size()-split;
}
public boolean add(Event event) {
split = -1;
return super.add(event);
}
public void sort() {
Collections.sort(this, ((e1, e2) -> Long.compare(e1.getEndDate(), e2.getEndDate())));
long now = System.currentTimeMillis();
split = 0;
for (Event event : this) {
if (event.getEndDate() < now)
split++;
else
break;
}
}
public Iterator<Event> getEventsOfMonth(int year, int month) {
if (split < 0)
sort();
final int[] i = {0};
Calendar minC = Calendar.getInstance();
minC.set(year, month-1, 1, 0, 0);
Calendar maxC = Calendar.getInstance();
maxC.set(year, month, 1, 0, 0);
for (; i[0] < this.size(); i[0]++) {
if (this.get(i[0]).getEndDate() > minC.getTimeInMillis()) {
break;
}
}
return new Iterator<Event>() {
@Override
public boolean hasNext() {
return i[0] < EventList.this.size() && EventList.this.get(i[0]).getEndDate() < maxC.getTimeInMillis();
}
@Override
public Event next() {
if (hasNext()) {
return EventList.this.get(i[0]++);
} else {
return null;
}
}
};
} }
} }

View File

@@ -0,0 +1,20 @@
package de.sebse.fuplanner.tools.ui;
import android.view.View;
import android.widget.TextView;
import de.sebse.fuplanner.R;
public class StringViewHolder extends CustomViewHolder {
public final TextView mString;
public StringViewHolder(View view) {
super(view);
mString = view.findViewById(R.id.string);
}
@Override
public String toString() {
return super.toString() + " '" + mString.getText() + "'";
}
}

View File

@@ -48,13 +48,22 @@
<android.support.v7.widget.AppCompatButton <android.support.v7.widget.AppCompatButton
android:id="@+id/btn_login" android:id="@+id/btn_login"
android:layout_width="fill_parent" android:layout_width="match_parent"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:layout_marginTop="24dp" android:layout_marginTop="24dp"
android:layout_marginBottom="24dp" android:layout_marginBottom="24dp"
android:padding="12dp" android:padding="12dp"
android:text="@string/log_in"/> android:text="@string/log_in"/>
<android.support.v7.widget.AppCompatButton
android:id="@+id/btn_offline"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginTop="24dp"
android:layout_marginBottom="24dp"
android:padding="12dp"
android:visibility="gone"/>
</LinearLayout> </LinearLayout>
</ScrollView> </ScrollView>

View File

@@ -1,14 +1,19 @@
<?xml version="1.0" encoding="utf-8"?> <?xml version="1.0" encoding="utf-8"?>
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android" <android.support.v4.widget.SwipeRefreshLayout
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools" xmlns:tools="http://schemas.android.com/tools"
android:id="@+id/swipe_container"
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="match_parent" android:layout_height="match_parent">
tools:context=".fragments.moddetails.ModDetailAnnounceFragment"> <ExpandableListView
android:id="@+id/list"
<!-- TODO: Update blank fragment layout --> android:name=".fragments.moddetails.ModDetailAnnounceFragment"
<TextView
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="match_parent" android:layout_height="match_parent"
android:text="@string/lorem_ipsum_100" /> android:layout_marginLeft="16dp"
android:layout_marginRight="16dp"
</FrameLayout> app:layoutManager="android.support.v7.widget.LinearLayoutManager"
tools:context=".fragments.moddetails.ModDetailAnnounceFragment"
tools:listitem="@layout/list_all_caption" />
</android.support.v4.widget.SwipeRefreshLayout>

View File

@@ -0,0 +1,15 @@
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout 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"
android:padding="5dip" >
<TextView
android:id="@+id/string"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:typeface="sans"
tools:text="Test this new stuff!" />
</RelativeLayout>

View File

@@ -34,4 +34,5 @@
<!-- TODO: Remove or change this placeholder text --> <!-- TODO: Remove or change this placeholder text -->
<string name="hello_blank_fragment" translatable="false">Hello blank fragment</string> <string name="hello_blank_fragment" translatable="false">Hello blank fragment</string>
<string name="enter_offline_mode">Enter Offline Mode (%1$s)</string>
</resources> </resources>

View File

@@ -18,6 +18,12 @@ allprojects {
jcenter() jcenter()
google() google()
} }
gradle.projectsEvaluated {
tasks.withType(JavaCompile) {
options.compilerArgs << "-Xlint:unchecked" << "-Xlint:deprecation"
}
}
} }
task clean(type: Delete) { task clean(type: Delete) {