Commit 337c18f6 authored by Roger Barton's avatar Roger Barton
Browse files

Fixed page viewer bug

parent 85f7bcc9
image: registry.gitlab.com/showcheap/android-ci:react-native
variables:
GIT_SUBMODULE_STRATEGY: recursive
before_script:
- git submodule sync --recursive
- git submodule update --init --recursive
- export GRADLE_USER_HOME=`pwd`/.gradle
- chmod +x ./gradlew
- npm install
cache:
key: "$CI_COMMIT_REF_NAME"
paths:
- .gradle/
stages:
- test
- build
test:
stage: test
script:
- ./gradlew check
build:
stage: build
script:
- ./gradlew assembleRelease
artifacts:
expire_in: 1 week
paths:
- app/build/outputs/
...@@ -27,13 +27,14 @@ dependencies { ...@@ -27,13 +27,14 @@ dependencies {
implementation fileTree(dir: 'libs', include: ['*.jar']) implementation fileTree(dir: 'libs', include: ['*.jar'])
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.2'
implementation 'com.android.support:support-v4:27.1.1' implementation 'com.android.support:support-v4:27.1.1'
//implementation 'com.mcxiaoke.volley:library:1.0.19' //implementation 'com.mcxiaoke.volley:library:1.0.19'
implementation project(path: ':volley') implementation project(path: ':volley')
implementation 'com.google.zxing:core:3.2.1' implementation 'com.google.zxing:core:3.2.1'
implementation 'com.journeyapps:zxing-android-embedded:3.2.0@aar' implementation 'com.journeyapps:zxing-android-embedded:3.2.0@aar'
implementation 'com.google.android.gms:play-services-vision:15.0.2' implementation 'com.google.android.gms:play-services-vision:15.0.2'
implementation 'com.google.code.gson:gson:2.8.2'
testImplementation 'junit:junit:4.12' testImplementation 'junit:junit:4.12'
androidTestImplementation 'com.android.support.test:runner:1.0.2' androidTestImplementation 'com.android.support.test:runner:1.0.2'
......
...@@ -17,7 +17,6 @@ import com.google.zxing.common.BitMatrix; ...@@ -17,7 +17,6 @@ import com.google.zxing.common.BitMatrix;
import com.journeyapps.barcodescanner.BarcodeEncoder; import com.journeyapps.barcodescanner.BarcodeEncoder;
import java.lang.reflect.Field; import java.lang.reflect.Field;
import java.nio.file.attribute.UserDefinedFileAttributeView;
import ch.amiv.android_app.R; import ch.amiv.android_app.R;
import ch.amiv.android_app.core.UserInfo; import ch.amiv.android_app.core.UserInfo;
......
package ch.amiv.android_app.core; package ch.amiv.android_app.core;
import android.app.Activity;
import android.content.Context;
import android.os.Bundle; import android.os.Bundle;
import android.os.Handler; import android.os.Handler;
import android.support.annotation.NonNull; import android.support.annotation.NonNull;
...@@ -38,7 +40,29 @@ public class ListFragment extends Fragment { ...@@ -38,7 +40,29 @@ public class ListFragment extends Fragment {
private Requests.OnDataReceivedCallback cancelRefreshCallback = new Requests.OnDataReceivedCallback() { private Requests.OnDataReceivedCallback cancelRefreshCallback = new Requests.OnDataReceivedCallback() {
@Override @Override
public void OnDataReceived() { public void OnDataReceived() {
swipeRefreshLayout.setRefreshing(false); SetRefreshUI(false);
}
};
public Requests.OnDataReceivedCallback onEventsListUpdatedCallback = new Requests.OnDataReceivedCallback() {
@Override
public void OnDataReceived() {
Requests.FetchEventSignups(recyclerView.getContext(), onSignupsUpdatedCallback, null, "");
RefreshList(true);
}
};
public Requests.OnDataReceivedCallback onJobsListUpdatedCallback = new Requests.OnDataReceivedCallback() {
@Override
public void OnDataReceived() {
RefreshList(true);
}
};
private Requests.OnDataReceivedCallback onSignupsUpdatedCallback = new Requests.OnDataReceivedCallback() {
@Override
public void OnDataReceived() {
RefreshList(false);
} }
}; };
...@@ -66,66 +90,57 @@ public class ListFragment extends Fragment { ...@@ -66,66 +90,57 @@ public class ListFragment extends Fragment {
@Override @Override
public void onViewCreated(@NonNull View view, @Nullable Bundle savedInstanceState) { public void onViewCreated(@NonNull View view, @Nullable Bundle savedInstanceState) {
recyclerView = getView().findViewById(R.id.recyclerView);
super.onViewCreated(view, savedInstanceState); super.onViewCreated(view, savedInstanceState);
swipeRefreshLayout = getView().findViewById(R.id.swipeRefresh); swipeRefreshLayout = getView().findViewById(R.id.swipeRefresh);
swipeRefreshLayout.setOnRefreshListener(new SwipeRefreshLayout.OnRefreshListener() { swipeRefreshLayout.setOnRefreshListener(new SwipeRefreshLayout.OnRefreshListener() {
@Override @Override
public void onRefresh() { public void onRefresh() {
if(!(getActivity() instanceof MainActivity)) if(!(recyclerView.getContext() instanceof MainActivity))
return; return;
if(pagePosition == PageType.EVENTS) if(pagePosition == PageType.EVENTS)
Requests.FetchEventList(getContext(), ((MainActivity)getActivity()).onEventsListUpdatedCallback, cancelRefreshCallback, ""); Requests.FetchEventList(recyclerView.getContext(), onEventsListUpdatedCallback, cancelRefreshCallback, "");
else if (pagePosition == PageType.JOBS) else if (pagePosition == PageType.JOBS)
Requests.FetchJobList(getContext(), ((MainActivity)getActivity()).onJobsListUpdatedCallback, cancelRefreshCallback, ""); Requests.FetchJobList(recyclerView.getContext(), onJobsListUpdatedCallback, cancelRefreshCallback, "");
} }
}); });
//refresh on activity start //refresh on activity start
swipeRefreshLayout.post(new Runnable() { swipeRefreshLayout.post(new Runnable() {
@Override @Override
public void run() { public void run() {
if(!(getActivity() instanceof MainActivity)) if(!(recyclerView.getContext() instanceof MainActivity))
return; return;
if(pagePosition == PageType.EVENTS) { if(pagePosition == PageType.EVENTS) {
swipeRefreshLayout.setRefreshing(true); SetRefreshUI(true);
Requests.FetchEventList(getContext(), ((MainActivity)getActivity()).onEventsListUpdatedCallback, cancelRefreshCallback, ""); Requests.FetchEventList(recyclerView.getContext(), onEventsListUpdatedCallback, cancelRefreshCallback, "");
} }
else if(pagePosition == PageType.JOBS){ else if(pagePosition == PageType.JOBS){
swipeRefreshLayout.setRefreshing(true); SetRefreshUI(true);
Requests.FetchJobList(getContext(), ((MainActivity)getActivity()).onJobsListUpdatedCallback, cancelRefreshCallback, ""); Requests.FetchJobList(recyclerView.getContext(), onJobsListUpdatedCallback, cancelRefreshCallback, "");
} }
} }
}); });
//Disable the refresh animation after a timeout
Handler handler = new Handler();
handler.postDelayed(new Runnable() {
@Override
public void run() {
swipeRefreshLayout.setRefreshing(false);
}
}, 1000*15);
recyclerView = getView().findViewById(R.id.recyclerView);
// use this setting to improve performance if you know that changes // use this setting to improve performance if you know that changes
// in content do not change the layout size of the RecyclerView // in content do not change the layout size of the RecyclerView
recyclerView.setHasFixedSize(true); recyclerView.setHasFixedSize(true);
// use a linear layout manager // use a linear layout manager
recyclerLayoutAdapter = new LinearLayoutManager(getContext()); recyclerLayoutAdapter = new LinearLayoutManager(recyclerView.getContext());
recyclerView.setLayoutManager(recyclerLayoutAdapter); recyclerView.setLayoutManager(recyclerLayoutAdapter);
// specify an adapter (see also next example) // specify an adapter (see also next example)
if(pagePosition == PageType.EVENTS) if(pagePosition == PageType.EVENTS)
recyclerAdapter = new EventsListAdapter(getActivity()); recyclerAdapter = new EventsListAdapter(((Activity) recyclerView.getContext()));
else if (pagePosition == PageType.JOBS) else if (pagePosition == PageType.JOBS)
recyclerAdapter = new JobListAdapter(getActivity()); recyclerAdapter = new JobListAdapter((Activity) recyclerView.getContext());
if(recyclerAdapter != null) { if(recyclerAdapter != null) {
recyclerView.setLayoutAnimation(AnimationUtils.loadLayoutAnimation(getContext(), R.anim.layout_anim_falldown)); recyclerView.setLayoutAnimation(AnimationUtils.loadLayoutAnimation(recyclerView.getContext(), R.anim.layout_anim_falldown));
recyclerView.setAdapter(recyclerAdapter); recyclerView.setAdapter(recyclerAdapter);
AnimateList(null); AnimateList(null);
...@@ -150,7 +165,7 @@ public class ListFragment extends Fragment { ...@@ -150,7 +165,7 @@ public class ListFragment extends Fragment {
if(recyclerAdapter == null) if(recyclerAdapter == null)
return; return;
swipeRefreshLayout.setRefreshing(false); SetRefreshUI(false);
recyclerAdapter.RefreshData(); recyclerAdapter.RefreshData();
if(animate) if(animate)
AnimateList(null); AnimateList(null);
...@@ -175,6 +190,22 @@ public class ListFragment extends Fragment { ...@@ -175,6 +190,22 @@ public class ListFragment extends Fragment {
recyclerAdapter.RefreshData(); recyclerAdapter.RefreshData();
} }
private void SetRefreshUI(boolean isRefreshing){
//Disable the refresh animation after a timeout
swipeRefreshLayout.setRefreshing(isRefreshing);
if(!isRefreshing)
return;
Handler handler = new Handler();
handler.postDelayed(new Runnable() {
@Override
public void run() {
swipeRefreshLayout.setRefreshing(false);
}
}, 1000*15);
}
/** /**
* Animation is stored in an xml in the res/anim folder, it is applied to the views in xml, this just triggers the anim * Animation is stored in an xml in the res/anim folder, it is applied to the views in xml, this just triggers the anim
* @param view Used to allow UI elems to call this, pass null otherwise * @param view Used to allow UI elems to call this, pass null otherwise
...@@ -184,7 +215,7 @@ public class ListFragment extends Fragment { ...@@ -184,7 +215,7 @@ public class ListFragment extends Fragment {
if(recyclerAdapter == null) if(recyclerAdapter == null)
return; return;
getActivity().runOnUiThread(new Runnable() { recyclerView.post(new Runnable() {
public void run() { public void run() {
recyclerView.invalidate(); recyclerView.invalidate();
recyclerView.scheduleLayoutAnimation(); recyclerView.scheduleLayoutAnimation();
......
...@@ -7,7 +7,7 @@ import android.support.design.widget.BottomNavigationView; ...@@ -7,7 +7,7 @@ import android.support.design.widget.BottomNavigationView;
import android.support.design.widget.NavigationView; import android.support.design.widget.NavigationView;
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.FragmentPagerAdapter; import android.support.v4.app.FragmentStatePagerAdapter;
import android.support.v4.view.GravityCompat; import android.support.v4.view.GravityCompat;
import android.support.v4.view.ViewPager; import android.support.v4.view.ViewPager;
import android.support.v4.widget.DrawerLayout; import android.support.v4.widget.DrawerLayout;
...@@ -21,11 +21,14 @@ import android.view.View; ...@@ -21,11 +21,14 @@ import android.view.View;
import android.view.ViewGroup; import android.view.ViewGroup;
import android.widget.TextView; import android.widget.TextView;
import java.util.Vector;
import ch.amiv.android_app.R; import ch.amiv.android_app.R;
import ch.amiv.android_app.checkin.BarcodeIdActivity; import ch.amiv.android_app.checkin.BarcodeIdActivity;
import ch.amiv.android_app.events.EventDetailActivity; import ch.amiv.android_app.events.EventDetailActivity;
import ch.amiv.android_app.events.Events; import ch.amiv.android_app.events.Events;
import ch.amiv.android_app.jobs.JobDetailActivity; import ch.amiv.android_app.jobs.JobDetailActivity;
import ch.amiv.android_app.util.PersistentStorage;
/** /**
* This is the first screen. features: drawer, pageview with bottom navigation bar and within each page a list view. * This is the first screen. features: drawer, pageview with bottom navigation bar and within each page a list view.
...@@ -42,28 +45,6 @@ public class MainActivity extends AppCompatActivity implements NavigationView.On ...@@ -42,28 +45,6 @@ public class MainActivity extends AppCompatActivity implements NavigationView.On
private ViewPager viewPager; private ViewPager viewPager;
private PagerAdapter pagerAdapter; private PagerAdapter pagerAdapter;
public Requests.OnDataReceivedCallback onEventsListUpdatedCallback = new Requests.OnDataReceivedCallback() {
@Override
public void OnDataReceived() {
Requests.FetchEventSignups(getApplicationContext(), onSignupsUpdatedCallback, null, "");
pagerAdapter.RefreshPage(ListFragment.PageType.EVENTS, true);
}
};
public Requests.OnDataReceivedCallback onJobsListUpdatedCallback = new Requests.OnDataReceivedCallback() {
@Override
public void OnDataReceived() {
pagerAdapter.RefreshPage(ListFragment.PageType.JOBS, true);
}
};
private Requests.OnDataReceivedCallback onSignupsUpdatedCallback = new Requests.OnDataReceivedCallback() {
@Override
public void OnDataReceived() {
pagerAdapter.RefreshPage(ListFragment.PageType.EVENTS, false);
}
};
/** /**
* Handle what should happen when the bottom nav buttons are pressed, will change the page of the viewpager * Handle what should happen when the bottom nav buttons are pressed, will change the page of the viewpager
*/ */
...@@ -166,14 +147,6 @@ public class MainActivity extends AppCompatActivity implements NavigationView.On ...@@ -166,14 +147,6 @@ public class MainActivity extends AppCompatActivity implements NavigationView.On
} }
//endregion //endregion
@Override
protected void onPostResume() {
super.onPostResume();
if(pagerAdapter != null)
pagerAdapter.notifyDataSetChanged();
}
//region - ====Login==== //region - ====Login====
/** /**
* Log the user out, delete token. Will not log the user out of the device with the API as this is used with other amiv services as well * Log the user out, delete token. Will not log the user out of the device with the API as this is used with other amiv services as well
...@@ -364,29 +337,41 @@ public class MainActivity extends AppCompatActivity implements NavigationView.On ...@@ -364,29 +337,41 @@ public class MainActivity extends AppCompatActivity implements NavigationView.On
//region =====START OF PAGEVIEW============== //region =====START OF PAGEVIEW==============
protected ListFragment[] pages = new ListFragment[ListFragment.PageType.COUNT]; protected Vector<ListFragment> pages = new Vector<>(ListFragment.PageType.COUNT);
/** /**
* This will handle changing between the pages * This will handle changing between the pages
*/ */
public class PagerAdapter extends FragmentPagerAdapter { public class PagerAdapter extends FragmentStatePagerAdapter {
int currentPosition; int currentPosition;
public PagerAdapter(FragmentManager fm) { public PagerAdapter(FragmentManager fm) {
super(fm); super(fm);
for(int i = 0; i< ListFragment.PageType.COUNT; i++) for(int i = 0; i< ListFragment.PageType.COUNT; i++)
pages[i] = ListFragment.NewInstance(i); pages.add(ListFragment.NewInstance(i));
notifyDataSetChanged();
} }
@Override @Override
public int getCount() { public int getCount() {
return ListFragment.PageType.COUNT; return pages.size();
} }
@Override @Override
public Fragment getItem(int position) { public Fragment getItem(int position) {
if(pages[position] == null) return pages.get(position);
pages[position] = ListFragment.NewInstance(position); }
return pages[position];
@Override
public int getItemPosition(Object object) {
ListFragment fragment = (ListFragment) object;
int position = pages.indexOf(fragment);
if (position >= 0) {
return position;
} else {
return POSITION_NONE;
}
} }
@Override @Override
...@@ -395,10 +380,15 @@ public class MainActivity extends AppCompatActivity implements NavigationView.On ...@@ -395,10 +380,15 @@ public class MainActivity extends AppCompatActivity implements NavigationView.On
super.setPrimaryItem(container, position, object); super.setPrimaryItem(container, position, object);
} }
/*
@Override
public void destroyItem(ViewGroup container, int position, Object object) {
}*/
public void RefreshPage(int position, boolean animate){ public void RefreshPage(int position, boolean animate){
if(pages[position] != null) if(pages.get(position) != null)
pages[position].RefreshList(animate); pages.get(position).RefreshList(animate);
else else
Log.e("pageview", "RefreshPage(), Page does not exist will not refresh: " + position); Log.e("pageview", "RefreshPage(), Page does not exist will not refresh: " + position);
} }
...@@ -439,4 +429,3 @@ public class MainActivity extends AppCompatActivity implements NavigationView.On ...@@ -439,4 +429,3 @@ public class MainActivity extends AppCompatActivity implements NavigationView.On
} }
//endregion =====END OF PAGEVIEW================ //endregion =====END OF PAGEVIEW================
} }
\ No newline at end of file
package ch.amiv.android_app.core; package ch.amiv.android_app.core;
import android.annotation.TargetApi;
import android.content.Context; import android.content.Context;
import android.graphics.Bitmap; import android.graphics.Bitmap;
import android.net.ConnectivityManager; import android.net.ConnectivityManager;
...@@ -93,7 +94,6 @@ public final class Requests { ...@@ -93,7 +94,6 @@ public final class Requests {
final JSONObject json = new JSONObject(new String(response.data)); final JSONObject json = new JSONObject(new String(response.data));
//Update events on main thread //Update events on main thread
if(callback != null) {
Runnable runnable = new Runnable() { Runnable runnable = new Runnable() {
@Override @Override
public void run() { public void run() {
...@@ -102,14 +102,15 @@ public final class Requests { ...@@ -102,14 +102,15 @@ public final class Requests {
Events.UpdateEventInfos(json.getJSONArray("_items")); Events.UpdateEventInfos(json.getJSONArray("_items"));
else else
Events.UpdateSingleEvent(json, eventId); Events.UpdateSingleEvent(json, eventId);
if(callback != null)
callback.OnDataReceived();
} catch (JSONException e) { } catch (JSONException e) {
RunCallback(errorCallback);
e.printStackTrace(); e.printStackTrace();
} }
callback.OnDataReceived();
} }
}; };
callbackHandler.post(runnable); callbackHandler.post(runnable);
}
Log.e("request", new JSONObject(new String(response.data)).toString()); Log.e("request", new JSONObject(new String(response.data)).toString());
} catch (JSONException e) { } catch (JSONException e) {
...@@ -257,8 +258,7 @@ public final class Requests { ...@@ -257,8 +258,7 @@ public final class Requests {
try { try {
final JSONObject json = new JSONObject(new String(response.data)); final JSONObject json = new JSONObject(new String(response.data));
//Update events on main thread //Update on main thread
if(callback != null) {
Runnable runnable = new Runnable() { Runnable runnable = new Runnable() {
@Override @Override
public void run() { public void run() {
...@@ -267,14 +267,15 @@ public final class Requests { ...@@ -267,14 +267,15 @@ public final class Requests {
Jobs.UpdateJobInfos(json.getJSONArray("_items")); Jobs.UpdateJobInfos(json.getJSONArray("_items"));
else else
Jobs.UpdateSingleJob(json, jobId); Jobs.UpdateSingleJob(json, jobId);
if(callback != null)
callback.OnDataReceived();
} catch (JSONException e) { } catch (JSONException e) {
RunCallback(errorCallback);
e.printStackTrace(); e.printStackTrace();
} }
callback.OnDataReceived();
} }
}; };
callbackHandler.post(runnable); callbackHandler.post(runnable);
}
Log.e("request", new JSONObject(new String(response.data)).toString()); Log.e("request", new JSONObject(new String(response.data)).toString());
} catch (JSONException e) { } catch (JSONException e) {
...@@ -492,6 +493,9 @@ public final class Requests { ...@@ -492,6 +493,9 @@ public final class Requests {
*/ */
public static boolean CheckConnection(Context context) public static boolean CheckConnection(Context context)
{ {
if(context == null)//If we cannot check the connection then fallback to no internet
return false;
ConnectivityManager cm = (ConnectivityManager)context.getSystemService(Context.CONNECTIVITY_SERVICE); ConnectivityManager cm = (ConnectivityManager)context.getSystemService(Context.CONNECTIVITY_SERVICE);
NetworkInfo activeNetwork = cm.getActiveNetworkInfo(); NetworkInfo activeNetwork = cm.getActiveNetworkInfo();
......
...@@ -68,7 +68,7 @@ ...@@ -68,7 +68,7 @@
<string name="no_internet">Kein Internet</string> <string name="no_internet">Kein Internet</string>
<string name="requires_internet">Benötigt Internet</string> <string name="requires_internet">Benötigt Internet</string>
<string name="snack_fill_all_fields">Bitte füllen sie alle Felder ein</string> <string name="snack_fill_fields">Bitte füllen sie Felder ein</string>