ConversationViewState.java revision 47aa9c991b33c722a6ba1946fc02e0aba17bc1c9
1/*
2 * Copyright (C) 2012 Google Inc.
3 * Licensed to The Android Open Source Project.
4 *
5 * Licensed under the Apache License, Version 2.0 (the "License");
6 * you may not use this file except in compliance with the License.
7 * You may obtain a copy of the License at
8 *
9 *      http://www.apache.org/licenses/LICENSE-2.0
10 *
11 * Unless required by applicable law or agreed to in writing, software
12 * distributed under the License is distributed on an "AS IS" BASIS,
13 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14 * See the License for the specific language governing permissions and
15 * limitations under the License.
16 */
17
18package com.android.mail.ui;
19
20import android.net.Uri;
21import android.os.Bundle;
22import android.os.Parcel;
23import android.os.Parcelable;
24
25import com.android.mail.providers.Conversation;
26import com.android.mail.providers.ConversationInfo;
27import com.android.mail.providers.Message;
28import com.google.common.collect.Maps;
29import com.google.common.collect.Sets;
30
31import org.json.JSONException;
32
33import java.util.Map;
34import java.util.Set;
35
36/**
37 * A small class to keep state for conversation view when restoring.
38 *
39 */
40class ConversationViewState implements Parcelable {
41
42    // N.B. don't serialize entire Messages because they contain body HTML/text
43
44    private final Map<Uri, MessageViewState> mMessageViewStates = Maps.newHashMap();
45
46    private String mConversationInfo;
47
48    public ConversationViewState() {}
49
50    /**
51     * Copy constructor that will copy overall conversation state, but NOT individual message state.
52     */
53    public ConversationViewState(ConversationViewState other) {
54        mConversationInfo = other.mConversationInfo;
55    }
56
57    public boolean isUnread(Message m) {
58        final MessageViewState mvs = mMessageViewStates.get(m.uri);
59        return (mvs != null && !mvs.read);
60    }
61
62    public void setReadState(Message m, boolean read) {
63        MessageViewState mvs = mMessageViewStates.get(m.uri);
64        if (mvs == null) {
65            mvs = new MessageViewState();
66        }
67        mvs.read = read;
68        mMessageViewStates.put(m.uri, mvs);
69    }
70
71    /**
72     * Returns the expansion state of a message in a conversation view. Expansion state only refers
73     * to the user action of expanding or collapsing a message view, and not any messages that
74     * are expanded by default (e.g. last message, starred messages).
75     *
76     * @param m a Message in the conversation
77     * @return true if the user expanded it, false if the user collapsed it, or null otherwise.
78     */
79    public Boolean getExpandedState(Message m) {
80        final MessageViewState mvs = mMessageViewStates.get(m.uri);
81        return (mvs == null ? null : mvs.expanded);
82    }
83
84    public void setExpandedState(Message m, boolean expanded) {
85        MessageViewState mvs = mMessageViewStates.get(m.uri);
86        if (mvs == null) {
87            mvs = new MessageViewState();
88        }
89        mvs.expanded = expanded;
90        mMessageViewStates.put(m.uri, mvs);
91    }
92
93    public String getConversationInfo() {
94        return mConversationInfo;
95    }
96
97    public void setInfoForConversation(Conversation conv) throws JSONException {
98        mConversationInfo = ConversationInfo.toString(conv.conversationInfo);
99    }
100
101    /**
102     * Returns URIs of all unread messages in the conversation per
103     * {@link #setReadState(Message, boolean)}. Returns an empty set for read conversations.
104     *
105     */
106    public Set<Uri> getUnreadMessageUris() {
107        final Set<Uri> result = Sets.newHashSet();
108        for (Uri uri : mMessageViewStates.keySet()) {
109            final MessageViewState mvs = mMessageViewStates.get(uri);
110            if (mvs != null && !mvs.read) {
111                result.add(uri);
112            }
113        }
114        return result;
115    }
116
117    public boolean contains(Message m) {
118        return mMessageViewStates.containsKey(m.uri);
119    }
120
121    @Override
122    public int describeContents() {
123        return 0;
124    }
125
126    @Override
127    public void writeToParcel(Parcel dest, int flags) {
128        final Bundle states = new Bundle();
129        for (Uri uri : mMessageViewStates.keySet()) {
130            final MessageViewState mvs = mMessageViewStates.get(uri);
131            states.putParcelable(uri.toString(), mvs);
132        }
133        dest.writeBundle(states);
134        dest.writeString(mConversationInfo);
135    }
136
137    private ConversationViewState(Parcel source) {
138        final Bundle states = source.readBundle(MessageViewState.class.getClassLoader());
139        for (String key : states.keySet()) {
140            final MessageViewState state = states.getParcelable(key);
141            mMessageViewStates.put(Uri.parse(key), state);
142        }
143        mConversationInfo = source.readString();
144    }
145
146    public static Parcelable.Creator<ConversationViewState> CREATOR =
147            new Parcelable.Creator<ConversationViewState>() {
148
149        @Override
150        public ConversationViewState createFromParcel(Parcel source) {
151            return new ConversationViewState(source);
152        }
153
154        @Override
155        public ConversationViewState[] newArray(int size) {
156            return new ConversationViewState[size];
157        }
158
159    };
160
161    // Keep per-message state in an inner Parcelable.
162    // This is a semi-private implementation detail.
163    static class MessageViewState implements Parcelable {
164
165        public boolean read;
166        /**
167         * null = default, false = collapsed, true = expanded
168         */
169        public Boolean expanded;
170
171        public MessageViewState() {}
172
173        @Override
174        public int describeContents() {
175            return 0;
176        }
177
178        @Override
179        public void writeToParcel(Parcel dest, int flags) {
180            dest.writeInt(read ? 1 : 0);
181            dest.writeInt(expanded == null ? -1 : (expanded ? 1 : 0));
182        }
183
184        private MessageViewState(Parcel source) {
185            read = (source.readInt() != 0);
186            final int expandedVal = source.readInt();
187            expanded = (expandedVal == -1) ? null : (expandedVal != 0);
188        }
189
190        @SuppressWarnings("hiding")
191        public static Parcelable.Creator<MessageViewState> CREATOR =
192                new Parcelable.Creator<MessageViewState>() {
193
194            @Override
195            public MessageViewState createFromParcel(Parcel source) {
196                return new MessageViewState(source);
197            }
198
199            @Override
200            public MessageViewState[] newArray(int size) {
201                return new MessageViewState[size];
202            }
203
204        };
205
206    }
207
208}
209