public class HackerNewsApplication extends SugarApp {
    private static boolean mDebug = BuildConfig.DEBUG;
    private static HackerNewsApplication sInstance;
    private Context mContext;
    private static AppComponent sAppComponent;

    private static AppModule sAppModule;

    @Override
    public void onCreate() {
        super.onCreate();
        if (sInstance == null) {
            sInstance = this;
        }

        if("release".equals(BuildConfig.BUILD_TYPE)){
            Bugsnag.init(this);
        }

        mContext = getApplicationContext();
        Stetho.initialize(
                Stetho.newInitializerBuilder(this)
                      .enableDumpapp(
                              Stetho.defaultDumperPluginsProvider(this))
                      .enableWebKitInspector(
                              Stetho.defaultInspectorModulesProvider(this))
                      .build());

        sAppModule = new AppModule(this);
        sAppComponent = DaggerAppComponent.builder()
                                          .appModule(sAppModule)
                                          .build();
        sAppComponent.inject(this);

        LocalDataManager.initialize(mContext);
    }

    public static boolean isDebug() {
        return mDebug;
    }

    public static HackerNewsApplication getInstance() {
        return sInstance;
    }

    public Context getContext() {
        return mContext;
    }

    public static AppComponent getAppComponent() {
        return sAppComponent;
    }

    public static AppModule getAppModule(){
        return sAppModule;
    }
} public class BaseViewModel {
    public void onAttachToView() {
    }

    public void onDetachFromView() {
    }
} public class Comment extends SugarRecord<Comment>{
    private Long mCommentId;
    private int mLevel;
    private boolean mOriginalPoster;
    private String mUser;
    private String mTimeAgo;
    private String mContent;
    private StoryDetail mStoryDetail;

    private boolean mHidden;

    public Comment() {
    }

    public Comment(Long commentId, int level, boolean originalPoster, String user, String timeAgo, String content, StoryDetail storyDetail) {
        mCommentId = commentId;
        mLevel = level;
        mOriginalPoster = originalPoster;
        mUser = user;
        mTimeAgo = timeAgo;
        mContent = content;
        mStoryDetail = storyDetail;
    }

    public long getCommentId() {
        return mCommentId;
    }

    public int getLevel() {
        return mLevel;
    }

    public String getUser() {
        return mUser;
    }

    public String getTimeAgo() {
        return mTimeAgo;
    }

    public String getContent() {
        return mContent;
    }

    public void setCommentId(Long commentId) {
        mCommentId  = commentId;
    }

    public void setLevel(int level) {
        mLevel = level;
    }

    public void setUser(String user) {
        mUser = user;
    }

    public void setTimeAgo(String timeAgo) {
        mTimeAgo = timeAgo;
    }

    public void setContent(String content) {
        mContent = content;
    }

    public boolean isOriginalPoster() {
        return mOriginalPoster;
    }

    public void setOriginalPoster(boolean originalPoster) {
        mOriginalPoster = originalPoster;
    }

    public boolean isHidden() {
        return mHidden;
    }

    public void setHidden(boolean hidden) {
        mHidden = hidden;
    }

} public class StoryDetail extends SugarRecord<StoryDetail>{
    @Retention(RetentionPolicy.SOURCE)
    @StringDef({JOB, LINK, ASK})
    public @interface StoryType{}
    public static final String JOB = "job";
    public static final String LINK = "link";
    public static final String ASK = "ask";
    public static final String STORY_DETAIL_ID = "mStoryDetailId";

    private Long mStoryDetailId;
    private String mTitle;
    private String mUrl;
    private String mDomain;
    private Integer mPoints;
    private String mUser;
    private String mTimeAgo;
    private Integer mCommentsCount;
    private String mContent;
    @Ignore private Object mPoll;
    private String mLink;
    @Ignore private List<Comment> mCommentList;
    private Long mMoreCommentsId;
    private String mType;

    public StoryDetail() {
    }

    public StoryDetail(Long storyDetailId, String title, String url,
                       String domain, Integer points, String user,
                       String timeAgo, Integer commentsCount, String content,
                       Object poll, String link, List<Comment> commentList,
                       Long moreCommentsId, @StoryType String type) {
        mStoryDetailId = storyDetailId;
        mTitle = title;
        mUrl = url;
        mDomain = domain;
        mPoints = points;
        mUser = user;
        mTimeAgo = timeAgo;
        mCommentsCount = commentsCount;
        mContent = content;
        mPoll = poll;
        mLink = link;
        mCommentList = commentList;
        mMoreCommentsId = moreCommentsId;
        mType = type;
    }

    public Long getStoryDetailId() {
        return mStoryDetailId;
    }

    public String getTitle() {
        return mTitle;
    }

    public String getUrl() {
        return mUrl;
    }

    public String getDomain() {
        return mDomain;
    }

    public Integer getPoints() {
        return mPoints;
    }

    public String getUser() {
        return mUser;
    }

    public String getTimeAgo() {
        return mTimeAgo;
    }

    public int getCommentsCount() {
        return mCommentsCount;
    }

    public String getContent() {
        return mContent;
    }

    public Object getPoll() {
        return mPoll;
    }

    public String getLink() {
        return mLink;
    }

    public List<Comment> getCommentList() {
        return mCommentList;
    }

    public void setCommentList(List<Comment> commentList) {
        mCommentList = commentList;
    }

    public Long getMoreCommentsId() {
        return mMoreCommentsId;
    }

    @StoryType
    public String getType() {
        return mType;
    }

    public void setUrl(String url) {
        mUrl = url;
    }
} public class User extends SugarRecord<User>{
    private String userName;
    private String userCookie;
    private boolean isCurrentUser;

    public User() {
    }

    public User(String userName, String userCookie, boolean isCurrentUser) {
        this.userName = userName;
        this.userCookie = userCookie;
        this.isCurrentUser = isCurrentUser;
    }

    public String getUserName() {
        return userName;
    }

    public void setUserName(String userName) {
        this.userName = userName;
    }

    public String getUserCookie() {
        return userCookie;
    }

    public void setUserCookie(String userCookie) {
        this.userCookie = userCookie;
    }

    public boolean isCurrentUser() {
        return isCurrentUser;
    }

    public void setIsCurrentUser(boolean isCurrentUser) {
        this.isCurrentUser = isCurrentUser;
    }

    public static boolean isLoggedIn() {
        return count(User.class, null, null) > 0;
    }

} public interface HackerNewsService {
    @GET("/news")
    void getTopStories(Callback<List<NodeHNAPIStory>> callback);

    @GET("/news")
    Observable<List<NodeHNAPIStory>> getTopStories();

    @GET("/news2")
    void getTopStoriesPageTwo(Callback<List<NodeHNAPIStory>> callback);

    @GET("/news2")
    Observable<List<NodeHNAPIStory>> getTopStoriesPageTwo();

    @GET("/newest")
    void getNewestStories(Callback<List<NodeHNAPIStory>> callback);

    @GET("/newest")
    Observable<List<NodeHNAPIStory>> getNewestStories();

    @GET("/best")
    void getBestStories(Callback<List<NodeHNAPIStory>> callback);

    @GET("/best")
    Observable<List<NodeHNAPIStory>> getBestStories();

    @GET("/show")
    Observable<List<NodeHNAPIStory>> getShowStories();

    @GET("/shownew")
    Observable<List<NodeHNAPIStory>> getShowNewStories();

    @GET("/ask")
    Observable<List<NodeHNAPIStory>> getAskStories();

    @GET("/item/{itemId}")
    void getItemDetails(@Path("itemId") long itemId, Callback<NodeHNAPIStoryDetail> callback);

    @GET("/item/{itemId}")
    Observable<NodeHNAPIStoryDetail> getItemDetails(@Path("itemId") long itemId);

} public interface UserService {
    @FormUrlEncoded
    @POST("/comment")
    Observable<Object> postComment(@Header("Cookie") String cookie,
                                   @Field("goto") String gotoParam,
                                   @Field("hmac") String hmac,
                                   @Field("parent") Long parentId,
                                   @Field("text") String text);

    @GET("/vote")
    Observable<Object> vote(@Header("Cookie") String cookie,
                            @Query("for") Long parentId,
                            @Query("dir") String direction,
                            @Query("auth") String auth,
                            @Query("goto") String gotoParam);
} @JsonObject(fieldNamingPolicy = JsonObject.FieldNamingPolicy.LOWER_CASE_WITH_UNDERSCORES)
public class NodeHNAPIComment {
    @JsonField public Long id;
    @JsonField public int level;
    @JsonField public String user;
    @JsonField public String timeAgo;
    @JsonField public String content;
    @JsonField public List<NodeHNAPIComment> comments;
} @JsonObject
public class NodeHNAPIStoryDetail {
    @JsonField(name = "id") public Long id;
    @JsonField(name = "title") public String title;
    @JsonField(name = "url") public String url;
    @JsonField(name = "domain") public String domain;
    @JsonField(name = "points") public Integer points;
    @JsonField(name = "user") public String user;
    @JsonField(name = "time_ago") public String timeAgo;
    @JsonField(name = "comments_count") public Integer commentsCount;
    @JsonField(name = "content") public String content;
    @JsonField(name = "poll") public Object poll;
    @JsonField(name = "link") public String link;
    @JsonField(name = "comments") public List<NodeHNAPIComment> commentList;
    @JsonField(name = "more_comments_id") public Long moreCommentsId;
    @JsonField(name = "type") public String type;

} public class UserPreferenceManager {

    public static final String SHOULD_USE_EXTERNAL_BROWSER = "pref_system_browser";
    public static final String PREF_LINK_FIRST = "pref_link_first";
    public static final String PREF_LIST_ANIMATIONS = "pref_list_animations";
    public static final String PREF_NIGHT_MODE = "pref_night_mode";
    public static final String PREF_TEXT_SIZE = "pref_text_size";
    public static final String PREF_SWIPE_BACK = "pref_swipe_back";

    @Retention(RetentionPolicy.SOURCE)
    @StringDef({SMALL, MEDIUM, LARGE})
    public @interface TextSize{}
    public static final String SMALL = "small";
    public static final String MEDIUM = "medium";
    public static final String LARGE = "large";

    public static UserPreferenceManager sInstance;
    @Inject SharedPreferences mSharedPreferences;

    public static UserPreferenceManager getInstance(){
        if(sInstance == null){
            sInstance = new UserPreferenceManager();
        }
        return sInstance;
    }

    public UserPreferenceManager() {
        DaggerSharedPreferencesComponent.builder()
                .appModule(HackerNewsApplication.getAppModule())
                .appComponent(HackerNewsApplication.getAppComponent())
                .build()
                .inject(this);
        sInstance = this;
    }

    public boolean showLinkFirst(){
        return mSharedPreferences.getBoolean(PREF_LINK_FIRST, false);
    }

    public @TextSize String getPreferredTextSize(){
        //noinspection ResourceType
        return mSharedPreferences.getString(PREF_TEXT_SIZE, SMALL);
    }

    public boolean isExternalBrowserEnabled(){
        return mSharedPreferences.getBoolean(SHOULD_USE_EXTERNAL_BROWSER, false);
    }

    public void registerOnSharedPreferenceChangeListener(SharedPreferences.OnSharedPreferenceChangeListener listener) {
        mSharedPreferences.registerOnSharedPreferenceChangeListener(listener);
    }

    public void unregisterOnSharedPreferenceChangeListener(SharedPreferences.OnSharedPreferenceChangeListener listener) {
        mSharedPreferences.unregisterOnSharedPreferenceChangeListener(listener);
    }

    public boolean isNightModeEnabled(){
        return mSharedPreferences.getBoolean(PREF_NIGHT_MODE, false);
    }

    public boolean isSwipeBackEnabled(){
        return mSharedPreferences.getBoolean(PREF_SWIPE_BACK, true);
    }
}
import android.support.annotation.ArrayRes;
import android.support.annotation.NonNull;
import android.support.annotation.Nullable;
import com.orm.StringUtil;
import com.orm.query.Condition;
import com.orm.query.Select;
import java.io.UnsupportedEncodingException;
import java.net.URLDecoder;
import java.util.ArrayList;
import java.util.List;
import javax.inject.Inject;
import io.dwak.holohackernews.app.HackerNewsApplication;
import io.dwak.holohackernews.app.R;
import io.dwak.holohackernews.app.base.BaseViewModel;
import io.dwak.holohackernews.app.dagger.component.DaggerNetworkServiceComponent;
import io.dwak.holohackernews.app.models.Comment;
import io.dwak.holohackernews.app.models.StoryDetail;
import io.dwak.holohackernews.app.models.User;
import io.dwak.holohackernews.app.network.HackerNewsService;
import io.dwak.holohackernews.app.network.UserService;
import io.dwak.holohackernews.app.network.models.NodeHNAPIComment;
import io.dwak.holohackernews.app.network.models.NodeHNAPIStoryDetail;
import io.dwak.holohackernews.app.preferences.UserPreferenceManager;
import rx.Observable;
import rx.Subscriber;
package io.dwak.holohackernews.app.ui.storydetail;






public class StoryDetailViewModel extends BaseViewModel {
    public static final String HACKER_NEWS_BASE_URL = "https://news.ycombinator.com/";
    private final String ITEM_PREFIX = "item?id=";
    private Observable<NodeHNAPIStoryDetail> mItemDetails;
    private long mStoryId;
    private StoryDetail mStoryDetail;
    private boolean mSaved;
    @Inject HackerNewsService mService;
    @Inject UserService mUserService;
    private boolean mIsViewingReadability;
    private Observable<String> mUserTokenObservable = Observable.<String>create(subscriber -> {
        User user = Select.from(User.class)