@Override public final void prepare(final Context context, final LinearLayout items) { final LoadingView loadingView = new LoadingView(context, R.string.download_waiting, true, true); items.addView(loadingView); username = getArguments().getString("user"); final CacheManager cm = CacheManager.getInstance(context); RedditAPI.getUser( cm, username, new APIResponseHandler.UserResponseHandler(context) { @Override protected void onDownloadStarted() { if (!active) return; loadingView.setIndeterminate(R.string.download_connecting); } @Override protected void onSuccess(final RedditUser user, long timestamp) { new Handler(Looper.getMainLooper()) .post( new Runnable() { public void run() { if (!active) return; loadingView.setDone(R.string.download_done); final LinearLayout karmaLayout = (LinearLayout) getLayoutInflater().inflate(R.layout.karma); items.addView(karmaLayout); final TextView linkKarma = (TextView) karmaLayout.findViewById(R.id.layout_karma_text_link); final TextView commentKarma = (TextView) karmaLayout.findViewById(R.id.layout_karma_text_comment); linkKarma.setText(String.valueOf(user.link_karma)); commentKarma.setText(String.valueOf(user.comment_karma)); items.addView( propView( context, R.string.userprofile_created, RRTime.formatDateTime(user.created_utc * 1000, context), false)); if (user.has_mail != null) { items.addView( propView( context, R.string.userprofile_hasmail, user.has_mail ? R.string.general_true : R.string.general_false, false)); } if (user.has_mod_mail != null) { items.addView( propView( context, R.string.userprofile_hasmodmail, user.has_mod_mail ? R.string.general_true : R.string.general_false, false)); } if (user.is_friend) { items.addView( propView( context, R.string.userprofile_isfriend, R.string.general_true, false)); } if (user.is_gold) { items.addView( propView( context, R.string.userprofile_isgold, R.string.general_true, false)); } if (user.is_mod) { items.addView( propView( context, R.string.userprofile_moderator, R.string.general_true, false)); } final Button commentsButton = new Button(context); commentsButton.setText(R.string.userprofile_viewcomments); commentsButton.setOnClickListener( new View.OnClickListener() { public void onClick(View v) { final Intent intent = new Intent(context, CommentListingActivity.class); intent.setData( Uri.parse( Constants.Reddit.getUri( "/user/" + username + "/comments.json") .toString())); startActivity(intent); dismiss(); } }); items.addView(commentsButton); // TODO use margin? or framelayout? scale padding dp // TODO change button color commentsButton.setPadding(20, 20, 20, 20); final Button postsButton = new Button(context); postsButton.setText(R.string.userprofile_viewposts); postsButton.setOnClickListener( new View.OnClickListener() { public void onClick(View v) { final Intent intent = new Intent(context, PostListingActivity.class); intent.putExtra( "subreddit", new RedditSubreddit( "/user/" + username + "/submitted", "Submitted by " + username, false)); startActivity(intent); dismiss(); } }); items.addView(postsButton); // TODO use margin? or framelayout? scale padding dp postsButton.setPadding(20, 20, 20, 20); } }); } @Override protected void onCallbackException(Throwable t) { BugReportActivity.handleGlobalError(context, t); } @Override protected void onFailure( final RequestFailureType type, final Throwable t, final StatusLine status, final String readableMessage) { new Handler(Looper.getMainLooper()) .post( new Runnable() { public void run() { if (!active) return; loadingView.setDone(R.string.download_failed); final RRError error = General.getGeneralErrorForFailure(context, type, t, status); items.addView(new ErrorView(getSupportActivity(), error)); } }); } @Override protected void onFailure(final APIFailureType type) { new Handler(Looper.getMainLooper()) .post( new Runnable() { public void run() { if (!active) return; loadingView.setDone(R.string.download_failed); final RRError error = General.getGeneralErrorForFailure(context, type); items.addView(new ErrorView(getSupportActivity(), error)); } }); } }, RedditAccountManager.getInstance(context).getDefaultAccount(), CacheRequest.DownloadType.FORCE, true, context); }
public void reset(final int listPosition, final ImageInfo info) { mImageInfo = info; if (info.title == null || info.title.trim().isEmpty()) { mTitle.setText("Image " + (listPosition + 1)); } else { mTitle.setText((listPosition + 1) + ". " + info.title.trim()); } String subtitle = ""; if (info.type != null) { subtitle += info.type; } if (info.width != null && info.height != null) { if (!subtitle.isEmpty()) subtitle += ", "; subtitle += info.width + "x" + info.height; } if (info.size != null) { if (!subtitle.isEmpty()) subtitle += ", "; long size = info.size; if (size < 512 * 1024) { subtitle += String.format("%.1f kB", (float) size / 1024); } else { subtitle += String.format("%.1f MB", (float) size / (1024 * 1024)); } } if (subtitle.isEmpty()) { mSubtitle.setVisibility(GONE); } else { mSubtitle.setVisibility(VISIBLE); } mSubtitle.setText(subtitle); mThumbnail.setImageBitmap(null); final boolean isConnectionWifi = General.isConnectionWifi(getContext()); final PrefsUtility.AppearanceThumbnailsShow thumbnailsPref = PrefsUtility.appearance_thumbnails_show( getContext(), PreferenceManager.getDefaultSharedPreferences(getContext())); final boolean downloadThumbnails = thumbnailsPref == PrefsUtility.AppearanceThumbnailsShow.ALWAYS || (thumbnailsPref == PrefsUtility.AppearanceThumbnailsShow.WIFIONLY && isConnectionWifi); if (!downloadThumbnails) { mThumbnail.setVisibility(GONE); } else { mThumbnail.setVisibility(VISIBLE); CacheManager.getInstance(getContext()) .makeRequest( new CacheRequest( General.uriFromString(info.urlBigSquare), RedditAccountManager.getAnon(), null, Constants.Priority.THUMBNAIL, listPosition, CacheRequest.DownloadType.IF_NECESSARY, Constants.FileType.THUMBNAIL, CacheRequest.DownloadQueueType.IMMEDIATE, false, false, getContext()) { @Override protected void onCallbackException(final Throwable t) { Log.e("ImgurAlbumListEntryView", "Error in album thumbnail fetch callback", t); } @Override protected void onDownloadNecessary() {} @Override protected void onDownloadStarted() {} @Override protected void onFailure( final RequestFailureType type, final Throwable t, final Integer status, final String readableMessage) { Log.e("ImgurAlbumListEntryView", "Failed to fetch thumbnail " + url.toString()); } @Override protected void onProgress( final boolean authorizationInProgress, final long bytesRead, final long totalBytes) {} @Override protected void onSuccess( final CacheManager.ReadableCacheFile cacheFile, final long timestamp, final UUID session, final boolean fromCache, final String mimetype) { if (mImageInfo != info) return; // TODO post message rather than runnable AndroidApi.UI_THREAD_HANDLER.post( new Runnable() { @Override public void run() { try { mThumbnail.setImageURI(cacheFile.getUri()); } catch (IOException e) { throw new RuntimeException(e); } } }); } }); } }
@Override public boolean onOptionsItemSelected(final MenuItem item) { switch (item.getItemId()) { case OPTIONS_MENU_MARK_ALL_AS_READ: RedditAPI.markAllAsRead( CacheManager.getInstance(this), new APIResponseHandler.ActionResponseHandler(this) { @Override protected void onSuccess() { General.quickToast(context, R.string.mark_all_as_read_success); } @Override protected void onCallbackException(final Throwable t) { BugReportActivity.addGlobalError( new RRError("Mark all as Read failed", "Callback exception", t)); } @Override protected void onFailure( final @CacheRequest.RequestFailureType int type, final Throwable t, final Integer status, final String readableMessage) { final RRError error = General.getGeneralErrorForFailure( context, type, t, status, "Reddit API action: Mark all as Read"); AndroidApi.UI_THREAD_HANDLER.post( new Runnable() { public void run() { General.showResultDialog(InboxListingActivity.this, error); } }); } @Override protected void onFailure(final APIFailureType type) { final RRError error = General.getGeneralErrorForFailure(context, type); AndroidApi.UI_THREAD_HANDLER.post( new Runnable() { public void run() { General.showResultDialog(InboxListingActivity.this, error); } }); } }, RedditAccountManager.getInstance(this).getDefaultAccount(), this); return true; case OPTIONS_MENU_SHOW_UNREAD_ONLY: if (!item.isChecked()) { item.setChecked(true); editor.putBoolean("onlyUnread", true); onlyUnread = true; } else { item.setChecked(false); editor.putBoolean("onlyUnread", false); onlyUnread = false; } editor.commit(); makeFirstRequest(this); return true; case android.R.id.home: finish(); return true; default: return super.onOptionsItemSelected(item); } }
private void makeFirstRequest(final Context context) { final RedditAccount user = RedditAccountManager.getInstance(context).getDefaultAccount(); final CacheManager cm = CacheManager.getInstance(context); final URI url; if (!isModmail) { if (onlyUnread) { url = Constants.Reddit.getUri("/message/unread.json?mark=true&limit=100"); } else { url = Constants.Reddit.getUri("/message/inbox.json?mark=true&limit=100"); } } else { url = Constants.Reddit.getUri("/message/moderator.json?limit=100"); } // TODO parameterise limit request = new CacheRequest( url, user, null, Constants.Priority.API_INBOX_LIST, 0, CacheRequest.DOWNLOAD_FORCE, Constants.FileType.INBOX_LIST, CacheRequest.DOWNLOAD_QUEUE_REDDIT_API, true, true, context) { @Override protected void onDownloadNecessary() {} @Override protected void onDownloadStarted() {} @Override protected void onCallbackException(final Throwable t) { request = null; BugReportActivity.handleGlobalError(context, t); } @Override protected void onFailure( final @CacheRequest.RequestFailureType int type, final Throwable t, final Integer status, final String readableMessage) { request = null; if (loadingView != null) loadingView.setDone(R.string.download_failed); final RRError error = General.getGeneralErrorForFailure(context, type, t, status, url.toString()); AndroidApi.UI_THREAD_HANDLER.post( new Runnable() { public void run() { notifications.addView(new ErrorView(InboxListingActivity.this, error)); } }); if (t != null) t.printStackTrace(); } @Override protected void onProgress( final boolean authorizationInProgress, final long bytesRead, final long totalBytes) {} @Override protected void onSuccess( final CacheManager.ReadableCacheFile cacheFile, final long timestamp, final UUID session, final boolean fromCache, final String mimetype) { request = null; } @Override public void onJsonParseStarted( final JsonValue value, final long timestamp, final UUID session, final boolean fromCache) { if (loadingView != null) loadingView.setIndeterminate(R.string.download_downloading); // TODO pref (currently 10 mins) // TODO xml if (fromCache && RRTime.since(timestamp) > 10 * 60 * 1000) { AndroidApi.UI_THREAD_HANDLER.post( new Runnable() { public void run() { final TextView cacheNotif = new TextView(context); cacheNotif.setText( context.getString(R.string.listing_cached) + RRTime.formatDateTime(timestamp, context)); final int paddingPx = General.dpToPixels(context, 6); final int sidePaddingPx = General.dpToPixels(context, 10); cacheNotif.setPadding(sidePaddingPx, paddingPx, sidePaddingPx, paddingPx); cacheNotif.setTextSize(13f); notifications.addView(cacheNotif); adapter.notifyDataSetChanged(); } }); } // TODO {"error": 403} is received for unauthorized subreddits try { final JsonBufferedObject root = value.asObject(); final JsonBufferedObject data = root.getObject("data"); final JsonBufferedArray children = data.getArray("children"); for (JsonValue child : children) { final RedditThing thing = child.asObject(RedditThing.class); switch (thing.getKind()) { case COMMENT: final RedditComment comment = thing.asComment(); final RedditParsedComment parsedComment = new RedditParsedComment(comment); final RedditRenderableComment renderableComment = new RedditRenderableComment(parsedComment, null, -100000, false); itemHandler.sendMessage(General.handlerMessage(0, renderableComment)); break; case MESSAGE: final RedditPreparedMessage message = new RedditPreparedMessage( InboxListingActivity.this, thing.asMessage(), timestamp); itemHandler.sendMessage(General.handlerMessage(0, message)); if (message.src.replies != null && message.src.replies.getType() == JsonValue.TYPE_OBJECT) { final JsonBufferedArray replies = message.src.replies.asObject().getObject("data").getArray("children"); for (JsonValue childMsgValue : replies) { final RedditMessage childMsgRaw = childMsgValue.asObject(RedditThing.class).asMessage(); final RedditPreparedMessage childMsg = new RedditPreparedMessage( InboxListingActivity.this, childMsgRaw, timestamp); itemHandler.sendMessage(General.handlerMessage(0, childMsg)); } } break; default: throw new RuntimeException("Unknown item in list."); } } } catch (Throwable t) { notifyFailure(CacheRequest.REQUEST_FAILURE_PARSE, t, null, "Parse failure"); return; } if (loadingView != null) loadingView.setDone(R.string.download_done); } }; cm.makeRequest(request); }
@Override public void onCreate() { super.onCreate(); Log.i("RedReader", "Application created."); final Thread.UncaughtExceptionHandler androidHandler = Thread.getDefaultUncaughtExceptionHandler(); Thread.setDefaultUncaughtExceptionHandler( new Thread.UncaughtExceptionHandler() { public void uncaughtException(Thread thread, Throwable t) { try { t.printStackTrace(); File dir = Environment.getExternalStorageDirectory(); if (dir == null) { dir = Environment.getDataDirectory(); } final FileOutputStream fos = new FileOutputStream( new File( dir, "redreader_crash_log_" + UUID.randomUUID().toString() + ".txt")); final PrintWriter pw = new PrintWriter(fos); t.printStackTrace(pw); pw.flush(); pw.close(); } catch (Throwable t1) { } androidHandler.uncaughtException(thread, t); } }); final CacheManager cm = CacheManager.getInstance(this); cm.pruneTemp(); new Thread() { @Override public void run() { android.os.Process.setThreadPriority(android.os.Process.THREAD_PRIORITY_BACKGROUND); cm.pruneCache(); // Hope for the best :) } }.start(); new Thread() { @Override public void run() { RedditChangeDataIO.getInstance(RedReader.this).runInitialReadInThisThread(); RedditChangeDataManager.pruneAllUsers(); } }.start(); Alarms.onBoot(this); NewMessageChecker.checkForNewMessages(this); }
@Override protected void onCreate(Bundle savedInstanceState) { PrefsUtility.applyTheme(this); getSupportActionBar().setTitle(R.string.post_captcha_title); super.onCreate(savedInstanceState); final LoadingView loadingView = new LoadingView(this, R.string.download_waiting, true, true); setContentView(loadingView); final RedditAccount selectedAccount = RedditAccountManager.getInstance(this).getAccount(getIntent().getStringExtra("username")); final CacheManager cm = CacheManager.getInstance(this); RedditAPI.newCaptcha( cm, new APIResponseHandler.NewCaptchaResponseHandler(this) { @Override protected void onSuccess(final String captchaId) { final URI captchaUrl = Constants.Reddit.getUri("/captcha/" + captchaId); cm.makeRequest( new CacheRequest( captchaUrl, RedditAccountManager.getAnon(), null, Constants.Priority.CAPTCHA, 0, CacheRequest.DownloadType.FORCE, Constants.FileType.CAPTCHA, false, false, true, CaptchaActivity.this) { @Override protected void onCallbackException(Throwable t) { BugReportActivity.handleGlobalError(CaptchaActivity.this, t); } @Override protected void onDownloadNecessary() {} @Override protected void onDownloadStarted() { loadingView.setIndeterminate(R.string.download_downloading); } @Override protected void onFailure( RequestFailureType type, Throwable t, StatusLine status, String readableMessage) { final RRError error = General.getGeneralErrorForFailure( CaptchaActivity.this, type, t, status, url.toString()); General.showResultDialog(CaptchaActivity.this, error); finish(); } @Override protected void onProgress(long bytesRead, long totalBytes) { loadingView.setProgress( R.string.download_downloading, (float) ((double) bytesRead / (double) totalBytes)); } @Override protected void onSuccess( final CacheManager.ReadableCacheFile cacheFile, long timestamp, UUID session, boolean fromCache, String mimetype) { final Bitmap image; try { image = BitmapFactory.decodeStream(cacheFile.getInputStream()); } catch (IOException e) { BugReportActivity.handleGlobalError(CaptchaActivity.this, e); return; } new Handler(Looper.getMainLooper()) .post( new Runnable() { public void run() { final LinearLayout ll = new LinearLayout(CaptchaActivity.this); ll.setOrientation(LinearLayout.VERTICAL); final ImageView captchaImg = new ImageView(CaptchaActivity.this); ll.addView(captchaImg); final LinearLayout.LayoutParams layoutParams = (LinearLayout.LayoutParams) captchaImg.getLayoutParams(); layoutParams.setMargins(20, 20, 20, 20); layoutParams.height = General.dpToPixels(context, 100); captchaImg.setScaleType(ImageView.ScaleType.FIT_CENTER); final EditText captchaText = new EditText(CaptchaActivity.this); ll.addView(captchaText); ((LinearLayout.LayoutParams) captchaText.getLayoutParams()) .setMargins(20, 0, 20, 20); captchaText.setInputType( android.text.InputType.TYPE_CLASS_TEXT | android.text.InputType .TYPE_TEXT_VARIATION_VISIBLE_PASSWORD | InputType.TYPE_TEXT_FLAG_CAP_CHARACTERS); captchaImg.setImageBitmap(image); final Button submitButton = new Button(CaptchaActivity.this); submitButton.setText(R.string.post_captcha_submit_button); ll.addView(submitButton); ((LinearLayout.LayoutParams) submitButton.getLayoutParams()) .setMargins(20, 0, 20, 20); ((LinearLayout.LayoutParams) submitButton.getLayoutParams()) .gravity = Gravity.RIGHT; ((LinearLayout.LayoutParams) submitButton.getLayoutParams()).width = LinearLayout.LayoutParams.WRAP_CONTENT; submitButton.setOnClickListener( new View.OnClickListener() { public void onClick(View v) { final Intent result = new Intent(); result.putExtra("captchaId", captchaId); result.putExtra( "captchaText", captchaText.getText().toString()); setResult(RESULT_OK, result); finish(); } }); final ScrollView sv = new ScrollView(CaptchaActivity.this); sv.addView(ll); setContentView(sv); } }); } }); } @Override protected void onCallbackException(Throwable t) { BugReportActivity.handleGlobalError(CaptchaActivity.this, t); } @Override protected void onFailure( RequestFailureType type, Throwable t, StatusLine status, String readableMessage) { final RRError error = General.getGeneralErrorForFailure(CaptchaActivity.this, type, t, status, null); General.showResultDialog(CaptchaActivity.this, error); finish(); } @Override protected void onFailure(APIFailureType type) { final RRError error = General.getGeneralErrorForFailure(CaptchaActivity.this, type); General.showResultDialog(CaptchaActivity.this, error); finish(); } }, selectedAccount, this); }