WIP: start restructuring to use Persistent entities and use Database as single source of truth

This commit is contained in:
Felix 2017-11-03 00:00:46 +01:00
parent 56a4addc14
commit 8bef45fcae
19 changed files with 299 additions and 163 deletions

View file

@ -8,6 +8,7 @@ buildscript {
maven {
url "https://maven.google.com"
}
google()
}
dependencies {
classpath 'com.android.tools.build:gradle:3.0.0'
@ -23,7 +24,7 @@ allprojects {
mavenLocal()
jcenter()
maven { url "https://oss.sonatype.org/content/repositories/snapshots/" }
maven { url "https://maven.google.com" }
google()
}
}

View file

@ -51,7 +51,7 @@ android {
dependencies {
implementation 'de.nicidienase.chaosflix:common:1.1.0-SNAPSHOT'
implementation 'de.nicidienase.chaosflix:common:1.2.0-SNAPSHOT'
implementation 'com.android.support:multidex:1.0.1'
@ -61,14 +61,14 @@ dependencies {
implementation 'com.android.support.constraint:constraint-layout:1.0.2'
implementation "com.android.support:design:${rootProject.ext.supportLibraryVersion}"
implementation "android.arch.lifecycle:runtime:1.0.3"
// implementation "android.arch.lifecycle:runtime:1.0.3"
implementation "android.arch.lifecycle:extensions:${rootProject.ext.archCompVersion}"
implementation "android.arch.lifecycle:common-java8:1.0.0-rc1"
implementation "android.arch.persistence.room:runtime:${rootProject.ext.archCompVersion}"
implementation "android.arch.persistence.room:rxjava2:${rootProject.ext.archCompVersion}"
kapt 'com.android.databinding:compiler:3.1.0-alpha01'
kapt "android.arch.lifecycle:compiler:${rootProject.ext.archCompVersion}"
kapt "android.arch.persistence.room:compiler:${rootProject.ext.archCompVersion}"
// kapt "android.arch.persistence.room:compiler:${rootProject.ext.archCompVersion}"
implementation "org.jetbrains.kotlin:kotlin-reflect:1.1.50"
implementation 'com.squareup.retrofit2:retrofit:2.2.0'

View file

@ -10,9 +10,7 @@ class ChaosflixApplication: Application(){
override fun onCreate() {
super.onCreate()
APPLICATION_CONTEXT = this
if(BuildConfig.DEBUG){
Stetho.initializeWithDefaults(this);
}
Stetho.initializeWithDefaults(this);
}
companion object {

View file

@ -13,6 +13,7 @@ import java.util.Map;
import de.nicidienase.chaosflix.R;
import de.nicidienase.chaosflix.common.entities.recording.Conference;
import de.nicidienase.chaosflix.common.entities.recording.ConferencesWrapper;
import de.nicidienase.chaosflix.common.entities.recording.persistence.ConferenceGroup;
import de.nicidienase.chaosflix.touch.fragments.ConferenceGroupFragment;
/**
@ -22,7 +23,7 @@ public class ConferenceGroupsFragmentPager extends FragmentPagerAdapter {
private static final String TAG = ConferenceGroupsFragmentPager.class.getSimpleName();
private final Context mContext;
private List<String> orderedConferencesList = new ArrayList<>();
private List<ConferenceGroup> conferenceGroupList = new ArrayList<>();
public ConferenceGroupsFragmentPager(Context context, FragmentManager fm) {
super(fm);
@ -31,7 +32,7 @@ public class ConferenceGroupsFragmentPager extends FragmentPagerAdapter {
@Override
public Fragment getItem(int position) {
String confKey = orderedConferencesList.get(position);
String confKey = conferenceGroupList.get(position);
ConferenceGroupFragment conferenceFragment = ConferenceGroupFragment.newInstance(confKey,1);
conferenceFragment.setRetainInstance(true);
Log.d(TAG,"Created Fragment for: " + confKey);

View file

@ -4,7 +4,6 @@ import android.arch.lifecycle.ViewModelProviders;
import android.content.Intent;
import android.os.Bundle;
import android.support.annotation.Nullable;
import android.support.design.widget.Snackbar;
import android.support.v4.app.Fragment;
import android.support.v4.app.FragmentManager;
import android.support.v4.app.FragmentTransaction;
@ -13,21 +12,20 @@ import android.support.v7.app.AppCompatActivity;
import android.support.v7.widget.Toolbar;
import android.transition.Slide;
import android.transition.TransitionInflater;
import android.util.Log;
import android.view.Gravity;
import android.view.Menu;
import android.view.MenuItem;
import android.view.View;
import de.nicidienase.chaosflix.R;
import de.nicidienase.chaosflix.common.entities.recording.Conference;
import de.nicidienase.chaosflix.common.entities.recording.Event;
import de.nicidienase.chaosflix.common.entities.recording.Recording;
import de.nicidienase.chaosflix.touch.viewmodels.BrowseViewModel;
import de.nicidienase.chaosflix.common.entities.recording.persistence.PersistentConference;
import de.nicidienase.chaosflix.common.entities.recording.persistence.PersistentEvent;
import de.nicidienase.chaosflix.common.entities.recording.persistence.PersistentRecording;
import de.nicidienase.chaosflix.touch.ViewModelFactory;
import de.nicidienase.chaosflix.touch.fragments.ConferencesTabBrowseFragment;
import de.nicidienase.chaosflix.touch.fragments.EventDetailsFragment;
import de.nicidienase.chaosflix.touch.fragments.EventsListFragment;
import de.nicidienase.chaosflix.touch.viewmodels.BrowseViewModel;
import io.reactivex.android.schedulers.AndroidSchedulers;
import io.reactivex.disposables.CompositeDisposable;
@ -38,7 +36,7 @@ import io.reactivex.disposables.CompositeDisposable;
public class BrowseActivity extends AppCompatActivity implements
ConferencesTabBrowseFragment.OnConferenceListFragmentInteractionListener,
EventsListFragment.OnEventsListFragmentInteractionListener,
EventDetailsFragment.OnEventDetailsFragmentInteractionListener{
EventDetailsFragment.OnEventDetailsFragmentInteractionListener {
private static final String TAG = BrowseActivity.class.getSimpleName();
CompositeDisposable mDisposables = new CompositeDisposable();
@ -51,7 +49,7 @@ public class BrowseActivity extends AppCompatActivity implements
mViewModel = ViewModelProviders.of(this, ViewModelFactory.INSTANCE).get(BrowseViewModel.class);
if(savedInstanceState == null){
if (savedInstanceState == null) {
ConferencesTabBrowseFragment browseFragment
= ConferencesTabBrowseFragment.newInstance(getNumColumns());
// mViewModel.getConferencesWrapperAsLiveData().observe(browseFragment,conferencesWrapper -> {
@ -59,18 +57,10 @@ public class BrowseActivity extends AppCompatActivity implements
// ft.replace(R.id.fragment_container,browseFragment);
// ft.setReorderingAllowed(true);
// ft.commit();
mDisposables.add(mViewModel.getConferencesWrapper()
.observeOn(AndroidSchedulers.mainThread())
.subscribe(conferencesWrapper -> {
FragmentTransaction ft = getSupportFragmentManager().beginTransaction();
ft.replace(R.id.fragment_container,browseFragment);
ft.setReorderingAllowed(true);
ft.commit();
}, throwable -> {
Snackbar.make(findViewById(R.id.fragment_container),throwable.getMessage(),Snackbar.LENGTH_INDEFINITE).show();
Log.d(TAG,throwable.getMessage(),throwable);
}));
// });
FragmentTransaction ft = getSupportFragmentManager().beginTransaction();
ft.replace(R.id.fragment_container, browseFragment);
ft.setReorderingAllowed(true);
ft.commit();
}
}
@ -85,11 +75,11 @@ public class BrowseActivity extends AppCompatActivity implements
}
@Override
public void onConferenceSelected(Conference con) {
mDisposables.add(mViewModel.getConference(con.getApiID())
public void onConferenceSelected(PersistentConference con) {
mDisposables.add(mViewModel.getConference(con.getConferenceId())
.observeOn(AndroidSchedulers.mainThread())
.subscribe(conference -> {
EventsListFragment eventsListFragment = EventsListFragment.newInstance(conference.getApiID(),getNumColumns());
EventsListFragment eventsListFragment = EventsListFragment.newInstance(conference.getConferenceId(), getNumColumns());
FragmentManager fm = getSupportFragmentManager();
Fragment oldFragment = fm.findFragmentById(R.id.fragment_container);
@ -112,27 +102,22 @@ public class BrowseActivity extends AppCompatActivity implements
}
@Override
public void onEventSelected(Event e, View v) {
mDisposables.add(mViewModel.getEvent(e.getApiID())
.observeOn(AndroidSchedulers.mainThread())
.subscribe(event -> {
public void onEventSelected(PersistentEvent event, View v) {
EventDetailsFragment detailsFragment = EventDetailsFragment.newInstance(event);
FragmentManager fm = getSupportFragmentManager();
EventDetailsFragment detailsFragment = EventDetailsFragment.newInstance(event);
FragmentManager fm = getSupportFragmentManager();
detailsFragment.setAllowEnterTransitionOverlap(true);
detailsFragment.setAllowReturnTransitionOverlap(true);
detailsFragment.setAllowEnterTransitionOverlap(true);
detailsFragment.setAllowReturnTransitionOverlap(true);
FragmentTransaction ft = fm.beginTransaction();
ft.replace(R.id.fragment_container, detailsFragment);
ft.addToBackStack(null);
ft.setReorderingAllowed(true);
FragmentTransaction ft = fm.beginTransaction();
ft.replace(R.id.fragment_container, detailsFragment);
ft.addToBackStack(null);
ft.setReorderingAllowed(true);
View thumb = v.findViewById(R.id.imageView);
ft.addSharedElement(thumb, ViewCompat.getTransitionName(thumb));
View thumb = v.findViewById(R.id.imageView);
ft.addSharedElement(thumb,ViewCompat.getTransitionName(thumb));
ft.commit();
}));
ft.commit();
}
@Override
@ -147,10 +132,10 @@ public class BrowseActivity extends AppCompatActivity implements
}
@Override
public void playItem(Event event, Recording recording) {
Intent i = new Intent(this,PlayerActivity.class);
i.putExtra(PlayerActivity.EVENT_ID,event.getApiID());
i.putExtra(PlayerActivity.RECORDING_ID, recording.getApiID());
public void playItem(PersistentEvent event, PersistentRecording recording) {
Intent i = new Intent(this, PlayerActivity.class);
i.putExtra(PlayerActivity.EVENT_ID, event.getEventId());
i.putExtra(PlayerActivity.RECORDING_ID, recording.getEventId());
startActivity(i);
// FragmentTransaction ft = getSupportFragmentManager().beginTransaction();
@ -162,16 +147,19 @@ public class BrowseActivity extends AppCompatActivity implements
@Override
public boolean onCreateOptionsMenu(Menu menu) {
getMenuInflater().inflate(R.menu.browse_menu,menu);
getMenuInflater().inflate(R.menu.browse_menu, menu);
return true;
}
@Override
public boolean onOptionsItemSelected(MenuItem item) {
switch (item.getItemId()){
switch (item.getItemId()) {
case R.id.action_about:
showAboutPage();
return true;
case R.id.action_update_database:
// mViewModel.updateDatabase();
return true;
default:
return super.onOptionsItemSelected(item);
}

View file

@ -9,8 +9,8 @@ import android.support.v4.app.FragmentTransaction;
import android.support.v7.app.AppCompatActivity;
import de.nicidienase.chaosflix.R;
import de.nicidienase.chaosflix.common.entities.recording.Event;
import de.nicidienase.chaosflix.common.entities.recording.Recording;
import de.nicidienase.chaosflix.common.entities.recording.persistence.PersistentEvent;
import de.nicidienase.chaosflix.common.entities.recording.persistence.PersistentRecording;
import de.nicidienase.chaosflix.common.entities.userdata.PlaybackProgress;
import de.nicidienase.chaosflix.touch.ViewModelFactory;
import de.nicidienase.chaosflix.touch.fragments.ExoPlayerFragment;
@ -35,7 +35,7 @@ public class PlayerActivity extends AppCompatActivity implements ExoPlayerFragme
long eventId = getIntent().getExtras().getLong(EVENT_ID);
long recordingId = getIntent().getExtras().getLong(RECORDING_ID);
if(savedInstanceState == null){
if (savedInstanceState == null) {
loadFragment(eventId, recordingId);
}
}
@ -47,19 +47,21 @@ public class PlayerActivity extends AppCompatActivity implements ExoPlayerFragme
int eventId = intent.getExtras().getInt(EVENT_ID);
int recordingId = intent.getExtras().getInt(RECORDING_ID);
loadFragment(eventId,recordingId);
loadFragment(eventId, recordingId);
}
private void loadFragment(long eventId, long recordingId) {
FragmentTransaction ft = getSupportFragmentManager().beginTransaction();
Observable.zip(viewModel.getEvent(eventId),viewModel.getRecording(recordingId),
(event, recording) -> new Object[]{event,recording})
Flowable.zip(viewModel.getEvent(eventId), viewModel.getRecording(recordingId),
(event, recording) -> new Object[]{event, recording})
.subscribeOn(Schedulers.io())
.observeOn(AndroidSchedulers.mainThread())
.subscribe(objects -> {
PersistentEvent event = (PersistentEvent) objects[0];
PersistentRecording recording = (PersistentRecording) objects[1];
Fragment playerFragment =
ExoPlayerFragment.newInstance((Event)objects[0],(Recording) objects[1]);
ft.replace(R.id.fragment_container,playerFragment);
ExoPlayerFragment.newInstance(event, recording);
ft.replace(R.id.fragment_container, playerFragment);
ft.commit();
});
}
@ -71,6 +73,6 @@ public class PlayerActivity extends AppCompatActivity implements ExoPlayerFragme
@Override
public void setPlaybackProgress(long apiId, long progress) {
viewModel.setPlaybackProgress(apiId,progress);
viewModel.setPlaybackProgress(apiId, progress);
}
}

View file

@ -7,9 +7,10 @@ import java.util.List;
import de.nicidienase.chaosflix.R;
import de.nicidienase.chaosflix.common.entities.recording.Conference;
import de.nicidienase.chaosflix.common.entities.recording.persistence.PersistentConference;
import de.nicidienase.chaosflix.touch.fragments.ConferencesTabBrowseFragment;
public class ConferenceRecyclerViewAdapter extends ItemRecyclerViewAdapter<Conference> {
public class ConferenceRecyclerViewAdapter extends ItemRecyclerViewAdapter<PersistentConference> {
private final ConferencesTabBrowseFragment.OnConferenceListFragmentInteractionListener mListener;
@ -17,7 +18,7 @@ public class ConferenceRecyclerViewAdapter extends ItemRecyclerViewAdapter<Confe
this(new ArrayList<>(),listener);
}
public ConferenceRecyclerViewAdapter(List<Conference> items, ConferencesTabBrowseFragment.OnConferenceListFragmentInteractionListener listener) {
public ConferenceRecyclerViewAdapter(List<PersistentConference> items, ConferencesTabBrowseFragment.OnConferenceListFragmentInteractionListener listener) {
super(items);
mListener = listener;
}
@ -35,7 +36,7 @@ public class ConferenceRecyclerViewAdapter extends ItemRecyclerViewAdapter<Confe
holder.mView.setOnClickListener(v -> {
if (null != mListener) {
mListener.onConferenceSelected((Conference) holder.mItem);
mListener.onConferenceSelected((PersistentConference) holder.mItem);
}
});
}

View file

@ -6,13 +6,14 @@ import android.support.v4.view.ViewCompat;
import com.squareup.picasso.Picasso;
import java.util.Collections;
import java.util.List;
import de.nicidienase.chaosflix.R;
import de.nicidienase.chaosflix.common.entities.recording.Conference;
import de.nicidienase.chaosflix.common.entities.recording.Event;
import de.nicidienase.chaosflix.common.entities.recording.persistence.PersistentConference;
import de.nicidienase.chaosflix.common.entities.recording.persistence.PersistentEvent;
import de.nicidienase.chaosflix.touch.fragments.EventsListFragment;
public class EventRecyclerViewAdapter extends ItemRecyclerViewAdapter<Event> {
public class EventRecyclerViewAdapter extends ItemRecyclerViewAdapter<PersistentEvent> {
private boolean areTagsUsefull;
private final EventsListFragment.OnEventsListFragmentInteractionListener mListener;
@ -22,29 +23,26 @@ public class EventRecyclerViewAdapter extends ItemRecyclerViewAdapter<Event> {
mListener = listener;
}
public EventRecyclerViewAdapter(Conference conference, EventsListFragment.OnEventsListFragmentInteractionListener listener) {
super(conference.getEvents());
public EventRecyclerViewAdapter(PersistentConference conference, List<PersistentEvent> events, EventsListFragment.OnEventsListFragmentInteractionListener listener) {
super(events);
mListener = listener;
setItems(conference);
}
public void setItems(Conference conference){
setItems(conference.getEvents());
areTagsUsefull = conference.areTagsUsefull();
Collections.sort(mItems,(o1, o2) -> o1.getTitle().compareTo(o2.getTitle()));
setItems(events);
areTagsUsefull = conference.getTagsUsefull();
Collections.sort(mItems, (o1, o2) -> o1.getTitle().compareTo(o2.getTitle()));
}
@Override
public void onBindViewHolder(ItemRecyclerViewAdapter.ViewHolder holder, int position) {
Event event = mItems.get(position);
PersistentEvent event = mItems.get(position);
holder.mItem = event;
holder.mTitleText.setText(event.getTitle());
holder.mSubtitle.setText(event.getSubtitle());
if(areTagsUsefull){
if (areTagsUsefull) {
StringBuilder tagString = new StringBuilder();
for(String tag: event.getTags()){
if(tagString.length() > 0) {
for (String tag : event.getTags()) {
if (tagString.length() > 0) {
tagString.append(", ");
}
tagString.append(tag);
@ -60,15 +58,15 @@ public class EventRecyclerViewAdapter extends ItemRecyclerViewAdapter<Event> {
Resources resources = holder.mTitleText.getContext().getResources();
ViewCompat.setTransitionName(holder.mTitleText,
resources.getString(R.string.title)+event.getApiID());
resources.getString(R.string.title) + event.getEventId());
ViewCompat.setTransitionName(holder.mSubtitle,
resources.getString(R.string.subtitle)+event.getApiID());
resources.getString(R.string.subtitle) + event.getEventId());
ViewCompat.setTransitionName(holder.mIcon,
resources.getString(R.string.thumbnail)+event.getApiID());
resources.getString(R.string.thumbnail) + event.getEventId());
holder.mView.setOnClickListener(v -> {
if (null != mListener) {
mListener.onEventSelected((Event) holder.mItem, v);
mListener.onEventSelected((PersistentEvent) holder.mItem, v);
}
});
}

View file

@ -29,6 +29,17 @@ public abstract class ItemRecyclerViewAdapter<T> extends RecyclerView.Adapter<It
notifyDataSetChanged();
}
public void addItem(T item){
if(mItems.contains(item)){
int index = mItems.indexOf(item);
mItems.set(index,item);
notifyItemChanged(index);
} else {
mItems.add(item);
notifyItemInserted(mItems.size()-1);
}
}
@Override
public ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
View view = LayoutInflater.from(parent.getContext())

View file

@ -11,6 +11,7 @@ import android.view.View;
import android.view.ViewGroup;
import de.nicidienase.chaosflix.R;
import de.nicidienase.chaosflix.common.entities.recording.persistence.ConferenceGroup;
import de.nicidienase.chaosflix.touch.adapters.ConferenceRecyclerViewAdapter;
import io.reactivex.android.schedulers.AndroidSchedulers;
import io.reactivex.disposables.CompositeDisposable;
@ -21,7 +22,7 @@ public class ConferenceGroupFragment extends ChaosflixFragment {
private static final String TAG = ConferenceGroupFragment.class.getSimpleName();
private static final String ARG_COLUMN_COUNT = "column-count";
private static final String ARG_GROUP_NAME = "group-name";
private static final String ARG_GROUP = "group-name";
private static final String LAYOUTMANAGER_STATE = "layoutmanager-state";
private ConferencesTabBrowseFragment.OnConferenceListFragmentInteractionListener mListener;
@ -36,11 +37,11 @@ public class ConferenceGroupFragment extends ChaosflixFragment {
public ConferenceGroupFragment() {
}
public static ConferenceGroupFragment newInstance(String group,int columnCount) {
public static ConferenceGroupFragment newInstance(ConferenceGroup group, int columnCount) {
ConferenceGroupFragment fragment = new ConferenceGroupFragment();
Bundle args = new Bundle();
args.putInt(ARG_COLUMN_COUNT, columnCount);
args.putString(ARG_GROUP_NAME, group);
args.putParcelable(ARG_GROUP, group);
fragment.setArguments(args);
return fragment;
}
@ -50,7 +51,7 @@ public class ConferenceGroupFragment extends ChaosflixFragment {
super.onCreate(savedInstanceState);
if (getArguments() != null) {
mColumnCount = getArguments().getInt(ARG_COLUMN_COUNT);
mGroupName = getArguments().getString(ARG_GROUP_NAME);
mGroupName = getArguments().getString(ARG_GROUP);
}
}

View file

@ -12,15 +12,12 @@ import android.view.View;
import android.view.ViewGroup;
import de.nicidienase.chaosflix.R;
import de.nicidienase.chaosflix.common.entities.recording.Conference;
import de.nicidienase.chaosflix.common.entities.recording.persistence.PersistentConference;
import de.nicidienase.chaosflix.touch.ConferenceGroupsFragmentPager;
import io.reactivex.android.schedulers.AndroidSchedulers;
import io.reactivex.disposables.CompositeDisposable;
import io.reactivex.schedulers.Schedulers;
/**
* Created by felix on 19.09.17.
*/
public class ConferencesTabBrowseFragment extends ChaosflixFragment {
@ -37,7 +34,6 @@ public class ConferencesTabBrowseFragment extends ChaosflixFragment {
private final CompositeDisposable mDisposable = new CompositeDisposable();
public static ConferencesTabBrowseFragment newInstance(int columnCount) {
ConferencesTabBrowseFragment fragment = new ConferencesTabBrowseFragment();
Bundle args = new Bundle();
@ -76,7 +72,7 @@ public class ConferencesTabBrowseFragment extends ChaosflixFragment {
ConferenceGroupsFragmentPager fragmentPager
= new ConferenceGroupsFragmentPager(this.getContext(), getChildFragmentManager());
getViewModel().getConferencesWrapper()
getViewModel().getConferencesMap()
.subscribeOn(Schedulers.io())
.observeOn(AndroidSchedulers.mainThread())
.subscribe(conferencesWrapper -> {
@ -116,6 +112,6 @@ public class ConferencesTabBrowseFragment extends ChaosflixFragment {
}
public interface OnConferenceListFragmentInteractionListener {
void onConferenceSelected(Conference conference);
void onConferenceSelected(PersistentConference conference);
}
}

View file

@ -18,9 +18,10 @@ import com.squareup.picasso.Callback;
import com.squareup.picasso.Picasso;
import de.nicidienase.chaosflix.R;
import de.nicidienase.chaosflix.common.entities.recording.Event;
import de.nicidienase.chaosflix.common.entities.recording.Recording;
import de.nicidienase.chaosflix.common.entities.recording.persistence.PersistentEvent;
import de.nicidienase.chaosflix.common.entities.recording.persistence.PersistentRecording;
import de.nicidienase.chaosflix.databinding.FragmentEventDetailsNewBinding;
import de.nicidienase.chaosflix.touch.Util;
import io.reactivex.disposables.CompositeDisposable;
public class EventDetailsFragment extends ChaosflixFragment {
@ -28,15 +29,15 @@ public class EventDetailsFragment extends ChaosflixFragment {
private static final String EVENT_PARAM = "event_param";
private OnEventDetailsFragmentInteractionListener mListener;
private Event mEvent;
private PersistentEvent mEvent;
private boolean appBarExpanded;
private CompositeDisposable disposable = new CompositeDisposable();
public static EventDetailsFragment newInstance(Event event) {
public static EventDetailsFragment newInstance(PersistentEvent event) {
EventDetailsFragment fragment = new EventDetailsFragment();
Bundle args = new Bundle();
args.putParcelable(EVENT_PARAM,event);
args.putParcelable(EVENT_PARAM, event);
fragment.setArguments(args);
return fragment;
}
@ -72,20 +73,20 @@ public class EventDetailsFragment extends ChaosflixFragment {
play();
});
if(mListener != null)
if (mListener != null)
mListener.setActionbar(binding.animToolbar);
binding.appbar.addOnOffsetChangedListener((appBarLayout, verticalOffset) -> {
double v = (double) Math.abs(verticalOffset) / appBarLayout.getTotalScrollRange();
if(appBarExpanded ^ v > 0.8){
if(mListener != null)
if (appBarExpanded ^ v > 0.8) {
if (mListener != null)
mListener.onToolbarStateChange();
appBarExpanded = v > 0.8;
binding.collapsingToolbar.setTitleEnabled(appBarExpanded);
}
});
binding.thumbImage.setTransitionName(getString(R.string.thumbnail)+mEvent.getApiID());
binding.thumbImage.setTransitionName(getString(R.string.thumbnail) + mEvent.getEventId());
Picasso.with(getContext())
.load(mEvent.getThumbUrl())
.noFade()
@ -103,8 +104,11 @@ public class EventDetailsFragment extends ChaosflixFragment {
}
private void play() {
if(mListener != null){
mListener.playItem(mEvent,mEvent.getOptimalStream());
if (mListener != null) {
getViewModel().getRecordingForEvent(mEvent.getEventId())
.subscribe(persistentRecordings -> {
mListener.playItem(mEvent, Util.Companion.getOptimalStream(persistentRecordings));
});
}
}
@ -134,7 +138,7 @@ public class EventDetailsFragment extends ChaosflixFragment {
@Override
public void onPrepareOptionsMenu(Menu menu) {
super.onPrepareOptionsMenu(menu);
disposable.add(getViewModel().getBookmark(mEvent.getApiID())
disposable.add(getViewModel().getBookmark(mEvent.getEventId())
.subscribe(watchlistItem -> {
if (watchlistItem != null) {
menu.findItem(R.id.action_bookmark).setVisible(false);
@ -146,24 +150,24 @@ public class EventDetailsFragment extends ChaosflixFragment {
@Override
public void onCreateOptionsMenu(Menu menu, MenuInflater inflater) {
super.onCreateOptionsMenu(menu, inflater);
if(appBarExpanded)
inflater.inflate(R.menu.details_menu,menu);
if (appBarExpanded)
inflater.inflate(R.menu.details_menu, menu);
}
@Override
public boolean onOptionsItemSelected(MenuItem item) {
switch (item.getItemId()){
switch (item.getItemId()) {
case R.id.action_play:
play();
return true;
case R.id.action_bookmark:
getViewModel().createBookmark(mEvent.getApiID());
getViewModel().createBookmark(mEvent.getEventId());
return true;
case R.id.action_unbookmark:
getViewModel().removeBookmark(mEvent.getApiID());
getViewModel().removeBookmark(mEvent.getEventId());
return true;
case R.id.action_download:
Snackbar.make(item.getActionView(),"Start download",Snackbar.LENGTH_LONG).show();
Snackbar.make(item.getActionView(), "Start download", Snackbar.LENGTH_LONG).show();
return true;
default:
return super.onOptionsItemSelected(item);
@ -172,7 +176,9 @@ public class EventDetailsFragment extends ChaosflixFragment {
public interface OnEventDetailsFragmentInteractionListener {
void onToolbarStateChange();
void setActionbar(Toolbar toolbar);
void playItem(Event event, Recording recording);
void playItem(PersistentEvent event, PersistentRecording recording);
}
}

View file

@ -17,9 +17,13 @@ import android.view.MenuInflater;
import android.view.View;
import android.view.ViewGroup;
import java.util.List;
import de.nicidienase.chaosflix.R;
import de.nicidienase.chaosflix.common.entities.recording.Event;
import de.nicidienase.chaosflix.common.entities.recording.persistence.PersistentConference;
import de.nicidienase.chaosflix.common.entities.recording.persistence.PersistentEvent;
import de.nicidienase.chaosflix.touch.adapters.EventRecyclerViewAdapter;
import io.reactivex.Flowable;
import io.reactivex.android.schedulers.AndroidSchedulers;
import io.reactivex.disposables.CompositeDisposable;
import io.reactivex.schedulers.Schedulers;
@ -97,41 +101,36 @@ public class EventsListFragment extends ChaosflixFragment {
recyclerView.setAdapter(mAdapter);
mToolbar = view.findViewById(R.id.toolbar);
((AppCompatActivity)mContext).setSupportActionBar(mToolbar);
((AppCompatActivity) mContext).setSupportActionBar(mToolbar);
mDisposable.add(getViewModel().getConference(mConferenceId)
.subscribeOn(Schedulers.io())
.observeOn(AndroidSchedulers.mainThread())
.subscribe(conference -> {
Parcelable layoutState = getArguments().getParcelable(LAYOUTMANAGER_STATE);
if(layoutState != null){
layoutManager.onRestoreInstanceState(layoutState);
}
mAdapter.setItems(conference);
mToolbar.setTitle(conference.getTitle());
}, throwable -> Snackbar.make(container,throwable.getMessage(),Snackbar.LENGTH_INDEFINITE).show()));
.subscribe(conference -> mToolbar.setTitle(conference.getTitle())));
mDisposable.add(getViewModel().getEventsforConference(mConferenceId).subscribe(
persistentEvent -> mAdapter.addItem(persistentEvent)));
return view;
}
@Override
public void onViewStateRestored(@Nullable Bundle savedInstanceState) {
super.onViewStateRestored(savedInstanceState);
if(savedInstanceState != null){
if (savedInstanceState != null) {
layoutManager.onRestoreInstanceState(savedInstanceState.getParcelable(LAYOUTMANAGER_STATE));
Log.d(TAG,"Layout State restored");
Log.d(TAG, "Layout State restored");
}
}
@Override
public void onCreateOptionsMenu(Menu menu, MenuInflater inflater) {
super.onCreateOptionsMenu(menu, inflater);
inflater.inflate(R.menu.events_menu,menu);
inflater.inflate(R.menu.events_menu, menu);
}
@Override
public void onSaveInstanceState(Bundle outState) {
super.onSaveInstanceState(outState);
outState.putParcelable(LAYOUTMANAGER_STATE,layoutManager.onSaveInstanceState());
outState.putParcelable(LAYOUTMANAGER_STATE, layoutManager.onSaveInstanceState());
Log.d(TAG, "Layout state saved");
}
@ -147,8 +146,8 @@ public class EventsListFragment extends ChaosflixFragment {
mDisposable.clear();
}
public interface OnEventsListFragmentInteractionListener{
void onEventSelected(Event event, View v);
public interface OnEventsListFragmentInteractionListener {
void onEventSelected(PersistentEvent event, View v);
}
}

View file

@ -43,8 +43,8 @@ import com.google.android.exoplayer2.util.Util;
import butterknife.BindView;
import butterknife.ButterKnife;
import de.nicidienase.chaosflix.R;
import de.nicidienase.chaosflix.common.entities.recording.Event;
import de.nicidienase.chaosflix.common.entities.recording.Recording;
import de.nicidienase.chaosflix.common.entities.recording.persistence.PersistentEvent;
import de.nicidienase.chaosflix.common.entities.recording.persistence.PersistentRecording;
import de.nicidienase.chaosflix.common.entities.userdata.PlaybackProgress;
import io.reactivex.Flowable;
import io.reactivex.disposables.CompositeDisposable;
@ -74,14 +74,14 @@ public class ExoPlayerFragment extends Fragment implements MyListener.PlayerStat
private String mUserAgent;
private Handler mainHandler = new Handler();
private boolean mPlaybackState = true;
private Event mEvent;
private Recording mRecording;
private PersistentEvent mEvent;
private PersistentRecording mRecording;
private SimpleExoPlayer exoPlayer;
public ExoPlayerFragment() {
}
public static ExoPlayerFragment newInstance(Event event, Recording recording) {
public static ExoPlayerFragment newInstance(PersistentEvent event, PersistentRecording recording) {
ExoPlayerFragment fragment = new ExoPlayerFragment();
Bundle args = new Bundle();
args.putParcelable(ARG_EVENT, event);
@ -131,7 +131,7 @@ public class ExoPlayerFragment extends Fragment implements MyListener.PlayerStat
super.onResume();
if (exoPlayer != null) {
exoPlayer.setPlayWhenReady(mPlaybackState);
disposable.add(mListener.getPlaybackProgress(mEvent.getApiID())
disposable.add(mListener.getPlaybackProgress(mEvent.getEventId())
.subscribe(playbackProgress -> {
if (playbackProgress != null) {
exoPlayer.seekTo(playbackProgress.getProgress());
@ -152,7 +152,7 @@ public class ExoPlayerFragment extends Fragment implements MyListener.PlayerStat
public void onPause() {
super.onPause();
if (exoPlayer != null) {
mListener.setPlaybackProgress(mEvent.getApiID(), exoPlayer.getCurrentPosition());
mListener.setPlaybackProgress(mEvent.getEventId(), exoPlayer.getCurrentPosition());
exoPlayer.setPlayWhenReady(false);
}
disposable.clear();

View file

@ -1,17 +1,19 @@
package de.nicidienase.chaosflix.touch.viewmodels
import android.arch.lifecycle.ViewModel
import android.util.Log
import de.nicidienase.chaosflix.common.entities.ChaosflixDatabase
import de.nicidienase.chaosflix.common.entities.userdata.PlaybackProgress
import de.nicidienase.chaosflix.common.entities.userdata.WatchlistItem
import de.nicidienase.chaosflix.common.entities.recording.Conference
import de.nicidienase.chaosflix.common.entities.recording.ConferencesWrapper
import de.nicidienase.chaosflix.common.entities.recording.Event
import de.nicidienase.chaosflix.common.entities.recording.Recording
import de.nicidienase.chaosflix.common.entities.recording.persistence.ConferenceGroup
import de.nicidienase.chaosflix.common.entities.recording.persistence.PersistentConference
import de.nicidienase.chaosflix.common.entities.recording.persistence.PersistentEvent
import de.nicidienase.chaosflix.common.entities.recording.persistence.PersistentRecording
import de.nicidienase.chaosflix.common.entities.streaming.LiveConference
import de.nicidienase.chaosflix.common.entities.userdata.WatchlistItem
import de.nicidienase.chaosflix.common.network.RecordingService
import de.nicidienase.chaosflix.common.network.StreamingService
import de.nicidienase.chaosflix.touch.Util
import io.reactivex.Flowable
import io.reactivex.Observable
import io.reactivex.schedulers.Schedulers
@ -23,28 +25,82 @@ class BrowseViewModel(
val database: ChaosflixDatabase,
val recordingApi: RecordingService,
val streamingApi: StreamingService
) : ViewModel(){
) : ViewModel() {
fun getConferencesWrapper(): Observable<ConferencesWrapper>
= recordingApi.getConferences().subscribeOn(Schedulers.io())
fun getConferencesMap(): Flowable<Map<String,List<PersistentConference>>>{
updateConferencesAndGroups()
// database.conferenceDao().getAllConferences()
// .observeOn(Schedulers.io())
// .map { ConferencesWrapper(it.map { it.toConference() }) }
// .subscribeOn(Schedulers.io())
}
fun getConferencesByGroup(group: String): Observable<MutableList<Conference>>
= recordingApi.getConferences().map { t: ConferencesWrapper -> t.getListForTag(group) }
fun getConferenceGroups(): Flowable<ConferenceGroup> {
updateConferencesAndGroups()
return database.conferenceGroupDao().getAll()
}
fun getConference(mConferenceId: Long): Observable<Conference>
= recordingApi.getConference(mConferenceId).subscribeOn(Schedulers.io())
private fun updateConferencesAndGroups() {
recordingApi.getConferencesWrapper().observeOn(Schedulers.io()).subscribe { con: ConferencesWrapper? ->
if (con != null) {
con.conferenceMap.map { entry ->
val conferenceGroup: ConferenceGroup?
= database.conferenceGroupDao().getConferenceGroupByName(entry.key)
val groupId: Long
if (conferenceGroup != null) {
groupId = conferenceGroup.conferenceGroupId
} else {
val group = ConferenceGroup(entry.key)
val index = Util.orderedConferencesList.indexOf(group.name).toLong()
if (index != -1L)
group.index = index
groupId = database.conferenceGroupDao().addConferenceGroup(group)[0]
}
val conferenceList = entry.value
.map { PersistentConference(it) }
.map { it.conferenceGroupId = groupId; it }.toTypedArray()
database.conferenceDao().insertConferences(*conferenceList)
}
}
}
}
fun getEvent(apiID: Long): Observable<Event>
= recordingApi.getEvent(apiID).subscribeOn(Schedulers.io())
// = recordingApi.getConferences().subscribeOn(Schedulers.io())
fun getRecording(id: Long): Observable<Recording>
= recordingApi.getRecording(id).subscribeOn(Schedulers.io())
fun getConferencesByGroup(group: String): Flowable<List<PersistentConference>>
= database.conferenceGroupDao().getConferenceGroupByName(group)
.flatMap { database.conferenceDao().findConferenceByGroup(it.conferenceGroupId) }
.subscribeOn(Schedulers.io())
// = recordingApi.getConferences().map { t: ConferencesWrapper -> t.getListForTag(group) }
fun getConference(conferenceId: Long): Flowable<PersistentConference>
= database.conferenceDao().findConferenceById(conferenceId).subscribeOn(Schedulers.io())
// = recordingApi.getConference(conferenceId).subscribeOn(Schedulers.io())
//
// { conference: Conference ->
// val persistentConference = PersistentConference(conference)
// val events = conference.events?.map { PersistentEvent(it) }
// conference.events?.map { it.persons?.map { } }
// })
// return database.conferenceDao().findConferenceById(conferenceId)
// }
fun getEvent(apiID: Long): Flowable<PersistentEvent>
= database.eventDao().findEventById(apiID).subscribeOn(Schedulers.io())
// = recordingApi.getEvent(apiID).subscribeOn(Schedulers.io())
fun getEventsforConference(conferenceId: Long): Flowable<PersistentEvent>
= database.eventDao().findEventsByConference(conferenceId)
fun getRecordingForEvent(id: Long): Flowable<List<PersistentRecording>>?
= database.recordingDao().findRecordingByEvent(id)
.subscribeOn(Schedulers.io())
fun getStreamingConferences(): Observable<List<LiveConference>>
= streamingApi.getStreamingConferences().subscribeOn(Schedulers.io())
fun createBookmark(apiId: Long) {
database.watchlistItemDao().getItemForEvent(apiId)
.subscribe { watchlistItem: WatchlistItem? ->
@ -64,4 +120,80 @@ class BrowseViewModel(
.observeOn(Schedulers.io())
.subscribe { watchlistItem -> database.watchlistItemDao().deleteItem(watchlistItem) }
}
private val TAG: String = BrowseViewModel::class.simpleName.toString()
// fun updateDatabase() {
// recordingApi.getConferences()
// .subscribeOn(Schedulers.io())
// .observeOn(Schedulers.io())
// .subscribe { conferenceWrapper: ConferencesWrapper ->
// // Get ConferencesWrapper and from it a list of ConferenceGroups
// val conGroups: List<ConferenceGroup>
// = conferenceWrapper.conferenceMap.map { entry -> ConferenceGroup(entry.key) }
// // Save conference-groups
// database.conferenceGroupDao().addConferenceGroup(*conGroups.toTypedArray())
// // Get saved conference-groups and save all conferences
// database.conferenceGroupDao().getAll()
// .subscribeOn(Schedulers.io())
// .observeOn(Schedulers.io())
// .subscribe { list: List<ConferenceGroup> ->
// // Iterate over saved conference-groups and save all conferences
// // belonging to them
// for (group in list) {
// val groupList = conferenceWrapper.conferenceMap[group.name]
// if (groupList != null) {
// database.conferenceDao().insertConferences(*groupList
// .map { PersistentConference(it) }
// .map { it.conferenceGroupId = group.conferenceGroupId; it }
// .toTypedArray())
// }
// }
// // Load Events for all Conferences
// database.conferenceDao().getAllConferences()
// .subscribeOn(Schedulers.io())
// .observeOn(Schedulers.io())
// .subscribe { conferences: List<PersistentConference> ->
// updateEventsForConferences(conferences)
// }
// }
// }
// }
//
// private fun updateEventsForConferences(conferences: List<PersistentConference>) {
// for (con in conferences) {
// // Load all Events for one Conference
// recordingApi.getConference(con.conferenceId)
// .subscribeOn(Schedulers.io())
// .observeOn(Schedulers.io())
// .subscribe { con: Conference ->
// updateEventsForConference(con)
// }
// }
// }
//
// private fun updateEventsForConference(con: Conference) {
// val events = con.events ?: emptyList()
// val persistentEvents = events.map { PersistentEvent(it) }.toTypedArray()
// database.eventDao().insertEvent(*persistentEvents)
// database.eventDao().findEventsByConference(con.conferenceID)
// .observeOn(Schedulers.io())
// .subscribe({ events: List<PersistentEvent>? ->
// // Load Recordings for all Events
// updateRecordings(events)
// })
// }
//
// private fun updateRecordings(events: List<PersistentEvent>?) {
// for (event in events ?: emptyList()) {
// recordingApi.getEvent(event.eventId)
// .subscribeOn(Schedulers.io())
// .observeOn(Schedulers.io())
// .subscribe { event: Event? ->
// val recordings = event?.recordings ?: emptyList()
// val persistentRecordings = recordings.map { PersistentRecording(it) }.toTypedArray()
// database.recordingDao().insertRecording(*persistentRecordings)
// }
// }
// }
}

View file

@ -2,27 +2,26 @@ package de.nicidienase.chaosflix.touch.viewmodels
import android.arch.lifecycle.ViewModel
import de.nicidienase.chaosflix.common.entities.ChaosflixDatabase
import de.nicidienase.chaosflix.common.entities.recording.Event
import de.nicidienase.chaosflix.common.entities.recording.Recording
import de.nicidienase.chaosflix.common.entities.recording.persistence.PersistentEvent
import de.nicidienase.chaosflix.common.entities.recording.persistence.PersistentRecording
import de.nicidienase.chaosflix.common.entities.userdata.PlaybackProgress
import de.nicidienase.chaosflix.common.network.RecordingService
import de.nicidienase.chaosflix.common.network.StreamingService
import io.reactivex.Flowable
import io.reactivex.Observable
import io.reactivex.Single
import io.reactivex.schedulers.Schedulers
internal class PlayerViewModel(val database: ChaosflixDatabase,
val recordingApi: RecordingService,
val streamingApi: StreamingService) : ViewModel() {
fun getRecording(id: Long): Observable<Recording> = recordingApi.getRecording(id)
fun getRecording(id: Long): Flowable<List<PersistentRecording>> = database.recordingDao().findRecordingById(id)
fun getEvent(id: Long): Observable<Event> = recordingApi.getEvent(id)
fun getEvent(id: Long): Flowable<PersistentEvent> = database.eventDao().findEventById(id)
fun getPlaybackProgress(apiID: Long): Flowable<PlaybackProgress>
= database.playbackProgressDao().getProgressForEvent(apiID)
fun setPlaybackProgress(apiId: Long, progress: Long){
fun setPlaybackProgress(apiId: Long, progress: Long) {
Single.fromCallable {
database.playbackProgressDao().saveProgress(PlaybackProgress(apiId, progress))
}.subscribeOn(Schedulers.io()).subscribe()

View file

@ -4,7 +4,7 @@
<import type="android.text.TextUtils"/>
<variable
name="event"
type="de.nicidienase.chaosflix.common.entities.recording.Event"/>
type="de.nicidienase.chaosflix.common.entities.recording.persistence.PersistentEvent"/>
</data>
<android.support.design.widget.CoordinatorLayout

View file

@ -4,5 +4,7 @@
<item android:id="@+id/action_about"
app:showAsAction="never"
android:title="About"/>
<item android:id="@+id/action_update_database"
android:title="@string/update_database"/>
</menu>

View file

@ -10,4 +10,5 @@
<string name="bookmark">Bookmark</string>
<string name="play">Play</string>
<string name="titleimage">TitleImage</string>
<string name="update_database">Update Database</string>
</resources>