Added watch settings

captchafix
Florens Douwes 11 years ago
parent 39d974f91c
commit 900fdb6ce4
  1. 8
      Chan/AndroidManifest.xml
  2. 11
      Chan/res/menu/watch_settings.xml
  3. 8
      Chan/res/values/strings.xml
  4. 91
      Chan/res/xml/preference.xml
  5. 3
      Chan/src/org/floens/chan/ChanApplication.java
  6. 108
      Chan/src/org/floens/chan/activity/WatchSettingsActivity.java
  7. 38
      Chan/src/org/floens/chan/fragment/SettingsFragment.java
  8. 2
      Chan/src/org/floens/chan/loader/Loader.java
  9. 135
      Chan/src/org/floens/chan/manager/ThreadManager.java
  10. 70
      Chan/src/org/floens/chan/service/PinnedService.java
  11. 28
      Chan/src/org/floens/chan/utils/ChanPreferences.java
  12. 8
      Chan/src/org/floens/chan/utils/ScrollerRunnable.java
  13. 5
      Chan/src/org/floens/chan/utils/Utils.java
  14. 18
      Chan/src/org/floens/chan/watch/WatchNotifier.java

@ -53,6 +53,14 @@
android:name="android.support.PARENT_ACTIVITY" android:name="android.support.PARENT_ACTIVITY"
android:value="org.floens.chan.activity.BoardActivity" /> android:value="org.floens.chan.activity.BoardActivity" />
</activity> </activity>
<activity
android:name="org.floens.chan.activity.WatchSettingsActivity"
android:label="@string/preference_watch_settings"
android:parentActivityName="org.floens.chan.activity.BoardActivity" >
<meta-data
android:name="android.support.PARENT_ACTIVITY"
android:value="org.floens.chan.activity.BoardActivity" />
</activity>
<activity <activity
android:name="org.floens.chan.activity.AboutActivity" android:name="org.floens.chan.activity.AboutActivity"
android:label="@string/preference_about" android:label="@string/preference_about"

@ -0,0 +1,11 @@
<?xml version="1.0" encoding="utf-8"?>
<menu xmlns:android="http://schemas.android.com/apk/res/android" >
<item
android:id="@+id/enable_watch_switch"
android:title=""
android:actionViewClass="android.widget.Switch"
android:showAsAction="always">
</item>
</menu>

@ -88,6 +88,8 @@
<string name="delete_fail">Error deleting post</string> <string name="delete_fail">Error deleting post</string>
<string name="delete_image_only">Only delete the image</string> <string name="delete_image_only">Only delete the image</string>
<string name="preference_watch_settings">Thread watcher</string>
<string name="preference_general">General</string> <string name="preference_general">General</string>
<string name="preference_open_link_confirmation">Ask before opening links</string> <string name="preference_open_link_confirmation">Ask before opening links</string>
<string name="preference_default_name">Default name</string> <string name="preference_default_name">Default name</string>
@ -100,4 +102,10 @@
<string name="open_link_confirmation">Open link?</string> <string name="open_link_confirmation">Open link?</string>
<string name="watch_summary_disabled">Off</string>
<string name="watch_summary_enabled">Watching pinned threads</string>
<string name="watch_info_text">
To view the thread watcher options, turn the thread watcher on.
</string>
</resources> </resources>

@ -1,57 +1,52 @@
<?xml version="1.0" encoding="utf-8"?> <?xml version="1.0" encoding="utf-8"?>
<PreferenceScreen xmlns:android="http://schemas.android.com/apk/res/android" > <PreferenceScreen xmlns:android="http://schemas.android.com/apk/res/android" >
<PreferenceCategory
android:title="@string/preference_general" > <Preference
android:key="watch_settings"
<Preference android:title="@string/preference_watch_settings" >
android:title="@string/board_edit" > <intent
<intent android:action="android.intent.action.VIEW"
android:action="android.intent.action.VIEW" android:targetClass="org.floens.chan.activity.WatchSettingsActivity"
android:targetPackage="org.floens.chan" android:targetPackage="org.floens.chan" />
android:targetClass="org.floens.chan.activity.BoardEditor" /> </Preference>
</Preference> <Preference android:title="@string/board_edit" >
<intent
<CheckBoxPreference android:action="android.intent.action.VIEW"
android:title="@string/preference_open_link_confirmation" android:targetClass="org.floens.chan.activity.BoardEditor"
android:key="preference_open_link_confirmation" android:targetPackage="org.floens.chan" />
android:defaultValue="true" /> </Preference>
<EditTextPreference <PreferenceCategory android:title="@string/preference_general" >
android:title="@string/preference_default_name" <CheckBoxPreference
android:key="preference_default_name" /> android:defaultValue="true"
android:key="preference_open_link_confirmation"
<EditTextPreference android:title="@string/preference_open_link_confirmation" />
android:title="@string/preference_default_email"
android:key="preference_default_email" /> <EditTextPreference
android:key="preference_default_name"
</PreferenceCategory> android:title="@string/preference_default_name" />
<EditTextPreference
<PreferenceCategory android:key="preference_default_email"
android:title="@string/preference_about" android:title="@string/preference_default_email" />
android:key="group_about" > </PreferenceCategory>
<PreferenceCategory
android:key="group_about"
android:title="@string/preference_about" >
<Preference <Preference
android:title="@string/preference_licenses" android:key="about_licences"
android:summary="@string/preference_licences_summary" android:summary="@string/preference_licences_summary"
android:key="about_licences" /> android:title="@string/preference_licenses" />
<Preference <Preference
android:title="Chan" android:key="about_version"
android:key="about_version" /> android:title="Chan" />
<Preference <Preference
android:title="@string/preference_developer" android:key="about_developer"
android:key="about_developer" > android:title="@string/preference_developer" >
<intent <intent
android:action="android.intent.action.VIEW" android:action="android.intent.action.VIEW"
android:targetPackage="org.floens.chan" android:targetClass="org.floens.chan.activity.DeveloperActivity"
android:targetClass="org.floens.chan.activity.DeveloperActivity" /> android:targetPackage="org.floens.chan" />
</Preference> </Preference>
</PreferenceCategory> </PreferenceCategory>
</PreferenceScreen>
</PreferenceScreen>

@ -8,7 +8,6 @@ import org.floens.chan.service.PinnedService;
import org.floens.chan.utils.IconCache; import org.floens.chan.utils.IconCache;
import android.app.Application; import android.app.Application;
import android.content.Intent;
import android.content.SharedPreferences; import android.content.SharedPreferences;
import android.os.StrictMode; import android.os.StrictMode;
import android.preference.PreferenceManager; import android.preference.PreferenceManager;
@ -72,7 +71,7 @@ public class ChanApplication extends Application {
new PinnedManager(this); new PinnedManager(this);
new ReplyManager(this); new ReplyManager(this);
startService(new Intent(this, PinnedService.class)); PinnedService.startStopAccordingToSettings(this);
} }
} }

@ -0,0 +1,108 @@
package org.floens.chan.activity;
import org.floens.chan.R;
import org.floens.chan.utils.ChanPreferences;
import org.floens.chan.utils.Utils;
import android.app.Activity;
import android.app.Fragment;
import android.app.FragmentTransaction;
import android.os.Bundle;
import android.os.Handler;
import android.os.Looper;
import android.preference.PreferenceFragment;
import android.view.Gravity;
import android.view.LayoutInflater;
import android.view.Menu;
import android.view.View;
import android.view.ViewGroup;
import android.widget.CompoundButton;
import android.widget.CompoundButton.OnCheckedChangeListener;
import android.widget.LinearLayout;
import android.widget.Switch;
import android.widget.TextView;
public class WatchSettingsActivity extends Activity implements OnCheckedChangeListener {
private Switch watchSwitch;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
}
@Override
public boolean onCreateOptionsMenu(Menu menu) {
getMenuInflater().inflate(R.menu.watch_settings, menu);
watchSwitch = (Switch) menu.findItem(R.id.enable_watch_switch).getActionView();
watchSwitch.setOnCheckedChangeListener(this);
watchSwitch.setPadding(0, 0, Utils.dp(this, 20), 0);
setEnabled(ChanPreferences.getWatchEnabled());
return true;
}
@Override
public void onCheckedChanged(CompoundButton buttonView, boolean isChecked) {
setEnabled(isChecked);
}
private void setEnabled(boolean enabled) {
if (enabled) {
FragmentTransaction t = getFragmentManager().beginTransaction();
t.replace(android.R.id.content, new WatchSettingsFragment());
t.setTransition(FragmentTransaction.TRANSIT_FRAGMENT_FADE);
t.commit();
} else {
FragmentTransaction t = getFragmentManager().beginTransaction();
t.replace(android.R.id.content, TextFragment.newInstance(R.string.watch_info_text));
t.setTransition(FragmentTransaction.TRANSIT_FRAGMENT_FADE);
t.commit();
}
watchSwitch.setChecked(enabled);
ChanPreferences.setWatchEnabled(enabled);
watchSwitch.setEnabled(false);
new Handler(Looper.getMainLooper()).postDelayed(new Runnable() {
@Override
public void run() {
watchSwitch.setEnabled(true);
}
}, 500);
}
public static class TextFragment extends Fragment {
public static TextFragment newInstance(int textResource) {
TextFragment f = new TextFragment();
Bundle bundle = new Bundle();
bundle.putInt("text_resource", textResource);
f.setArguments(bundle);
return f;
}
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup group, Bundle savedInstanceState) {
LinearLayout container = new LinearLayout(inflater.getContext());
int p = Utils.dp(inflater.getContext(), 20);
container.setPadding(p, p, p, p);
TextView text = new TextView(inflater.getContext());
text.setTextSize(20);
text.setText(getArguments().getInt("text_resource"));
container.setGravity(Gravity.CENTER);
container.addView(text);
return container;
}
}
public static class WatchSettingsFragment extends PreferenceFragment {
}
}

@ -15,27 +15,27 @@ import android.widget.Toast;
public class SettingsFragment extends PreferenceFragment { public class SettingsFragment extends PreferenceFragment {
private int clickCount = 0; private int clickCount = 0;
private Preference developerPreference; private Preference developerPreference;
@Override @Override
public void onCreate(Bundle savedInstanceState) { public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState); super.onCreate(savedInstanceState);
addPreferencesFromResource(R.xml.preference); addPreferencesFromResource(R.xml.preference);
Preference aboutLicences = findPreference("about_licences"); Preference aboutLicences = findPreference("about_licences");
if (aboutLicences != null) { if (aboutLicences != null) {
aboutLicences.setOnPreferenceClickListener(new OnPreferenceClickListener() { aboutLicences.setOnPreferenceClickListener(new OnPreferenceClickListener() {
@Override @Override
public boolean onPreferenceClick(Preference preference) { public boolean onPreferenceClick(Preference preference) {
startActivity(new Intent(getActivity(), AboutActivity.class)); startActivity(new Intent(getActivity(), AboutActivity.class));
return true; return true;
} }
}); });
} }
Preference aboutVersion = findPreference("about_version"); Preference aboutVersion = findPreference("about_version");
if (aboutVersion != null) { if (aboutVersion != null) {
aboutVersion.setOnPreferenceClickListener(new OnPreferenceClickListener() { aboutVersion.setOnPreferenceClickListener(new OnPreferenceClickListener() {
@ -43,35 +43,45 @@ public class SettingsFragment extends PreferenceFragment {
public boolean onPreferenceClick(Preference preference) { public boolean onPreferenceClick(Preference preference) {
if (++clickCount >= 5) { if (++clickCount >= 5) {
clickCount = 0; clickCount = 0;
boolean enabled = !ChanPreferences.getDeveloper(); boolean enabled = !ChanPreferences.getDeveloper();
ChanPreferences.setDeveloper(enabled); ChanPreferences.setDeveloper(enabled);
updateDeveloperPreference(); updateDeveloperPreference();
Toast.makeText(getActivity(), Toast.makeText(getActivity(),
(enabled ? "Enabled " : "Disabled ") + "developer options", Toast.LENGTH_LONG).show(); (enabled ? "Enabled " : "Disabled ") + "developer options", Toast.LENGTH_LONG).show();
} }
return true; return true;
} }
}); });
String version = ""; String version = "";
try { try {
version = getActivity().getPackageManager().getPackageInfo(getActivity().getPackageName(), 0).versionName; version = getActivity().getPackageManager().getPackageInfo(getActivity().getPackageName(), 0).versionName;
} catch (NameNotFoundException e) { } catch (NameNotFoundException e) {
e.printStackTrace(); e.printStackTrace();
} }
aboutVersion.setTitle(R.string.app_name); aboutVersion.setTitle(R.string.app_name);
aboutVersion.setSummary(version); aboutVersion.setSummary(version);
} }
developerPreference = findPreference("about_developer"); developerPreference = findPreference("about_developer");
((PreferenceGroup) findPreference("group_about")).removePreference(developerPreference); ((PreferenceGroup) findPreference("group_about")).removePreference(developerPreference);
updateDeveloperPreference(); updateDeveloperPreference();
} }
@Override
public void onResume() {
super.onResume();
final Preference watchPreference = findPreference("watch_settings");
if (watchPreference != null) {
watchPreference.setSummary(ChanPreferences.getWatchEnabled() ? R.string.watch_summary_enabled : R.string.watch_summary_disabled);
}
}
private void updateDeveloperPreference() { private void updateDeveloperPreference() {
if (ChanPreferences.getDeveloper()) { if (ChanPreferences.getDeveloper()) {
((PreferenceGroup) findPreference("group_about")).addPreference(developerPreference); ((PreferenceGroup) findPreference("group_about")).addPreference(developerPreference);

@ -200,8 +200,6 @@ public class Loader {
private void onData(List<Post> result) { private void onData(List<Post> result) {
if (destroyed) return; if (destroyed) return;
Logger.test("ondata in loader");
postsById.clear(); postsById.clear();
for (Post post : result) { for (Post post : result) {
postsById.append(post.no, post); postsById.append(post.no, post);

@ -38,10 +38,9 @@ import android.widget.Toast;
import com.android.volley.VolleyError; import com.android.volley.VolleyError;
/** /**
* All PostView's need to have this referenced. * All PostView's need to have this referenced. This manages some things like
* This manages some things like pages, starting and stopping of loading, * pages, starting and stopping of loading, handling linkables, replies popups
* handling linkables, replies popups etc. * etc. onDestroy, onStart and onStop must be called from the activity/fragment
* onDestroy, onStart and onStop must be called from the activity/fragment
*/ */
public class ThreadManager implements Loader.LoaderListener { public class ThreadManager implements Loader.LoaderListener {
private static final String TAG = "ThreadManager"; private static final String TAG = "ThreadManager";
@ -54,8 +53,8 @@ public class ThreadManager implements Loader.LoaderListener {
private Loader loader; private Loader loader;
public ThreadManager(Activity context, final ThreadManagerListener listener) { public ThreadManager(Activity activity, final ThreadManagerListener listener) {
activity = context; this.activity = activity;
threadManagerListener = listener; threadManagerListener = listener;
} }
@ -137,12 +136,14 @@ public class ThreadManager implements Loader.LoaderListener {
} }
public Post findPostById(int id) { public Post findPostById(int id) {
if (loader == null) return null; if (loader == null)
return null;
return loader.findPostById(id); return loader.findPostById(id);
} }
public Loadable getLoadable() { public Loadable getLoadable() {
if (loader == null) return null; if (loader == null)
return null;
return loader.getLoadable(); return loader.getLoadable();
} }
@ -178,7 +179,7 @@ public class ThreadManager implements Loader.LoaderListener {
builder.setItems(items, new DialogInterface.OnClickListener() { builder.setItems(items, new DialogInterface.OnClickListener() {
@Override @Override
public void onClick(DialogInterface dialog, int which) { public void onClick(DialogInterface dialog, int which) {
switch(which) { switch (which) {
case 0: // Reply case 0: // Reply
openReply(true); // todo if tablet openReply(true); // todo if tablet
// Pass through // Pass through
@ -205,7 +206,8 @@ public class ThreadManager implements Loader.LoaderListener {
} }
public void openReply(boolean startInActivity) { public void openReply(boolean startInActivity) {
if (loader == null) return; if (loader == null)
return;
if (startInActivity) { if (startInActivity) {
ReplyActivity.setLoadable(loader.getLoadable()); ReplyActivity.setLoadable(loader.getLoadable());
@ -246,7 +248,7 @@ public class ThreadManager implements Loader.LoaderListener {
text += "File: " + post.filename + " \nSize: " + post.imageWidth + "x" + post.imageHeight + "\n\n"; text += "File: " + post.filename + " \nSize: " + post.imageWidth + "x" + post.imageHeight + "\n\n";
} }
text += "Time: " + post.date ; text += "Time: " + post.date;
if (!TextUtils.isEmpty(post.id)) { if (!TextUtils.isEmpty(post.id)) {
text += "\nId: " + post.id; text += "\nId: " + post.id;
@ -268,24 +270,23 @@ public class ThreadManager implements Loader.LoaderListener {
text += "\nCapcode: " + post.capcode; text += "\nCapcode: " + post.capcode;
} }
AlertDialog dialog = new AlertDialog.Builder(activity) AlertDialog dialog = new AlertDialog.Builder(activity).setTitle(R.string.post_info).setMessage(text)
.setTitle(R.string.post_info) .setNeutralButton(android.R.string.ok, new DialogInterface.OnClickListener() {
.setMessage(text) @Override
.setNeutralButton(android.R.string.ok, new DialogInterface.OnClickListener() { public void onClick(DialogInterface dialog, int which) {
@Override }
public void onClick(DialogInterface dialog, int which) { }).create();
}
})
.create();
dialog.show(); dialog.show();
} }
/** /**
* When the user clicks a post: * When the user clicks a post: a. when there's one linkable, open the
* a. when there's one linkable, open the linkable. * linkable. b. when there's more than one linkable, show the user multiple
* b. when there's more than one linkable, show the user multiple options to select from. * options to select from.
* @param post The post that was clicked. *
* @param post
* The post that was clicked.
*/ */
public void showPostLinkables(Post post) { public void showPostLinkables(Post post) {
AlertDialog.Builder builder = new AlertDialog.Builder(activity); AlertDialog.Builder builder = new AlertDialog.Builder(activity);
@ -329,7 +330,9 @@ public class ThreadManager implements Loader.LoaderListener {
/** /**
* Handle when a linkable has been clicked. * Handle when a linkable has been clicked.
* @param linkable the selected linkable. *
* @param linkable
* the selected linkable.
*/ */
private void handleLinkableSelected(final PostLinkable linkable) { private void handleLinkableSelected(final PostLinkable linkable) {
if (linkable.type == PostLinkable.Type.QUOTE) { if (linkable.type == PostLinkable.Type.QUOTE) {
@ -337,20 +340,16 @@ public class ThreadManager implements Loader.LoaderListener {
} else if (linkable.type == PostLinkable.Type.LINK) { } else if (linkable.type == PostLinkable.Type.LINK) {
if (ChanPreferences.getOpenLinkConfirmation()) { if (ChanPreferences.getOpenLinkConfirmation()) {
AlertDialog dialog = new AlertDialog.Builder(activity) AlertDialog dialog = new AlertDialog.Builder(activity)
.setNegativeButton(android.R.string.cancel, new DialogInterface.OnClickListener() { .setNegativeButton(android.R.string.cancel, new DialogInterface.OnClickListener() {
@Override @Override
public void onClick(DialogInterface dialog, int which) { public void onClick(DialogInterface dialog, int which) {
} }
}) }).setPositiveButton(android.R.string.ok, new DialogInterface.OnClickListener() {
.setPositiveButton(android.R.string.ok, new DialogInterface.OnClickListener() { @Override
@Override public void onClick(DialogInterface dialog, int which) {
public void onClick(DialogInterface dialog, int which) { openLink(linkable);
openLink(linkable); }
} }).setTitle(R.string.open_link_confirmation).setMessage(linkable.value).create();
})
.setTitle(R.string.open_link_confirmation)
.setMessage(linkable.value)
.create();
dialog.show(); dialog.show();
} else { } else {
@ -360,9 +359,11 @@ public class ThreadManager implements Loader.LoaderListener {
} }
/** /**
* When a linkable to a post has been clicked, * When a linkable to a post has been clicked, show a dialog with the
* show a dialog with the referenced post in it. * referenced post in it.
* @param linkable the clicked linkable. *
* @param linkable
* the clicked linkable.
*/ */
private void showPostReply(PostLinkable linkable) { private void showPostReply(PostLinkable linkable) {
String value = linkable.value; String value = linkable.value;
@ -383,21 +384,24 @@ public class ThreadManager implements Loader.LoaderListener {
showPostsRepliesFragment(l); showPostsRepliesFragment(l);
} }
} }
} catch(NumberFormatException e) { } catch (NumberFormatException e) {
e.printStackTrace(); e.printStackTrace();
} }
} }
/** /**
* Open an url. * Open an url.
* @param linkable Linkable with an url. *
* @param linkable
* Linkable with an url.
*/ */
private void openLink(PostLinkable linkable) { private void openLink(PostLinkable linkable) {
activity.startActivity(new Intent(Intent.ACTION_VIEW, Uri.parse(linkable.value))); activity.startActivity(new Intent(Intent.ACTION_VIEW, Uri.parse(linkable.value)));
} }
private void showPostsRepliesFragment(List<Post> list) { private void showPostsRepliesFragment(List<Post> list) {
// Post popups are now queued up, more than 32 popups on top of each other makes the system crash! // Post popups are now queued up, more than 32 popups on top of each
// other makes the system crash!
popupQueue.add(list); popupQueue.add(list);
if (currentPopupFragment != null) { if (currentPopupFragment != null) {
@ -414,7 +418,8 @@ public class ThreadManager implements Loader.LoaderListener {
} }
public void onPostRepliesPop() { public void onPostRepliesPop() {
if (popupQueue.size() == 0) return; if (popupQueue.size() == 0)
return;
popupQueue.remove(popupQueue.size() - 1); popupQueue.remove(popupQueue.size() - 1);
@ -442,30 +447,26 @@ public class ThreadManager implements Loader.LoaderListener {
int padding = activity.getResources().getDimensionPixelSize(R.dimen.general_padding); int padding = activity.getResources().getDimensionPixelSize(R.dimen.general_padding);
view.setPadding(padding, padding, padding, padding); view.setPadding(padding, padding, padding, padding);
new AlertDialog.Builder(activity) new AlertDialog.Builder(activity).setTitle(R.string.delete_confirm).setView(view)
.setTitle(R.string.delete_confirm) .setPositiveButton(R.string.delete, new OnClickListener() {
.setView(view) @Override
.setPositiveButton(R.string.delete, new OnClickListener() { public void onClick(DialogInterface dialog, int which) {
@Override doDeletePost(post, view.isChecked());
public void onClick(DialogInterface dialog, int which) { }
doDeletePost(post, view.isChecked()); }).setNegativeButton(R.string.cancel, new OnClickListener() {
} @Override
}) public void onClick(DialogInterface dialog, int which) {
.setNegativeButton(R.string.cancel, new OnClickListener() { }
@Override }).show();
public void onClick(DialogInterface dialog, int which) {
}
})
.show();
} }
private void doDeletePost(Post post, boolean onlyImageDelete) { private void doDeletePost(Post post, boolean onlyImageDelete) {
SavedReply reply = DatabaseManager.getInstance().getSavedReply(post.board, post.no); SavedReply reply = DatabaseManager.getInstance().getSavedReply(post.board, post.no);
if (reply == null) { if (reply == null) {
/*reply = new SavedReply(); /*
reply.board = "g"; * reply = new SavedReply(); reply.board = "g"; reply.no = 1234;
reply.no = 1234; * reply.password = "boom";
reply.password = "boom";*/ */
return; return;
} }
@ -501,9 +502,13 @@ public class ThreadManager implements Loader.LoaderListener {
public interface ThreadManagerListener { public interface ThreadManagerListener {
public void onThreadLoaded(List<Post> result, boolean append); public void onThreadLoaded(List<Post> result, boolean append);
public void onThreadLoadError(VolleyError error); public void onThreadLoadError(VolleyError error);
public void onOPClicked(Post post); public void onOPClicked(Post post);
public void onThumbnailClicked(Post post); public void onThumbnailClicked(Post post);
public void onScrollTo(Post post); public void onScrollTo(Post post);
} }
} }

@ -4,19 +4,23 @@ import java.util.List;
import org.floens.chan.manager.PinnedManager; import org.floens.chan.manager.PinnedManager;
import org.floens.chan.model.Pin; import org.floens.chan.model.Pin;
import org.floens.chan.utils.ChanPreferences;
import org.floens.chan.utils.Logger; import org.floens.chan.utils.Logger;
import org.floens.chan.watch.WatchNotifier; import org.floens.chan.watch.WatchNotifier;
import android.app.Service; import android.app.Service;
import android.content.Context;
import android.content.Intent; import android.content.Intent;
import android.os.Handler; import android.os.Handler;
import android.os.IBinder; import android.os.IBinder;
import android.os.Looper; import android.os.Looper;
import android.widget.Toast;
public class PinnedService extends Service { public class PinnedService extends Service {
private static final long FOREGROUND_INTERVAL = 10000L; private static final long FOREGROUND_INTERVAL = 10000L;
private static final long BACKGROUND_INTERVAL = 60000L; private static final long BACKGROUND_INTERVAL = 60000L;
private static PinnedService instance;
private static boolean activityInForeground = false; private static boolean activityInForeground = false;
private Thread loadThread; private Thread loadThread;
@ -33,6 +37,43 @@ public class PinnedService extends Service {
activityInForeground = false; activityInForeground = false;
} }
public static void startStopAccordingToSettings(Context context) {
if (ChanPreferences.getWatchEnabled()) {
if (!getRunning()) {
enable(context);
}
} else {
if (getRunning()) {
disable(context);
}
}
}
public static void enable(Context context) {
if (!getRunning()) {
context.startService(new Intent(context, PinnedService.class));
}
}
public static void disable(Context context) {
if (getRunning()) {
context.stopService(new Intent(context, PinnedService.class));
}
}
public static boolean getRunning() {
return instance != null;
}
public static void callOnPinsChanged() {
new Handler(Looper.getMainLooper()).post(new Runnable() {
@Override
public void run() {
PinnedManager.getInstance().onPinsChanged();
}
});
}
public PinnedService() { public PinnedService() {
watchNotifier = new WatchNotifier(this); watchNotifier = new WatchNotifier(this);
} }
@ -41,17 +82,25 @@ public class PinnedService extends Service {
public void onCreate() { public void onCreate() {
super.onCreate(); super.onCreate();
start(); instance = this;
startThread();
} }
@Override @Override
public void onDestroy() { public void onDestroy() {
super.onDestroy(); super.onDestroy();
instance = null;
running = false; running = false;
if (loadThread != null) {
loadThread.interrupt();
Toast.makeText(getApplicationContext(), "Service thread interrupted", Toast.LENGTH_SHORT).show();
}
} }
private void start() { private void startThread() {
running = true; running = true;
if (loadThread == null) { if (loadThread == null) {
@ -63,18 +112,19 @@ public class PinnedService extends Service {
long timeout = activityInForeground ? FOREGROUND_INTERVAL : BACKGROUND_INTERVAL; long timeout = activityInForeground ? FOREGROUND_INTERVAL : BACKGROUND_INTERVAL;
if (!running) return;
try { try {
Thread.sleep(timeout); Thread.sleep(timeout);
} catch (InterruptedException e) { } catch (InterruptedException e) {
e.printStackTrace(); return;
} }
} }
loadThread = null;
} }
}); });
loadThread.start(); loadThread.start();
Toast.makeText(getApplicationContext(), "Service thread started", Toast.LENGTH_SHORT).show();
} }
} }
@ -87,16 +137,6 @@ public class PinnedService extends Service {
watchNotifier.update(); watchNotifier.update();
} }
public static void callOnPinsChanged() {
new Handler(Looper.getMainLooper()).post(new Runnable() {
@Override
public void run() {
PinnedManager.getInstance().onPinsChanged();
}
});
}
@Override @Override
public IBinder onBind(Intent intent) { public IBinder onBind(Intent intent) {
return null; return null;

@ -1,29 +1,47 @@
package org.floens.chan.utils; package org.floens.chan.utils;
import org.floens.chan.ChanApplication; import org.floens.chan.ChanApplication;
import org.floens.chan.service.PinnedService;
public class ChanPreferences { public class ChanPreferences {
public static boolean getOpenLinkConfirmation() { public static boolean getOpenLinkConfirmation() {
return ChanApplication.getPreferences().getBoolean("preference_open_link_confirmation", true); return ChanApplication.getPreferences().getBoolean("preference_open_link_confirmation", true);
} }
public static String getDefaultName() { public static String getDefaultName() {
return ChanApplication.getPreferences().getString("preference_default_name", ""); return ChanApplication.getPreferences().getString("preference_default_name", "");
} }
public static String getDefaultEmail() { public static String getDefaultEmail() {
return ChanApplication.getPreferences().getString("preference_default_email", ""); return ChanApplication.getPreferences().getString("preference_default_email", "");
} }
public static boolean getDeveloper() { public static boolean getDeveloper() {
return ChanApplication.getPreferences().getBoolean("preference_developer", false); return ChanApplication.getPreferences().getBoolean("preference_developer", false);
} }
public static void setDeveloper(boolean developer) { public static void setDeveloper(boolean developer) {
ChanApplication.getPreferences().edit().putBoolean("preference_developer", developer).commit(); ChanApplication.getPreferences().edit().putBoolean("preference_developer", developer).commit();
} }
public static String getImageSaveDirectory() { public static String getImageSaveDirectory() {
return "Chan"; return "Chan";
} }
public static boolean getWatchEnabled() {
return ChanApplication.getPreferences().getBoolean("preference_watch_enabled", true);
}
/**
* This also calls startStopAccordingToSettings on the PinnedService to
* start/stop the service as needed.
*
* @param enabled
*/
public static void setWatchEnabled(boolean enabled) {
if (getWatchEnabled() != enabled) {
ChanApplication.getPreferences().edit().putBoolean("preference_watch_enabled", enabled).commit();
PinnedService.startStopAccordingToSettings(ChanApplication.getInstance());
}
}
} }

@ -5,8 +5,6 @@ import android.view.ViewConfiguration;
import android.widget.ListView; import android.widget.ListView;
public class ScrollerRunnable implements Runnable { public class ScrollerRunnable implements Runnable {
private static final int SCROLL_DURATION = 1;
private static final int MOVE_DOWN_POS = 1; private static final int MOVE_DOWN_POS = 1;
private static final int MOVE_UP_POS = 2; private static final int MOVE_UP_POS = 2;
@ -28,12 +26,12 @@ public class ScrollerRunnable implements Runnable {
final int firstPos = mList.getFirstVisiblePosition(); final int firstPos = mList.getFirstVisiblePosition();
final int lastPos = firstPos + mList.getChildCount() - 1; final int lastPos = firstPos + mList.getChildCount() - 1;
int viewTravelCount = 0; // int viewTravelCount = 0;
if (position <= firstPos) { if (position <= firstPos) {
viewTravelCount = firstPos - position + 1; // viewTravelCount = firstPos - position + 1;
mMode = MOVE_UP_POS; mMode = MOVE_UP_POS;
} else if (position >= lastPos) { } else if (position >= lastPos) {
viewTravelCount = position - lastPos + 1; // viewTravelCount = position - lastPos + 1;
mMode = MOVE_DOWN_POS; mMode = MOVE_DOWN_POS;
} else { } else {
// Already on screen, nothing to do // Already on screen, nothing to do

@ -5,9 +5,14 @@ import android.content.res.TypedArray;
import android.graphics.drawable.Drawable; import android.graphics.drawable.Drawable;
import android.os.Handler; import android.os.Handler;
import android.os.Looper; import android.os.Looper;
import android.util.TypedValue;
import android.view.View; import android.view.View;
public class Utils { public class Utils {
public static int dp(Context context, int dp) {
return (int) TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, 14, context.getResources().getDisplayMetrics());
}
/** /**
* Sets the android.R.attr.selectableItemBackground as background drawable on the view. * Sets the android.R.attr.selectableItemBackground as background drawable on the view.
* @param view * @param view

@ -1,6 +1,10 @@
package org.floens.chan.watch; package org.floens.chan.watch;
import java.util.List;
import org.floens.chan.R; import org.floens.chan.R;
import org.floens.chan.manager.PinnedManager;
import org.floens.chan.model.Pin;
import android.app.Notification; import android.app.Notification;
import android.app.NotificationManager; import android.app.NotificationManager;
@ -16,7 +20,18 @@ public class WatchNotifier {
} }
public void update() { public void update() {
showNotification("Update!"); List<Pin> pins = PinnedManager.getInstance().getPins();
int count = 0;
int pinCount = 0;
for (Pin pin : pins) {
count += pin.getNewPostCount();
pinCount++;
}
showNotification(count + " new posts in " + pinCount + " threads");
// showNotification("WatchNotifier update");
} }
private void showNotification(String text) { private void showNotification(String text) {
@ -27,6 +42,7 @@ public class WatchNotifier {
builder.setContentTitle(text); builder.setContentTitle(text);
builder.setContentText(text); builder.setContentText(text);
builder.setSmallIcon(R.drawable.ic_stat_notify); builder.setSmallIcon(R.drawable.ic_stat_notify);
builder.setOnlyAlertOnce(false);
nm.notify(NOTIFICATION_ID, builder.getNotification()); nm.notify(NOTIFICATION_ID, builder.getNotification());
} }

Loading…
Cancel
Save