/* * Zirco Browser for Android * * Copyright (C) 2010 - 2011 J. Devauchelle and contributors. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * version 3 as published by the Free Software Foundation. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. */ package org.shadowsocks.zirco.ui.activities; import java.util.ArrayList; import java.util.Date; import java.util.List; import java.util.concurrent.atomic.AtomicReference; import org.emergent.android.weave.client.WeaveAccountInfo; import org.shadowsocks.R; import org.shadowsocks.zirco.model.DbAdapter; import org.shadowsocks.zirco.model.adapters.WeaveBookmarksCursorAdapter; import org.shadowsocks.zirco.model.items.WeaveBookmarkItem; import org.shadowsocks.zirco.providers.BookmarksProviderWrapper; import org.shadowsocks.zirco.providers.WeaveColumns; import org.shadowsocks.zirco.sync.ISyncListener; import org.shadowsocks.zirco.sync.WeaveSyncTask; import org.shadowsocks.zirco.ui.activities.preferences.WeavePreferencesActivity; import org.shadowsocks.zirco.utils.ApplicationUtils; import org.shadowsocks.zirco.utils.Constants; import android.app.Activity; import android.app.ProgressDialog; import android.content.DialogInterface; import android.content.DialogInterface.OnCancelListener; import android.content.Intent; import android.content.SharedPreferences.Editor; import android.database.Cursor; import android.os.AsyncTask; import android.os.Bundle; import android.os.Handler; import android.os.Message; import android.preference.PreferenceManager; import android.util.Log; import android.view.ContextMenu; import android.view.ContextMenu.ContextMenuInfo; import android.view.KeyEvent; import android.view.Menu; import android.view.MenuItem; import android.view.View; import android.view.View.OnClickListener; import android.view.animation.AlphaAnimation; import android.view.animation.Animation; import android.view.animation.AnimationSet; import android.view.animation.LayoutAnimationController; import android.view.animation.TranslateAnimation; import android.widget.AdapterView; import android.widget.AdapterView.AdapterContextMenuInfo; import android.widget.AdapterView.OnItemClickListener; import android.widget.Button; import android.widget.ImageButton; import android.widget.LinearLayout; import android.widget.ListAdapter; import android.widget.ListView; import android.widget.TextView; public class WeaveBookmarksListActivity extends Activity implements ISyncListener { private class Clearer implements Runnable { private Handler mHandler = new Handler() { @Override public void handleMessage(Message msg) { mProgressDialog.dismiss(); fillData(); } }; public Clearer() { new Thread(this).start(); } @Override public void run() { BookmarksProviderWrapper.clearWeaveBookmarks(getContentResolver()); mHandler.sendEmptyMessage(0); } } private static final int MENU_SYNC = Menu.FIRST; private static final int MENU_CLEAR = Menu.FIRST + 1; private static final int MENU_OPEN_IN_TAB = Menu.FIRST + 10; private static final int MENU_COPY_URL = Menu.FIRST + 11; private static final int MENU_SHARE = Menu.FIRST + 12; private static final String ROOT_FOLDER = "places"; private LinearLayout mNavigationView; private TextView mNavigationText; private ImageButton mNavigationBack; private ListView mListView; private Button mSetupButton; private Button mSyncButton; private View mEmptyView; private View mEmptyFolderView; private List<WeaveBookmarkItem> mNavigationList; private ProgressDialog mProgressDialog; private DbAdapter mDbAdapter; private Cursor mCursor = null; private WeaveSyncTask mSyncTask; private static final AtomicReference<AsyncTask<WeaveAccountInfo, Integer, Throwable>> mSyncThread = new AtomicReference<AsyncTask<WeaveAccountInfo, Integer, Throwable>>(); private void doClear() { mProgressDialog = ProgressDialog.show(this, this.getResources() .getString(R.string.Commons_PleaseWait), this.getResources() .getString(R.string.Commons_ClearingBookmarks)); new Clearer(); // Reset last sync date. Editor lastSyncDateEditor = PreferenceManager .getDefaultSharedPreferences(this).edit(); lastSyncDateEditor.putLong(Constants.PREFERENCE_WEAVE_LAST_SYNC_DATE, -1); lastSyncDateEditor.commit(); } private void doNavigationBack() { mNavigationList.remove(mNavigationList.size() - 1); if (mNavigationList.size() == 0) { mNavigationList.add(new WeaveBookmarkItem(getResources().getString( R.string.WeaveBookmarksListActivity_WeaveRootFolder), null, ROOT_FOLDER, true)); } fillData(); } private void doSync() { String authToken = ApplicationUtils.getWeaveAuthToken(this); if (authToken != null) { WeaveAccountInfo info = WeaveAccountInfo .createWeaveAccountInfo(authToken); mSyncTask = new WeaveSyncTask(this, this); mProgressDialog = new ProgressDialog(this); mProgressDialog.setIndeterminate(true); mProgressDialog.setTitle(R.string.WeaveSync_SyncTitle); mProgressDialog .setMessage(getString(R.string.WeaveSync_Connecting)); mProgressDialog.setCancelable(true); mProgressDialog.setOnCancelListener(new OnCancelListener() { @Override public void onCancel(DialogInterface dialog) { mSyncTask.cancel(true); } }); mProgressDialog.show(); boolean retVal = mSyncThread.compareAndSet(null, mSyncTask); if (retVal) { mSyncTask.execute(info); } } else { ApplicationUtils.showErrorDialog(this, R.string.Errors_WeaveSyncFailedTitle, R.string.Errors_WeaveAuthFailedMessage); } } private void fillData() { String[] from = { WeaveColumns.WEAVE_BOOKMARKS_TITLE, WeaveColumns.WEAVE_BOOKMARKS_URL }; int[] to = { R.id.BookmarkRow_Title, R.id.BookmarkRow_Url }; mCursor = BookmarksProviderWrapper.getWeaveBookmarksByParentId( getContentResolver(), mNavigationList.get(mNavigationList.size() - 1).getWeaveId()); ListAdapter adapter = new WeaveBookmarksCursorAdapter(this, R.layout.weave_bookmark_row, mCursor, from, to); if (adapter.isEmpty() && (mNavigationList.size() <= 1)) { mNavigationView.setVisibility(View.GONE); } else { mNavigationView.setVisibility(View.VISIBLE); } if (mNavigationList.size() > 1) { mNavigationBack.setEnabled(true); mListView.setEmptyView(mEmptyFolderView); } else { mNavigationBack.setEnabled(false); mListView.setEmptyView(mEmptyView); } mListView.setAdapter(adapter); setAnimation(); mNavigationText.setText(getNavigationText()); } private String getNavigationText() { StringBuilder sb = new StringBuilder(); for (WeaveBookmarkItem navigationItem : mNavigationList) { if (sb.length() != 0) { sb.append(" > "); } sb.append(navigationItem.getTitle()); } return sb.toString(); } @Override public boolean onContextItemSelected(MenuItem item) { AdapterContextMenuInfo info = (AdapterContextMenuInfo) item .getMenuInfo(); WeaveBookmarkItem bookmarkItem = BookmarksProviderWrapper .getWeaveBookmarkById(getContentResolver(), info.id); switch (item.getItemId()) { case MENU_OPEN_IN_TAB: Intent i = new Intent(); i.putExtra(Constants.EXTRA_ID_NEW_TAB, true); i.putExtra(Constants.EXTRA_ID_URL, bookmarkItem.getUrl()); if (getParent() != null) { getParent().setResult(RESULT_OK, i); } else { setResult(RESULT_OK, i); } finish(); return true; case MENU_COPY_URL: ApplicationUtils.copyTextToClipboard(this, bookmarkItem.getUrl(), getString(R.string.Commons_UrlCopyToastMessage)); return true; case MENU_SHARE: ApplicationUtils.sharePage(this, bookmarkItem.getTitle(), bookmarkItem.getUrl()); return true; default: return super.onContextItemSelected(item); } } @Override public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.weave_bookmarks_list_activity); mNavigationView = (LinearLayout) findViewById(R.id.WeaveBookmarksNavigationView); mNavigationText = (TextView) findViewById(R.id.WeaveBookmarksNavigationText); mNavigationBack = (ImageButton) findViewById(R.id.WeaveBookmarksNavigationBack); mListView = (ListView) findViewById(R.id.WeaveBookmarksList); mNavigationBack.setOnClickListener(new OnClickListener() { @Override public void onClick(View v) { doNavigationBack(); } }); mListView.setOnItemClickListener(new OnItemClickListener() { @Override public void onItemClick(AdapterView<?> arg0, View v, int position, long id) { WeaveBookmarkItem selectedItem = BookmarksProviderWrapper .getWeaveBookmarkById(getContentResolver(), id); if (selectedItem != null) { if (selectedItem.isFolder()) { mNavigationList.add(selectedItem); fillData(); } else { String url = selectedItem.getUrl(); if (url != null) { Intent result = new Intent(); result.putExtra(Constants.EXTRA_ID_NEW_TAB, false); result.putExtra(Constants.EXTRA_ID_URL, url); if (getParent() != null) { getParent().setResult(RESULT_OK, result); } else { setResult(RESULT_OK, result); } finish(); } } } } }); mEmptyView = findViewById(R.id.WeaveBookmarksEmptyView); mEmptyFolderView = findViewById(R.id.WeaveBookmarksEmptyFolderView); // mListView.setEmptyView(mEmptyView); mSetupButton = (Button) findViewById(R.id.WeaveBookmarksEmptyViewSetupButton); mSetupButton.setOnClickListener(new OnClickListener() { @Override public void onClick(View arg0) { startActivity(new Intent(WeaveBookmarksListActivity.this, WeavePreferencesActivity.class)); } }); mSyncButton = (Button) findViewById(R.id.WeaveBookmarksEmptyViewSyncButton); mSyncButton.setOnClickListener(new OnClickListener() { @Override public void onClick(View v) { doSync(); } }); mNavigationList = new ArrayList<WeaveBookmarkItem>(); mNavigationList.add(new WeaveBookmarkItem(getResources().getString( R.string.WeaveBookmarksListActivity_WeaveRootFolder), null, ROOT_FOLDER, true)); mDbAdapter = new DbAdapter(this); mDbAdapter.open(); registerForContextMenu(mListView); fillData(); } @Override public void onCreateContextMenu(ContextMenu menu, View v, ContextMenuInfo menuInfo) { super.onCreateContextMenu(menu, v, menuInfo); long id = ((AdapterContextMenuInfo) menuInfo).id; if (id != -1) { WeaveBookmarkItem item = BookmarksProviderWrapper .getWeaveBookmarkById(getContentResolver(), id); if (!item.isFolder()) { menu.setHeaderTitle(item.getTitle()); menu.add(0, MENU_OPEN_IN_TAB, 0, R.string.BookmarksListActivity_MenuOpenInTab); menu.add(0, MENU_COPY_URL, 0, R.string.BookmarksHistoryActivity_MenuCopyLinkUrl); menu.add(0, MENU_SHARE, 0, R.string.Main_MenuShareLinkUrl); } } } @Override public boolean onCreateOptionsMenu(Menu menu) { super.onCreateOptionsMenu(menu); MenuItem item = menu.add(0, MENU_SYNC, 0, R.string.WeaveBookmarksListActivity_MenuSync); item.setIcon(R.drawable.ic_menu_sync); item = menu.add(0, MENU_CLEAR, 0, R.string.WeaveBookmarksListActivity_MenuClear); item.setIcon(R.drawable.ic_menu_delete); return true; } @Override protected void onDestroy() { if (mCursor != null) { mCursor.close(); } mDbAdapter.close(); super.onDestroy(); } @Override public boolean onKeyUp(int keyCode, KeyEvent event) { switch (keyCode) { case KeyEvent.KEYCODE_BACK: if (mNavigationList.size() > 1) { doNavigationBack(); return true; } else { return super.onKeyUp(keyCode, event); } default: return super.onKeyUp(keyCode, event); } } @Override public boolean onMenuItemSelected(int featureId, MenuItem item) { switch (item.getItemId()) { case MENU_SYNC: doSync(); return true; case MENU_CLEAR: doClear(); return true; default: return super.onMenuItemSelected(featureId, item); } } @Override public void onSyncCancelled() { mSyncThread.compareAndSet(mSyncTask, null); mProgressDialog.dismiss(); fillData(); if (mSyncTask.isFullSync()) { // Reset last sync date is this was a full sync. Editor lastSyncDateEditor = PreferenceManager .getDefaultSharedPreferences(this).edit(); lastSyncDateEditor.putLong( Constants.PREFERENCE_WEAVE_LAST_SYNC_DATE, -1); lastSyncDateEditor.commit(); } } @Override public void onSyncEnd(Throwable result) { mSyncThread.compareAndSet(mSyncTask, null); if (result != null) { String msg = String.format( getResources().getString( R.string.Errors_WeaveSyncFailedMessage), result.getMessage()); Log.e("MainActivity: Sync failed.", msg); ApplicationUtils.showErrorDialog(this, R.string.Errors_WeaveSyncFailedTitle, msg); } else { Editor lastSyncDateEditor = PreferenceManager .getDefaultSharedPreferences(this).edit(); lastSyncDateEditor.putLong( Constants.PREFERENCE_WEAVE_LAST_SYNC_DATE, new Date().getTime()); lastSyncDateEditor.commit(); } mProgressDialog.dismiss(); fillData(); } @Override public void onSyncProgress(int step, int done, int total) { switch (step) { case 0: mProgressDialog .setMessage(getString(R.string.WeaveSync_Connecting)); break; case 1: mProgressDialog .setMessage(getString(R.string.WeaveSync_GettingData)); break; case 2: mProgressDialog.setMessage(String.format( getString(R.string.WeaveSync_ReadingData), done, total)); break; case 3: mProgressDialog .setMessage(getString(R.string.WeaveSync_WrittingData)); break; } } /** * Set the list loading animation. */ private void setAnimation() { AnimationSet set = new AnimationSet(true); Animation animation = new AlphaAnimation(0.0f, 1.0f); animation.setDuration(75); set.addAnimation(animation); animation = new TranslateAnimation(Animation.RELATIVE_TO_SELF, 0.0f, Animation.RELATIVE_TO_SELF, 0.0f, Animation.RELATIVE_TO_SELF, -1.0f, Animation.RELATIVE_TO_SELF, 0.0f); animation.setDuration(50); set.addAnimation(animation); LayoutAnimationController controller = new LayoutAnimationController( set, 0.5f); mListView.setLayoutAnimation(controller); } }