Skip to content
Projects
Groups
Snippets
Help
Loading...
Help
Support
Keyboard shortcuts
?
Submit feedback
Contribute to GitLab
Sign in
Toggle navigation
I
InstiApp
Project overview
Project overview
Details
Activity
Releases
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Analytics
Analytics
Repository
Value Stream
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Commits
Open sidebar
RAHUL SHARMA
InstiApp
Commits
67f7e775
Commit
67f7e775
authored
Dec 01, 2018
by
Sajal Narang
Committed by
GitHub
Dec 01, 2018
Browse files
Options
Browse Files
Download
Plain Diff
Merge pull request #248 from wncc/notif
Change notifications to sheet, add animations to recyclerviews
parents
805b324d
39e4261a
Changes
18
Hide whitespace changes
Inline
Side-by-side
Showing
18 changed files
with
122 additions
and
48 deletions
+122
-48
app/src/main/java/app/insti/UpdatableList.java
app/src/main/java/app/insti/UpdatableList.java
+8
-12
app/src/main/java/app/insti/Utils.java
app/src/main/java/app/insti/Utils.java
+3
-0
app/src/main/java/app/insti/activity/MainActivity.java
app/src/main/java/app/insti/activity/MainActivity.java
+6
-6
app/src/main/java/app/insti/adapter/CardAdapter.java
app/src/main/java/app/insti/adapter/CardAdapter.java
+6
-0
app/src/main/java/app/insti/adapter/MessMenuAdapter.java
app/src/main/java/app/insti/adapter/MessMenuAdapter.java
+10
-0
app/src/main/java/app/insti/adapter/NewsAdapter.java
app/src/main/java/app/insti/adapter/NewsAdapter.java
+6
-0
app/src/main/java/app/insti/adapter/NotificationsAdapter.java
...src/main/java/app/insti/adapter/NotificationsAdapter.java
+7
-0
app/src/main/java/app/insti/adapter/PlacementBlogAdapter.java
...src/main/java/app/insti/adapter/PlacementBlogAdapter.java
+6
-0
app/src/main/java/app/insti/adapter/TrainingBlogAdapter.java
app/src/main/java/app/insti/adapter/TrainingBlogAdapter.java
+6
-0
app/src/main/java/app/insti/api/model/Body.java
app/src/main/java/app/insti/api/model/Body.java
+4
-0
app/src/main/java/app/insti/api/model/Event.java
app/src/main/java/app/insti/api/model/Event.java
+4
-0
app/src/main/java/app/insti/api/model/Notification.java
app/src/main/java/app/insti/api/model/Notification.java
+4
-0
app/src/main/java/app/insti/api/model/Role.java
app/src/main/java/app/insti/api/model/Role.java
+4
-0
app/src/main/java/app/insti/api/model/User.java
app/src/main/java/app/insti/api/model/User.java
+4
-0
app/src/main/java/app/insti/fragment/FeedFragment.java
app/src/main/java/app/insti/fragment/FeedFragment.java
+4
-4
app/src/main/java/app/insti/fragment/MessMenuFragment.java
app/src/main/java/app/insti/fragment/MessMenuFragment.java
+10
-4
app/src/main/java/app/insti/fragment/NotificationsFragment.java
...c/main/java/app/insti/fragment/NotificationsFragment.java
+29
-22
app/src/main/java/app/insti/interfaces/CardInterface.java
app/src/main/java/app/insti/interfaces/CardInterface.java
+1
-0
No files found.
app/src/main/java/app/insti/UpdatableList.java
View file @
67f7e775
...
...
@@ -4,25 +4,21 @@ import java.util.ArrayList;
import
java.util.List
;
public
class
UpdatableList
<
T
>
extends
ArrayList
<
T
>
{
private
List
<
T
>
cache
=
new
ArrayList
<>();
public
List
<
T
>
getCache
()
{
return
cache
;
}
public
void
setCache
(
List
<
T
>
mCache
)
{
cache
=
mCache
;
/** Convert a list to updatable list */
public
void
setList
(
List
<
T
>
list
)
{
this
.
clear
();
this
.
addAll
(
list
);
}
/** Update existing or add */
public
void
updateCache
(
T
t
)
{
for
(
int
i
=
0
;
i
<
cache
.
size
();
i
++)
{
T
cachedT
=
cache
.
get
(
i
);
for
(
int
i
=
0
;
i
<
this
.
size
();
i
++)
{
T
cachedT
=
this
.
get
(
i
);
if
(
cachedT
.
equals
(
t
))
{
cache
.
set
(
i
,
t
);
this
.
set
(
i
,
t
);
return
;
}
}
cache
.
add
(
t
);
this
.
add
(
t
);
}
}
app/src/main/java/app/insti/Utils.java
View file @
67f7e775
...
...
@@ -20,6 +20,7 @@ import app.insti.activity.MainActivity;
import
app.insti.api.RetrofitInterface
;
import
app.insti.api.model.Body
;
import
app.insti.api.model.Event
;
import
app.insti.api.model.Notification
;
import
app.insti.api.model.User
;
import
app.insti.fragment.BodyFragment
;
import
app.insti.fragment.EventFragment
;
...
...
@@ -27,6 +28,8 @@ import app.insti.fragment.UserFragment;
public
final
class
Utils
{
public
static
UpdatableList
<
Event
>
eventCache
=
new
UpdatableList
<>();
public
static
UpdatableList
<
Notification
>
notificationCache
=
null
;
private
static
String
sessionId
;
private
static
RetrofitInterface
retrofitInterface
;
public
static
Gson
gson
;
...
...
app/src/main/java/app/insti/activity/MainActivity.java
View file @
67f7e775
...
...
@@ -47,6 +47,7 @@ import java.util.List;
import
app.insti.Constants
;
import
app.insti.R
;
import
app.insti.SessionManager
;
import
app.insti.UpdatableList
;
import
app.insti.Utils
;
import
app.insti.api.EmptyCallback
;
import
app.insti.api.RetrofitInterface
;
...
...
@@ -95,8 +96,6 @@ public class MainActivity extends AppCompatActivity implements NavigationView.On
private
User
currentUser
;
private
BackHandledFragment
selectedFragment
;
private
Menu
menu
;
private
RetrofitInterface
retrofitInterface
;
private
List
<
Notification
>
notifications
=
null
;
public
static
void
hideKeyboard
(
Activity
activity
)
{
InputMethodManager
imm
=
(
InputMethodManager
)
activity
.
getSystemService
(
Activity
.
INPUT_METHOD_SERVICE
);
...
...
@@ -180,7 +179,7 @@ public class MainActivity extends AppCompatActivity implements NavigationView.On
*/
private
void
fetchNotifications
()
{
// Try memory cache
if
(
notifications
!=
null
)
{
if
(
Utils
.
notificationCache
!=
null
)
{
showNotifications
();
return
;
}
...
...
@@ -191,7 +190,8 @@ public class MainActivity extends AppCompatActivity implements NavigationView.On
@Override
public
void
onResponse
(
Call
<
List
<
Notification
>>
call
,
Response
<
List
<
Notification
>>
response
)
{
if
(
response
.
isSuccessful
())
{
notifications
=
response
.
body
();
Utils
.
notificationCache
=
new
UpdatableList
<>();
Utils
.
notificationCache
.
setList
(
response
.
body
());
showNotifications
();
}
}
...
...
@@ -202,7 +202,7 @@ public class MainActivity extends AppCompatActivity implements NavigationView.On
* Show the right notification icon
*/
private
void
showNotifications
()
{
if
(
notifications
!=
null
&&
!
notifications
.
isEmpty
())
{
if
(
Utils
.
notificationCache
!=
null
&&
!
Utils
.
notificationCache
.
isEmpty
())
{
menu
.
findItem
(
R
.
id
.
action_notifications
).
setIcon
(
R
.
drawable
.
baseline_notifications_active_white_24
);
}
else
{
menu
.
findItem
(
R
.
id
.
action_notifications
).
setIcon
(
R
.
drawable
.
ic_notifications_white_24dp
);
...
...
@@ -521,7 +521,7 @@ public class MainActivity extends AppCompatActivity implements NavigationView.On
if
(
id
==
R
.
id
.
action_notifications
)
{
NotificationsFragment
notificationsFragment
=
new
NotificationsFragment
();
updateFragment
(
notificationsFragment
);
notificationsFragment
.
show
(
getSupportFragmentManager
(),
TAG
);
return
true
;
}
return
super
.
onOptionsItemSelected
(
item
);
...
...
app/src/main/java/app/insti/adapter/CardAdapter.java
View file @
67f7e775
...
...
@@ -38,6 +38,7 @@ public abstract class CardAdapter<T extends CardInterface> extends RecyclerView.
public
CardAdapter
(
List
<
T
>
tList
,
Fragment
fragment
)
{
this
.
tList
=
tList
;
mFragment
=
fragment
;
this
.
setHasStableIds
(
true
);
}
@Override
...
...
@@ -114,6 +115,11 @@ public abstract class CardAdapter<T extends CardInterface> extends RecyclerView.
else
return
2
;
}
@Override
public
long
getItemId
(
int
position
)
{
return
tList
.
get
(
position
).
getId
();
}
@Override
public
int
getItemCount
()
{
return
tList
.
size
();
...
...
app/src/main/java/app/insti/adapter/MessMenuAdapter.java
View file @
67f7e775
...
...
@@ -19,6 +19,7 @@ public class MessMenuAdapter extends RecyclerView.Adapter<MessMenuAdapter.ViewHo
public
MessMenuAdapter
(
List
<
MessMenu
>
messMenus
)
{
this
.
messMenus
=
messMenus
;
this
.
setHasStableIds
(
true
);
}
@NonNull
...
...
@@ -42,11 +43,20 @@ public class MessMenuAdapter extends RecyclerView.Adapter<MessMenuAdapter.ViewHo
holder
.
dinner
.
setText
(
messMenu
.
getDinner
());
}
@Override
public
long
getItemId
(
int
position
)
{
return
messMenus
.
get
(
position
).
getMealID
().
hashCode
();
}
@Override
public
int
getItemCount
()
{
return
messMenus
.
size
();
}
public
void
setMenu
(
List
<
MessMenu
>
menus
)
{
messMenus
=
menus
;
}
private
String
generateDayString
(
int
day
)
{
switch
(
day
)
{
case
1
:
...
...
app/src/main/java/app/insti/adapter/NewsAdapter.java
View file @
67f7e775
...
...
@@ -35,6 +35,7 @@ public class NewsAdapter extends RecyclerView.Adapter<RecyclerView.ViewHolder> i
public
NewsAdapter
(
List
<
NewsArticle
>
newsArticles
,
ItemClickListener
itemClickListener
)
{
this
.
newsArticles
=
newsArticles
;
this
.
itemClickListener
=
itemClickListener
;
this
.
setHasStableIds
(
true
);
}
@Override
...
...
@@ -108,6 +109,11 @@ public class NewsAdapter extends RecyclerView.Adapter<RecyclerView.ViewHolder> i
return
newsArticles
.
size
()
>
position
?
VIEW_ITEM
:
VIEW_PROG
;
}
@Override
public
long
getItemId
(
int
position
)
{
return
newsArticles
.
get
(
position
).
getArticleID
().
hashCode
();
}
@Override
public
int
getItemCount
()
{
return
NewsFragment
.
showLoader
?
(
newsArticles
.
size
()
+
1
)
:
newsArticles
.
size
();
...
...
app/src/main/java/app/insti/adapter/NotificationsAdapter.java
View file @
67f7e775
...
...
@@ -15,12 +15,16 @@ import app.insti.api.model.Event;
import
app.insti.api.model.Notification
;
import
app.insti.api.model.PlacementBlogPost
;
import
app.insti.fragment.NewsFragment
;
import
app.insti.fragment.NotificationsFragment
;
import
app.insti.fragment.PlacementBlogFragment
;
import
app.insti.fragment.TrainingBlogFragment
;
public
class
NotificationsAdapter
extends
CardAdapter
<
Notification
>
{
private
NotificationsFragment
notificationsFragment
;
public
NotificationsAdapter
(
List
<
Notification
>
notifications
,
Fragment
fragment
)
{
super
(
notifications
,
fragment
);
notificationsFragment
=
(
NotificationsFragment
)
fragment
;
}
@Override
...
...
@@ -30,6 +34,9 @@ public class NotificationsAdapter extends CardAdapter<Notification> {
String
sessId
=
Utils
.
getSessionIDHeader
();
retrofitInterface
.
markNotificationRead
(
sessId
,
notification
.
getNotificationId
().
toString
()).
enqueue
(
new
EmptyCallback
<
Void
>());
/* Close the bottom sheet */
notificationsFragment
.
dismiss
();
/* Open event */
if
(
notification
.
isEvent
())
{
Gson
gson
=
new
Gson
();
...
...
app/src/main/java/app/insti/adapter/PlacementBlogAdapter.java
View file @
67f7e775
...
...
@@ -32,6 +32,7 @@ public class PlacementBlogAdapter extends RecyclerView.Adapter<RecyclerView.View
public
PlacementBlogAdapter
(
List
<
PlacementBlogPost
>
posts
,
ItemClickListener
itemClickListener
)
{
this
.
posts
=
posts
;
this
.
itemClickListener
=
itemClickListener
;
this
.
setHasStableIds
(
true
);
}
public
List
<
PlacementBlogPost
>
getPosts
()
{
...
...
@@ -100,6 +101,11 @@ public class PlacementBlogAdapter extends RecyclerView.Adapter<RecyclerView.View
}
}
@Override
public
long
getItemId
(
int
position
)
{
return
posts
.
get
(
position
).
getPostID
().
hashCode
();
}
public
static
class
ProgressViewHolder
extends
RecyclerView
.
ViewHolder
{
public
ProgressBar
progressBar
;
...
...
app/src/main/java/app/insti/adapter/TrainingBlogAdapter.java
View file @
67f7e775
...
...
@@ -34,6 +34,7 @@ public class TrainingBlogAdapter extends RecyclerView.Adapter<RecyclerView.ViewH
public
TrainingBlogAdapter
(
List
<
TrainingBlogPost
>
posts
,
ItemClickListener
itemClickListener
)
{
this
.
posts
=
posts
;
this
.
itemClickListener
=
itemClickListener
;
this
.
setHasStableIds
(
true
);
}
public
List
<
TrainingBlogPost
>
getPosts
()
{
...
...
@@ -96,6 +97,11 @@ public class TrainingBlogAdapter extends RecyclerView.Adapter<RecyclerView.ViewH
return
posts
.
size
()
>
position
?
VIEW_ITEM
:
VIEW_PROG
;
}
@Override
public
long
getItemId
(
int
position
)
{
return
posts
.
get
(
position
).
getPostID
().
hashCode
();
}
@Override
public
int
getItemCount
()
{
return
TrainingBlogFragment
.
showLoader
?
(
posts
.
size
()
+
1
)
:
posts
.
size
();
...
...
app/src/main/java/app/insti/api/model/Body.java
View file @
67f7e775
...
...
@@ -184,6 +184,10 @@ public class Body implements CardInterface {
this
.
bodyRoles
=
bodyRoles
;
}
public
long
getId
()
{
return
getBodyID
().
hashCode
();
}
public
String
getTitle
()
{
return
getBodyName
();
}
...
...
app/src/main/java/app/insti/api/model/Event.java
View file @
67f7e775
...
...
@@ -243,6 +243,10 @@ public class Event implements CardInterface {
return
Objects
.
hash
(
eventID
);
}
public
long
getId
()
{
return
hashCode
();
}
public
String
getTitle
()
{
return
getEventName
();
}
...
...
app/src/main/java/app/insti/api/model/Notification.java
View file @
67f7e775
...
...
@@ -79,6 +79,10 @@ public class Notification implements CardInterface {
this
.
notificationActor
=
notificationActor
;
}
public
long
getId
()
{
return
getNotificationId
().
hashCode
();
}
public
String
getTitle
()
{
if
(
isEvent
())
{
return
getEvent
().
getEventName
();
...
...
app/src/main/java/app/insti/api/model/Role.java
View file @
67f7e775
...
...
@@ -121,6 +121,10 @@ public class Role implements CardInterface {
this
.
roleUsersDetail
=
roleUsersDetail
;
}
public
long
getId
()
{
return
getRoleID
().
hashCode
();
}
public
String
getTitle
()
{
return
getRoleBodyDetails
().
getBodyName
();
}
...
...
app/src/main/java/app/insti/api/model/User.java
View file @
67f7e775
...
...
@@ -238,6 +238,10 @@ public class User implements CardInterface {
return
new
Gson
().
toJson
(
this
);
}
public
long
getId
()
{
return
getUserID
().
hashCode
();
}
public
String
getTitle
()
{
return
getUserName
();
}
...
...
app/src/main/java/app/insti/fragment/FeedFragment.java
View file @
67f7e775
...
...
@@ -74,10 +74,10 @@ public class FeedFragment extends BaseFragment {
fab
=
getView
().
findViewById
(
R
.
id
.
fab
);
// Initialize the feed
if
(
Utils
.
eventCache
.
getCache
()
==
null
||
Utils
.
eventCache
.
getCache
().
size
()
==
0
)
{
if
(
Utils
.
eventCache
==
null
||
Utils
.
eventCache
.
isEmpty
()
)
{
updateFeed
();
}
else
{
displayEvents
(
Utils
.
eventCache
.
getCache
()
);
displayEvents
(
Utils
.
eventCache
);
}
}
...
...
@@ -107,8 +107,8 @@ public class FeedFragment extends BaseFragment {
@Override
public
void
onResponse
(
Call
<
NewsFeedResponse
>
call
,
Response
<
NewsFeedResponse
>
response
)
{
if
(
response
.
isSuccessful
())
{
Utils
.
eventCache
.
set
Cache
(
response
.
body
().
getEvents
());
displayEvents
(
Utils
.
eventCache
.
getCache
()
);
Utils
.
eventCache
.
set
List
(
response
.
body
().
getEvents
());
displayEvents
(
Utils
.
eventCache
);
}
//Server Error
feedSwipeRefreshLayout
.
setRefreshing
(
false
);
...
...
app/src/main/java/app/insti/fragment/MessMenuFragment.java
View file @
67f7e775
...
...
@@ -37,6 +37,7 @@ import retrofit2.Response;
*/
public
class
MessMenuFragment
extends
BaseFragment
{
private
MessMenuAdapter
messMenuAdapter
;
private
RecyclerView
messMenuRecyclerView
;
private
SwipeRefreshLayout
messMenuSwipeRefreshLayout
;
private
Spinner
hostelSpinner
;
...
...
@@ -164,14 +165,19 @@ public class MessMenuFragment extends BaseFragment {
}
}
final
MessMenuAdapter
messMenuAdapter
=
new
MessMenuAdapter
(
sortedMenus
);
getActivityBuffer
().
safely
(
new
ActivityBuffer
.
IRunnable
()
{
@Override
public
void
run
(
Activity
pActivity
)
{
try
{
messMenuRecyclerView
=
getActivity
().
findViewById
(
R
.
id
.
mess_menu_recycler_view
);
messMenuRecyclerView
.
setAdapter
(
messMenuAdapter
);
messMenuRecyclerView
.
setLayoutManager
(
new
LinearLayoutManager
(
getContext
()));
if
(
messMenuAdapter
==
null
)
{
messMenuAdapter
=
new
MessMenuAdapter
(
sortedMenus
);
messMenuRecyclerView
=
getActivity
().
findViewById
(
R
.
id
.
mess_menu_recycler_view
);
messMenuRecyclerView
.
setAdapter
(
messMenuAdapter
);
messMenuRecyclerView
.
setLayoutManager
(
new
LinearLayoutManager
(
getContext
()));
}
else
{
messMenuAdapter
.
setMenu
(
sortedMenus
);
messMenuAdapter
.
notifyDataSetChanged
();
}
}
catch
(
NullPointerException
e
)
{
e
.
printStackTrace
();
}
...
...
app/src/main/java/app/insti/fragment/NotificationsFragment.java
View file @
67f7e775
...
...
@@ -2,10 +2,10 @@ package app.insti.fragment;
import
android.os.Bundle
;
import
android.support.design.widget.BottomSheetDialogFragment
;
import
android.support.v4.app.Fragment
;
import
android.support.v7.widget.LinearLayoutManager
;
import
android.support.v7.widget.RecyclerView
;
import
android.support.v7.widget.Toolbar
;
import
android.view.LayoutInflater
;
import
android.view.View
;
import
android.view.ViewGroup
;
...
...
@@ -13,22 +13,22 @@ import android.view.ViewGroup;
import
java.util.List
;
import
app.insti.R
;
import
app.insti.UpdatableList
;
import
app.insti.Utils
;
import
app.insti.adapter.NotificationsAdapter
;
import
app.insti.api.EmptyCallback
;
import
app.insti.api.RetrofitInterface
;
import
app.insti.api.model.Notification
;
import
retrofit2.Call
;
import
retrofit2.Callback
;
import
retrofit2.Response
;
/**
* A simple {@link Fragment} subclass.
*/
public
class
NotificationsFragment
extends
B
ase
Fragment
{
public
class
NotificationsFragment
extends
B
ottomSheetDialog
Fragment
{
RecyclerView
notificationsRecyclerView
;
List
<
Notification
>
notifications
;
private
RecyclerView
notificationsRecyclerView
;
private
NotificationsAdapter
notificationsAdapter
=
null
;
public
NotificationsFragment
()
{
// Required empty public constructor
...
...
@@ -46,35 +46,42 @@ public class NotificationsFragment extends BaseFragment {
public
void
onStart
()
{
super
.
onStart
();
Toolbar
toolbar
=
getActivity
().
findViewById
(
R
.
id
.
toolbar
);
toolbar
.
setTitle
(
"Notifications"
);
/* Show cached notifications */
if
(
Utils
.
notificationCache
!=
null
)
{
showNotifications
(
Utils
.
notificationCache
);
}
else
{
Utils
.
notificationCache
=
new
UpdatableList
<>();
}
/* Update notifications */
RetrofitInterface
retrofitInterface
=
Utils
.
getRetrofitInterface
();
retrofitInterface
.
getNotifications
(
Utils
.
getSessionIDHeader
()).
enqueue
(
new
Callback
<
List
<
Notification
>>()
{
retrofitInterface
.
getNotifications
(
Utils
.
getSessionIDHeader
()).
enqueue
(
new
Empty
Callback
<
List
<
Notification
>>()
{
@Override
public
void
onResponse
(
Call
<
List
<
Notification
>>
call
,
Response
<
List
<
Notification
>>
response
)
{
if
(
response
.
isSuccessful
())
{
notifications
=
response
.
body
(
);
showNotifications
(
notifications
);
Utils
.
notificationCache
.
setList
(
response
.
body
()
);
showNotifications
(
Utils
.
notificationCache
);
}
}
@Override
public
void
onFailure
(
Call
<
List
<
Notification
>>
call
,
Throwable
t
)
{
}
});
}
private
void
showNotifications
(
final
List
<
Notification
>
notifications
)
{
/* Check if activity is done with */
if
(
getActivity
()
==
null
)
return
;
if
(
getActivity
()
==
null
||
getView
()
==
null
)
return
;
/* Hide loader */
getActivity
().
findViewById
(
R
.
id
.
loadingPanel
).
setVisibility
(
View
.
GONE
);
NotificationsAdapter
notificationsAdapter
=
new
NotificationsAdapter
(
notifications
,
this
);
notificationsRecyclerView
=
(
RecyclerView
)
getActivity
().
findViewById
(
R
.
id
.
notifications_recycler_view
);
notificationsRecyclerView
.
setAdapter
(
notificationsAdapter
);
notificationsRecyclerView
.
setLayoutManager
(
new
LinearLayoutManager
(
getContext
()));
getView
().
findViewById
(
R
.
id
.
loadingPanel
).
setVisibility
(
View
.
GONE
);
/* Initialize */
if
(
notificationsAdapter
==
null
)
{
notificationsAdapter
=
new
NotificationsAdapter
(
notifications
,
this
);
notificationsRecyclerView
=
(
RecyclerView
)
getView
().
findViewById
(
R
.
id
.
notifications_recycler_view
);
notificationsRecyclerView
.
setAdapter
(
notificationsAdapter
);
notificationsRecyclerView
.
setLayoutManager
(
new
LinearLayoutManager
(
getContext
()));
}
else
{
notificationsAdapter
.
setList
(
notifications
);
notificationsAdapter
.
notifyDataSetChanged
();
}
}
}
app/src/main/java/app/insti/interfaces/CardInterface.java
View file @
67f7e775
package
app.insti.interfaces
;
public
interface
CardInterface
{
long
getId
();
String
getTitle
();
String
getSubtitle
();
String
getAvatarUrl
();
...
...
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment