implement views for streams

This commit is contained in:
Felix 2017-03-25 03:17:12 +01:00
parent 8d55700e0e
commit cfd6653c29
9 changed files with 331 additions and 88 deletions

View file

@ -23,6 +23,8 @@ import com.bumptech.glide.Glide;
import de.nicidienase.chaosflix.entities.recording.Conference;
import de.nicidienase.chaosflix.entities.recording.Event;
import de.nicidienase.chaosflix.entities.streaming.LiveConference;
import de.nicidienase.chaosflix.entities.streaming.Room;
/*
* A CardPresenter is used to generate Views and bind Objects to them on demand.
@ -95,6 +97,24 @@ public class CardPresenter extends Presenter {
.into(cardView.getMainImageView());
}
}
if(item instanceof LiveConference){
LiveConference con = (LiveConference) item;
cardView.setTitleText(con.getConference());
cardView.setMainImage(mDefaultCardImage);
cardView.setContentText(con.getDescription());
}
if(item instanceof Room){
Room room = (Room) item;
cardView.setTitleText(room.getDisplay());
cardView.setContentText(room.getShedulename());
if(room.getThumb() != null){
Glide.with(viewHolder.view.getContext())
.load(room.getThumb())
.fitCenter()
.error(mDefaultCardImage)
.into(cardView.getMainImageView());
}
}
}
@Override

View file

@ -4,6 +4,7 @@ import android.support.v17.leanback.widget.AbstractDetailsDescriptionPresenter;
import android.text.TextUtils;
import de.nicidienase.chaosflix.entities.recording.Event;
import de.nicidienase.chaosflix.entities.streaming.Room;
/**
* Created by felix on 18.03.17.
@ -12,18 +13,24 @@ import de.nicidienase.chaosflix.entities.recording.Event;
public class EventDetailsDescriptionPresenter extends AbstractDetailsDescriptionPresenter {
@Override
protected void onBindDescription(ViewHolder vh, Object item) {
Event event = (Event) item;
if(item instanceof Event){
Event event = (Event) item;
vh.getTitle().setText(event.getTitle());
vh.getSubtitle().setText(event.getSubtitle());
StringBuilder sb = new StringBuilder();
String speaker = TextUtils.join(", ", event.getPersons());
sb.append(event.getDescription())
.append("\n")
.append("by: ").append(speaker)
.append("\nreleased at: ").append(event.getReleaseDate())
.append("\nlast updated at: ").append(event.getUpdatedAt())
.append("\nTags: ").append(android.text.TextUtils.join(", ",event.getTags()));
vh.getBody().setText(sb.toString());
vh.getTitle().setText(event.getTitle());
vh.getSubtitle().setText(event.getSubtitle());
StringBuilder sb = new StringBuilder();
String speaker = TextUtils.join(", ", event.getPersons());
sb.append(event.getDescription())
.append("\n")
.append("by: ").append(speaker)
.append("\nreleased at: ").append(event.getReleaseDate())
.append("\nlast updated at: ").append(event.getUpdatedAt())
.append("\nTags: ").append(android.text.TextUtils.join(", ",event.getTags()));
vh.getBody().setText(sb.toString());
} else if(item instanceof Room){
Room room = (Room) item;
vh.getTitle().setText(room.getDisplay());
vh.getSubtitle().setText(room.getShedulename());
}
}
}

View file

@ -15,6 +15,7 @@ import de.nicidienase.chaosflix.activities.EventDetailsActivity;
import de.nicidienase.chaosflix.activities.EventsActivity;
import de.nicidienase.chaosflix.entities.recording.Conference;
import de.nicidienase.chaosflix.entities.recording.Event;
import de.nicidienase.chaosflix.entities.streaming.Room;
/**
* Created by felix on 21.03.17.
@ -52,5 +53,15 @@ public class ItemViewClickedListener implements OnItemViewClickedListener {
EventDetailsActivity.SHARED_ELEMENT_NAME).toBundle();
fragment.getActivity().startActivity(i, bundle);
}
if(item instanceof Room){
Room room = (Room) item;
Intent i = new Intent(fragment.getActivity(), DetailsActivity.class);
i.putExtra(DetailsActivity.ROOM,room);
Bundle bundle = ActivityOptionsCompat.makeSceneTransitionAnimation(
fragment.getActivity(),
((ImageCardView) itemViewHolder.view).getMainImageView(),
EventDetailsActivity.SHARED_ELEMENT_NAME).toBundle();
fragment.getActivity().startActivity(i, bundle);
}
}
}

View file

@ -26,6 +26,7 @@ public class DetailsActivity extends AbstractServiceConnectedAcitivty {
public static final String SHARED_ELEMENT_NAME = "hero";
public static final String EVENT = "event";
public static final String ROOM = "room";
public static final String RECORDING = "recording";
/**

View file

@ -1,12 +1,16 @@
package de.nicidienase.chaosflix.entities.streaming;
import android.os.Parcel;
import android.os.Parcelable;
import java.util.ArrayList;
import java.util.List;
/**
* Created by felix on 23.03.17.
*/
public class Room {
public class Room implements Parcelable{
String slug;
String shedulename;
String thumb;
@ -14,6 +18,40 @@ public class Room {
String display;
List<Stream> streams;
protected Room(Parcel in) {
slug = in.readString();
shedulename = in.readString();
thumb = in.readString();
link = in.readString();
display = in.readString();
}
public static final Creator<Room> CREATOR = new Creator<Room>() {
@Override
public Room createFromParcel(Parcel in) {
return new Room(in);
}
@Override
public Room[] newArray(int size) {
return new Room[size];
}
};
@Override
public int describeContents() {
return 0;
}
@Override
public void writeToParcel(Parcel dest, int flags) {
dest.writeString(slug);
dest.writeString(shedulename);
dest.writeString(thumb);
dest.writeString(link);
dest.writeString(display);
}
public String getSlug() {
return slug;
}

View file

@ -1,12 +1,15 @@
package de.nicidienase.chaosflix.entities.streaming;
import android.os.Parcel;
import android.os.Parcelable;
import java.util.Map;
/**
* Created by felix on 23.03.17.
*/
class Stream {
public class Stream implements Parcelable{
String slug;
String display;
String type;
@ -14,6 +17,40 @@ class Stream {
int[] videoSize;
Map<String,StreamUrl> urls;
protected Stream(Parcel in) {
slug = in.readString();
display = in.readString();
type = in.readString();
isTranslated = in.readByte() != 0;
videoSize = in.createIntArray();
}
@Override
public void writeToParcel(Parcel dest, int flags) {
dest.writeString(slug);
dest.writeString(display);
dest.writeString(type);
dest.writeByte((byte) (isTranslated ? 1 : 0));
dest.writeIntArray(videoSize);
}
@Override
public int describeContents() {
return 0;
}
public static final Creator<Stream> CREATOR = new Creator<Stream>() {
@Override
public Stream createFromParcel(Parcel in) {
return new Stream(in);
}
@Override
public Stream[] newArray(int size) {
return new Stream[size];
}
};
public String getSlug() {
return slug;
}

View file

@ -1,14 +1,35 @@
package de.nicidienase.chaosflix.entities.streaming;
import android.os.Parcel;
import android.os.Parcelable;
/**
* Created by felix on 23.03.17.
*/
public class StreamUrl {
public class StreamUrl implements Parcelable {
String display;
String tech;
String url;
protected StreamUrl(Parcel in) {
display = in.readString();
tech = in.readString();
url = in.readString();
}
public static final Creator<StreamUrl> CREATOR = new Creator<StreamUrl>() {
@Override
public StreamUrl createFromParcel(Parcel in) {
return new StreamUrl(in);
}
@Override
public StreamUrl[] newArray(int size) {
return new StreamUrl[size];
}
};
public String getDisplay() {
return display;
}
@ -32,4 +53,16 @@ public class StreamUrl {
public void setUrl(String url) {
this.url = url;
}
@Override
public int describeContents() {
return 0;
}
@Override
public void writeToParcel(Parcel dest, int flags) {
dest.writeString(display);
dest.writeString(tech);
dest.writeString(url);
}
}

View file

@ -6,6 +6,10 @@ import android.support.v17.leanback.widget.ArrayObjectAdapter;
import android.support.v17.leanback.widget.HeaderItem;
import android.support.v17.leanback.widget.ListRow;
import android.support.v17.leanback.widget.ListRowPresenter;
import android.support.v17.leanback.widget.OnItemViewSelectedListener;
import android.support.v17.leanback.widget.Presenter;
import android.support.v17.leanback.widget.Row;
import android.support.v17.leanback.widget.RowPresenter;
import java.util.Arrays;
import java.util.List;
@ -17,9 +21,10 @@ import de.nicidienase.chaosflix.ItemViewClickedListener;
import de.nicidienase.chaosflix.R;
import de.nicidienase.chaosflix.activities.AbstractServiceConnectedAcitivty;
import de.nicidienase.chaosflix.entities.recording.Conference;
import de.nicidienase.chaosflix.network.MediaApiService;
import de.nicidienase.chaosflix.entities.streaming.Group;
import de.nicidienase.chaosflix.entities.streaming.LiveConference;
import de.nicidienase.chaosflix.entities.streaming.Room;
import io.reactivex.android.schedulers.AndroidSchedulers;
import io.reactivex.schedulers.Schedulers;
/**
* Created by felix on 21.03.17.
@ -36,40 +41,70 @@ public class ConferencesBrowseFragment extends BrowseFragment {
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setTitle(getResources().getString(R.string.app_name));
final BrowseErrorFragment errorFragment =
BrowseErrorFragment.showErrorFragment(getFragmentManager(),FRAGMENT);
CardPresenter cardPresenter = new CardPresenter();
mRowsAdapter = new ArrayObjectAdapter(new ListRowPresenter());
((AbstractServiceConnectedAcitivty)getActivity()).getmApiServiceObservable()
.subscribe(mediaApiService -> {
mediaApiService.getConferences()
.doOnError(t -> {errorFragment.setErrorContent(t.getMessage());})
.observeOn(AndroidSchedulers.mainThread())
.subscribe(conferences -> {
mConferences = conferences.getConferencesBySeries();
mRowsAdapter = new ArrayObjectAdapter(new ListRowPresenter());
CardPresenter cardPresenter = new CardPresenter();
Set<String> keySet = mConferences.keySet();
for(String tag: getOrderedConferencesList()){
if(keySet.contains(tag)){
addRow(mConferences, cardPresenter,tag);
mediaApiService.getStreamingConferences()
.subscribe(liveConferences -> {
if(liveConferences.size() > 0){
for(LiveConference con : liveConferences){
ArrayObjectAdapter listRowAdapter
= new ArrayObjectAdapter(cardPresenter);
for(Group g: con.getGroups()){
listRowAdapter.addAll(0,g.getRooms());
}
HeaderItem header = new HeaderItem(con.getConference());
header.setDescription(con.getDescription());
header.setContentDescription(con.getAuthor());
mRowsAdapter.add(new ListRow(header,listRowAdapter));
}
}
mediaApiService.getConferences()
.doOnError(t -> {errorFragment.setErrorContent(t.getMessage());})
.observeOn(AndroidSchedulers.mainThread())
.subscribe(conferences -> {
mConferences = conferences.getConferencesBySeries();
Set<String> keySet = mConferences.keySet();
for(String tag: getOrderedConferencesList()){
if(keySet.contains(tag)){
ListRow row = getRow(mConferences, cardPresenter, tag,"");
mRowsAdapter.add(row);
}
}
for(String tag: keySet){
if(!getOrderedConferencesList().contains(tag)){
mRowsAdapter.add(getRow(mConferences, cardPresenter, tag,""));
}
}
errorFragment.dismiss();
setAdapter(mRowsAdapter);
});
});
setOnItemViewClickedListener(new ItemViewClickedListener(this));
setOnItemViewSelectedListener(new OnItemViewSelectedListener() {
@Override
public void onItemSelected(Presenter.ViewHolder itemViewHolder, Object item, RowPresenter.ViewHolder rowViewHolder, Row row) {
// if(item instanceof Conference){
// Conference con = (Conference) item;
// row.getHeaderItem().setDescription(con.getTitle());
// }
// if(item instanceof Room)
}
}
for(String tag: keySet){
if(!getOrderedConferencesList().contains(tag)){
addRow(mConferences, cardPresenter, tag);
}
}
errorFragment.dismiss();
setAdapter(mRowsAdapter);
});
});
});
setOnItemViewClickedListener(new ItemViewClickedListener(this));
}
private void addRow(Map<String, List<Conference>> conferences, CardPresenter cardPresenter, String tag) {
private ListRow getRow(Map<String, List<Conference>> conferences, CardPresenter cardPresenter, String tag, String description) {
ArrayObjectAdapter listRowAdapter = new ArrayObjectAdapter(cardPresenter);
listRowAdapter.addAll(0,conferences.get(tag));
HeaderItem header = new HeaderItem(getStringForTag(tag));
mRowsAdapter.add(new ListRow(header, listRowAdapter));
header.setDescription(description);
return new ListRow(header, listRowAdapter);
}
private String getStringForTag(String tag) {
@ -105,7 +140,7 @@ public class ConferencesBrowseFragment extends BrowseFragment {
case "cryptocon":
return "CryptoCon";
case "other conferences":
return "Other ConferencesWrapper";
return "Other Conferences";
case "denog":
return "DENOG";
case "vcfb":

View file

@ -30,9 +30,7 @@ import com.bumptech.glide.request.target.SimpleTarget;
import java.util.ArrayList;
import java.util.Collections;
import java.util.HashSet;
import java.util.List;
import java.util.Set;
import de.nicidienase.chaosflix.CardPresenter;
import de.nicidienase.chaosflix.EventDetailsDescriptionPresenter;
@ -45,13 +43,15 @@ import de.nicidienase.chaosflix.activities.PlaybackOverlayActivity;
import de.nicidienase.chaosflix.entities.recording.Conference;
import de.nicidienase.chaosflix.entities.recording.Event;
import de.nicidienase.chaosflix.entities.recording.Recording;
import de.nicidienase.chaosflix.entities.streaming.Group;
import de.nicidienase.chaosflix.entities.streaming.LiveConference;
import de.nicidienase.chaosflix.entities.streaming.Room;
import de.nicidienase.chaosflix.entities.streaming.Stream;
import de.nicidienase.chaosflix.entities.streaming.StreamUrl;
import de.nicidienase.chaosflix.network.MediaApiService;
import de.nicidienase.chaosflix.network.RecordingClient;
import io.reactivex.Observable;
import io.reactivex.android.schedulers.AndroidSchedulers;
import retrofit2.Call;
import retrofit2.Callback;
import retrofit2.Response;
/**
* Created by felix on 18.03.17.
@ -81,59 +81,91 @@ public class EventsDetailsFragment extends DetailsFragment {
BrowseErrorFragment.showErrorFragment(getFragmentManager(),FRAGMENT);
mSelectedEvent = getActivity().getIntent()
.getParcelableExtra(DetailsActivity.EVENT);
Room room = getActivity().getIntent()
.getParcelableExtra(DetailsActivity.ROOM);
final ArrayObjectAdapter adapter = setupDetailsOverviewRowPresenter();
final DetailsOverviewRow detailsOverviewRow = setupDetailsOverviewRow(mSelectedEvent);
((AbstractServiceConnectedAcitivty)getActivity()).getmApiServiceObservable()
.doOnError(t -> browseErrorFragment.setErrorContent(t.getMessage()))
.subscribe(mediaApiService -> {
((AbstractServiceConnectedAcitivty)getActivity()).getmApiServiceObservable()
.doOnError(t -> browseErrorFragment.setErrorContent(t.getMessage()))
.subscribe(mediaApiService -> {
// mMediaApiService = mediaApiService;
if(mSelectedEvent != null){
final DetailsOverviewRow detailsOverviewRow = setupDetailsOverviewRow(mSelectedEvent);
mediaApiService.getEvent(mSelectedEvent.getApiID())
.doOnError(t -> browseErrorFragment.setErrorContent(t.getMessage()))
.subscribe(event -> {
mSelectedEvent = event;
final ArrayObjectAdapter recordingActionsAdapter =
getRecordingActionsAdapter(mSelectedEvent.getRecordings());
detailsOverviewRow.setActionsAdapter(recordingActionsAdapter);
adapter.add(detailsOverviewRow);
mediaApiService.getConference(
mSelectedEvent.getParentConferenceID())
.observeOn(AndroidSchedulers.mainThread())
.subscribe(conference -> {
String tag = null;
if(mSelectedEvent.getTags().size()>0) {
tag = mSelectedEvent.getTags().get(0);
List<Event> relatedEvents = conference.getEventsByTags().get(tag);
relatedEvents.remove(mSelectedEvent);
Collections.shuffle(relatedEvents);
if (relatedEvents.size() > 5) {
relatedEvents = relatedEvents.subList(0, NUM_RELATED_TALKS );
}
ArrayObjectAdapter relatedEventsAdapter
= new ArrayObjectAdapter(new CardPresenter());
relatedEventsAdapter.addAll(0,relatedEvents);
HeaderItem header = new HeaderItem(getString(R.string.related_talks));
adapter.add(new ListRow(header,relatedEventsAdapter));
}
mediaApiService.getEvent(mSelectedEvent.getApiID())
.doOnError(t -> browseErrorFragment.setErrorContent(t.getMessage()))
.subscribe(event -> {
mSelectedEvent = event;
final ArrayObjectAdapter recordingActionsAdapter =
getRecordingActionsAdapter(mSelectedEvent.getRecordings());
detailsOverviewRow.setActionsAdapter(recordingActionsAdapter);
adapter.add(detailsOverviewRow);
mediaApiService.getConference(
mSelectedEvent.getParentConferenceID())
.observeOn(AndroidSchedulers.mainThread())
.subscribe(conference -> {
String tag = null;
if(mSelectedEvent.getTags().size()>0) {
tag = mSelectedEvent.getTags().get(0);
List<Event> relatedEvents = conference.getEventsByTags().get(tag);
relatedEvents.remove(mSelectedEvent);
Collections.shuffle(relatedEvents);
if (relatedEvents.size() > 5) {
relatedEvents = relatedEvents.subList(0, NUM_RELATED_TALKS );
}
ArrayObjectAdapter relatedEventsAdapter
= new ArrayObjectAdapter(new CardPresenter());
relatedEventsAdapter.addAll(0,relatedEvents);
HeaderItem header = new HeaderItem(getString(R.string.related_talks));
adapter.add(new ListRow(header,relatedEventsAdapter));
}
List<Event> selectedEvents = getRandomEvents(conference, tag);
if(selectedEvents.size()>0){
ArrayObjectAdapter randomEventAdapter
= new ArrayObjectAdapter(new CardPresenter());
randomEventAdapter.addAll(0,selectedEvents);
HeaderItem header = new HeaderItem(getString(R.string.random_talks));
adapter.add(new ListRow(header,randomEventAdapter));
}
List<Event> selectedEvents = getRandomEvents(conference, tag);
if(selectedEvents.size()>0){
ArrayObjectAdapter randomEventAdapter
= new ArrayObjectAdapter(new CardPresenter());
randomEventAdapter.addAll(0,selectedEvents);
HeaderItem header = new HeaderItem(getString(R.string.random_talks));
adapter.add(new ListRow(header,randomEventAdapter));
}
setAdapter(adapter);
setOnItemViewClickedListener(
new ItemViewClickedListener(EventsDetailsFragment.this));
browseErrorFragment.dismiss();
});
});
} else if(room != null){
mediaApiService.getStreamingConferences()
.observeOn(AndroidSchedulers.mainThread())
.subscribe(liveConferences -> {
Room room_ = getRoom(room, liveConferences);
if(room_ != null){
final DetailsOverviewRow detailsOverviewRow = setupDetailsOverviewRow(room_);
ArrayObjectAdapter actionsAdapter = getStreamActionsAdapter(room_.getStreams());
detailsOverviewRow.setActionsAdapter(actionsAdapter);
adapter.add(detailsOverviewRow);
setAdapter(adapter);
setOnItemViewClickedListener(
new ItemViewClickedListener(EventsDetailsFragment.this));
browseErrorFragment.dismiss();
});
}
});
});
}
});
}
private Room getRoom(Room room, List<LiveConference> liveConferences) {
for(LiveConference con : liveConferences){
for(Group g : con.getGroups()){
for(Room r : g.getRooms()){
if(r.getSlug().equals(room.getSlug())){
return r;
}
}
}
}
return null;
}
@NonNull
@ -205,6 +237,23 @@ public class EventsDetailsFragment extends DetailsFragment {
return row;
}
private DetailsOverviewRow setupDetailsOverviewRow(Room room) {
final DetailsOverviewRow row = new DetailsOverviewRow(room);
Glide.with(getActivity())
.load(room.getThumb())
.asBitmap()
.error(R.drawable.default_background)
.into(new SimpleTarget<Bitmap>(DETAIL_THUMB_WIDTH,DETAIL_THUMB_HEIGHT) {
@Override
public void onResourceReady(Bitmap resource,
GlideAnimation<? super Bitmap> glideAnimation) {
row.setImageBitmap(getActivity(),resource);
startEntranceTransition();
}
});
return row;
}
private ArrayObjectAdapter getRecordingActionsAdapter(List<Recording> recordings) {
ArrayObjectAdapter actionsAdapter = new ArrayObjectAdapter();
for(int i = 0; i < recordings.size(); i++){
@ -217,6 +266,18 @@ public class EventsDetailsFragment extends DetailsFragment {
return actionsAdapter;
}
private ArrayObjectAdapter getStreamActionsAdapter(List<Stream> streams){
ArrayObjectAdapter actionsAdapter = new ArrayObjectAdapter();
for(Stream s: streams){
if(s.getType().equals("video"))
for(String key :s.getUrls().keySet()){
StreamUrl url = s.getUrls().get(key);
actionsAdapter.add(new Action(0,s.getDisplay(), url.getDisplay()));
}
}
return actionsAdapter;
}
static class EventDetailsOverviewLogoPresenter extends DetailsOverviewLogoPresenter {
static class ViewHolder extends DetailsOverviewLogoPresenter.ViewHolder {
public ViewHolder(View view) {