/*
* Copyright 2013 Square Inc.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.example.mortar.screen;
import android.support.annotation.Nullable;
import android.util.Log;
import com.example.mortar.R;
import com.example.mortar.android.ActionBarOwner;
import com.example.mortar.core.SingletonComponent;
import com.example.mortar.model.Chat;
import com.example.mortar.model.Chats;
import com.example.mortar.model.Message;
import com.example.mortar.util.BaseKey;
import com.example.mortar.util.DaggerService;
import com.example.mortar.util.Subscope;
import com.example.mortar.util.ViewPresenter;
import com.example.mortar.view.ChatView;
import com.example.mortar.view.Confirmation;
import com.zhuinden.servicetree.ServiceTree;
import com.zhuinden.simplestack.navigator.Navigator;
import com.zhuinden.statebundle.StateBundle;
import javax.inject.Inject;
import dagger.Provides;
import io.reactivex.disposables.Disposable;
import io.reactivex.disposables.Disposables;
import io.reactivex.functions.Action;
import io.reactivex.observers.DisposableObserver;
import mortar.PopupPresenter;
public class ChatScreen
extends BaseKey {
private final int conversationIndex;
public ChatScreen(int conversationIndex) {
this.conversationIndex = conversationIndex;
}
@Override
public void bindServices(ServiceTree.Node node) {
SingletonComponent singletonComponent = DaggerService.get(node);
node.bindService(DaggerService.SERVICE_NAME, //
DaggerChatScreen_Component.builder() //
.singletonComponent(singletonComponent) //
.module(new Module(conversationIndex)) //
.build());
node.bindService("PRESENTER", DaggerService.<Component>get(node).presenter()); // <-- for Bundleable callback
}
@Override
public int layout() {
return R.layout.chat_view;
}
@dagger.Component(dependencies = {SingletonComponent.class}, modules = {Module.class})
@Subscope
public interface Component extends SingletonComponent {
Presenter presenter();
void inject(ChatView chatView);
}
@dagger.Module
public static class Module {
private final int conversationIndex;
public Module(int conversationIndex) {
this.conversationIndex = conversationIndex;
}
@Provides
Chat conversation(Chats chats) {
return chats.getChat(conversationIndex);
}
}
@Override
public int hashCode() {
return 37 + ChatScreen.class.hashCode() + 37 * conversationIndex;
}
@Override
public boolean equals(Object obj) {
return obj != null && obj instanceof ChatScreen && ((ChatScreen) obj).conversationIndex == conversationIndex;
}
@Override
public String toString() {
return "ChatScreen{" + "conversationIndex=" + conversationIndex + '}';
}
@Subscope
public static class Presenter
extends ViewPresenter<ChatView>
implements ServiceTree.Scoped {
private final Chat chat;
private final ActionBarOwner actionBar;
private final PopupPresenter<Confirmation, Boolean> confirmer;
private Disposable running = Disposables.empty();
@Inject
public Presenter(Chat chat, ActionBarOwner actionBar) {
this.chat = chat;
this.actionBar = actionBar;
this.confirmer = new PopupPresenter<Confirmation, Boolean>() {
@Override
protected void onPopupResult(Boolean confirmed) {
if(confirmed) {
Presenter.this.getView().toast("Haven't implemented that, friend.");
}
}
};
}
@Override
public void dropView(ChatView view) {
confirmer.dropView(view.getConfirmerPopup());
super.dropView(view);
}
@Override
public void onLoad(@Nullable StateBundle savedInstanceState) {
if(!hasView()) {
return;
}
ActionBarOwner.Config actionBarConfig = actionBar.getConfig();
actionBarConfig = actionBarConfig.withAction(new ActionBarOwner.MenuAction("End", new Action() {
@Override
public void run() {
confirmer.show(new Confirmation("End Chat",
"Do you really want to leave this chat?",
"Yes",
"I guess not"));
}
}));
actionBar.setConfig(actionBarConfig);
confirmer.takeView(getView().getConfirmerPopup());
running = chat.getMessages().subscribeWith(new DisposableObserver<Message>() {
@Override
public void onComplete() {
Log.w(getClass().getName(), "That's surprising, never thought this should end.");
running = Disposables.empty();
}
@Override
public void onError(Throwable e) {
Log.w(getClass().getName(), "'sploded, will try again on next config change.");
Log.w(getClass().getName(), e);
running = Disposables.empty();
}
@Override
public void onNext(Message message) {
if(!hasView()) {
return;
}
getView().getItems().add(message);
}
});
}
@Override
public void onExitScope() {
ensureStopped();
}
public void onConversationSelected(int position) {
Navigator.getBackstack(getView().getContext()).goTo(new MessageScreen(chat.getId(), position));
}
public void visibilityChanged(boolean visible) {
if(!visible) {
ensureStopped();
}
}
private void ensureStopped() {
running.dispose();
}
}
}