1 package pl
.blip
.divide
.bliper
;
3 import java
.util
.concurrent
.Executors
;
4 import java
.util
.concurrent
.ScheduledExecutorService
;
5 import java
.util
.concurrent
.TimeUnit
;
6 import java
.util
.regex
.Matcher
;
7 import java
.util
.regex
.Pattern
;
9 import pl
.blip
.divide
.bliper
.DashboardView
.DashboardAdapter
;
10 import android
.app
.Activity
;
11 import android
.content
.AsyncQueryHandler
;
12 import android
.content
.ContentValues
;
13 import android
.content
.Intent
;
14 import android
.database
.Cursor
;
15 import android
.net
.Uri
;
16 import android
.os
.Bundle
;
17 import android
.view
.KeyEvent
;
18 import android
.view
.View
;
19 import android
.view
.View
.OnClickListener
;
20 import android
.view
.View
.OnFocusChangeListener
;
21 import android
.widget
.AdapterView
;
22 import android
.widget
.Button
;
23 import android
.widget
.EditText
;
24 import android
.widget
.ImageView
;
25 import android
.widget
.TextView
;
26 import android
.widget
.Toast
;
27 import android
.widget
.AdapterView
.OnItemClickListener
;
28 import android
.widget
.TextView
.OnEditorActionListener
;
30 public class Dashboard
extends Activity
{
31 public class SendListener
implements OnClickListener
, OnEditorActionListener
{
32 public void onClick(View v
) {
36 private void doSend() {
37 if (newStatus
== null)
39 newStatus
= insertingStatus
= myStatusView
.getText().toString();
41 final ContentValues cv
= new ContentValues();
42 cv
.put("update[body]", newStatus
);
43 myselfHandler
.startInsert(0, null, Blip
.Updates
.CONTENT_URI
, cv
);
47 public boolean onEditorAction(TextView v
, int actionId
, KeyEvent event
) {
48 if (event
== null || event
.getAction() != KeyEvent
.ACTION_UP
)
55 private ImageView myAvatarView
;
57 private String currentStatus
= null;
58 private String newStatus
= null;
59 private String insertingStatus
= null;
61 private class MyselfHandler
extends AsyncQueryHandler
{
62 private final String
[] PROJECTION
= { "current_status/body", "avatar/url_50" };
63 private final int BODY_COLUMN
= 0, AVATAR_COLUMN
= 1;
66 public MyselfHandler(String login
) {
67 super(getContentResolver());
68 this.uri
= Uri
.withAppendedPath(Blip
.Users
.CONTENT_URI
, login
);
71 private void startQuery() {
72 startQuery(0, null, uri
, PROJECTION
, null, null, null);
76 protected void onQueryComplete(int token
, Object cookie
, Cursor cursor
) {
77 super.onQueryComplete(token
, cookie
, cursor
);
79 if (cursor
== null || !cursor
.moveToFirst()) {
81 Toast
.makeText(Dashboard
.this, R
.string
.connection_unsuccessful
, Toast
.LENGTH_LONG
).show();
90 currentStatus
= cursor
.getString(BODY_COLUMN
);
92 if (!myStatusView
.hasFocus() && newStatus
== null)
93 myStatusView
.setText(currentStatus
);
95 if (myAvatarView
!= null)
96 myAvatarView
.setImageURI(Uri
.withAppendedPath(Blip
.CONTENT_URI
, cursor
.getString(AVATAR_COLUMN
)));
100 protected void onInsertComplete(int token
, Object cookie
, Uri uri
) {
101 super.onInsertComplete(token
, cookie
, uri
);
104 if (!insertingStatus
.matches("^>>?.*:.*"))
105 currentStatus
= insertingStatus
;
107 updateMyStatus(true);
108 updateMyStatus(myStatusView
.hasFocus());
110 if (updatesView
!= null)
111 updatesView
.updateNow();
116 private String login
;
117 private boolean initialized
= false;
118 private EditText myStatusView
;
119 private MyselfHandler myselfHandler
;
120 private ScheduledExecutorService executor
;
121 private DashboardView updatesView
;
122 private OnFocusChangeListener myStatusViewFocusWatcher
= new OnFocusChangeListener() {
124 public void onFocusChange(View v
, boolean hasFocus
) {
125 updateMyStatus(hasFocus
);
129 private Button sendButton
;
131 private SendListener sendListener
= new SendListener();
134 protected void onCreate(Bundle savedInstanceState
) {
135 super.onCreate(savedInstanceState
);
137 login
= Blip
.getUsername(this);
140 Intent i
= new Intent(this, LoginActivity
.class);
146 myselfHandler
= new MyselfHandler(login
);
147 myselfHandler
.startQuery();
149 setContentView(R
.layout
.dashboard
);
150 myStatusView
= (EditText
) findViewById(R
.id
.status
);
154 protected void onRestoreInstanceState(Bundle savedInstanceState
) {
155 super.onRestoreInstanceState(savedInstanceState
);
157 // in case we were just thawed by Android, retrieve the status
158 final String status
= myStatusView
.getText().toString();
159 if (status
.length() > 0)
163 public void updateMyStatus(boolean hasFocus
) {
165 if (newStatus
== null) {
167 myStatusView
.setText(newStatus
);
169 myStatusView
.setBackgroundResource(android
.R
.drawable
.edit_text
);
170 myStatusView
.setTextColor(getResources().getColorStateList(android
.R
.color
.primary_text_light
));
172 newStatus
= myStatusView
.getText().toString();
173 if (newStatus
== null || newStatus
.length() == 0) {
175 myStatusView
.setText(currentStatus
);
176 myStatusView
.setBackgroundResource(R
.drawable
.textfield_default_dormant
);
177 myStatusView
.setTextColor(getResources().getColorStateList(R
.drawable
.custom_status_textfield_color
));
181 // TODO make it extract values from XML or whatever
182 myStatusView
.setPadding(5, 2, 37, 5);
185 public void finishInitializing() {
186 setTitle(R
.string
.dashboard
);
188 myAvatarView
= (ImageView
) findViewById(R
.id
.avatar
);
189 updatesView
= (DashboardView
) findViewById(R
.id
.updates
);
190 sendButton
= (Button
) findViewById(R
.id
.send
);
192 myStatusView
.setOnFocusChangeListener(myStatusViewFocusWatcher
);
193 myStatusView
.setOnEditorActionListener(sendListener
);
195 updatesView
.bindDashboard();
196 updatesView
.startUpdating();
197 updatesView
.setOnItemClickListener(new OnItemClickListener() {
199 public void onItemClick(AdapterView
<?
> view
, View itemView
, int position
, long id
) {
200 tryToQuote(position
);
204 sendButton
.setOnClickListener(sendListener
);
205 sendButton
.requestFocus();
210 protected void tryToQuote(int position
) {
211 Cursor c
= (Cursor
) updatesView
.getAdapter().getItem(position
);
212 final String type
= c
.getString(DashboardAdapter
.TYPE_COLUMN
);
213 String user
= c
.getString(DashboardAdapter
.AUTHOR_COLUMN
);
214 if (user
.equals(login
)) {
215 final String recipient
= c
.getString(DashboardAdapter
.RECIPIENT_COLUMN
);
216 if (recipient
!= null)
222 final StringBuilder messageBuilder
= new StringBuilder();
223 if (type
.equals(Blip
.PRIVATE_MESSAGE_TYPE
))
224 messageBuilder
.append(">>" + user
+ ": ");
226 messageBuilder
.append(">" + user
+ ": ");
228 if (newStatus
!= null) {
229 newStatus
= myStatusView
.getText().toString();
230 Matcher m
= Pattern
.compile("^>>?.*?: *(.*)$").matcher(newStatus
);
232 messageBuilder
.append(m
.group(1));
235 myStatusView
.requestFocus();
236 newStatus
= messageBuilder
.toString();
237 myStatusView
.setText(newStatus
);
238 myStatusView
.setSelection(newStatus
.length());
241 private void scheduleQuerying() {
242 executor
= Executors
.newSingleThreadScheduledExecutor();
243 Runnable requeryMyselfCommand
= new Runnable() {
246 myselfHandler
.startQuery();
249 executor
.scheduleAtFixedRate(requeryMyselfCommand
, 20, 20, TimeUnit
.SECONDS
);
253 protected void onPause() {
255 MessagePoller
.startPolling(this);
259 protected void onResume() {
261 MessagePoller
.stopPolling(this);
265 protected void onStop() {
267 executor
.shutdownNow();
268 if (updatesView
!= null)
269 updatesView
.stopUpdating();
273 protected void onStart() {
276 myselfHandler
.startQuery();
279 if (updatesView
!= null)
280 updatesView
.startUpdating();
284 public void onUserInteraction() {
285 super.onUserInteraction();
286 updatesView
.onUserInteraction();