diff options
author | Kazuki Yamaguchi <k@rhe.jp> | 2017-10-04 21:10:58 +0900 |
---|---|---|
committer | Kazuki Yamaguchi <k@rhe.jp> | 2017-10-04 22:00:52 +0900 |
commit | 986fa8cd8bdf6110d2aa390a9dcafc4ff19ee6dd (patch) | |
tree | e92964cc05dc18021011fbed2f8f249b7f3ed5b6 /app/src | |
parent | b471085c2b2d6229bb6fb54a6d444802147a7392 (diff) | |
download | SmileEssence-986fa8cd8bdf6110d2aa390a9dcafc4ff19ee6dd.tar.gz |
worldify (wip)2017-10-04
Diffstat (limited to 'app/src')
105 files changed, 1680 insertions, 4279 deletions
diff --git a/app/src/debug/res/values/app_info.xml b/app/src/debug/res/values/app_info.xml index 46a00c0d..2d8cb016 100644 --- a/app/src/debug/res/values/app_info.xml +++ b/app/src/debug/res/values/app_info.xml @@ -1,4 +1,4 @@ <resources xmlns:tools="http://schemas.android.com/tools" tools:ignore="MissingTranslation"> - <string name="app_name">dSmileEssence</string> + <string name="app_name">SE3-D</string> </resources>
\ No newline at end of file diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml index 0f9a670c..38d75d3f 100644 --- a/app/src/main/AndroidManifest.xml +++ b/app/src/main/AndroidManifest.xml @@ -36,11 +36,11 @@ android:label="@string/app_name" android:theme="@style/theme_dark"> <activity - android:name=".activity.MainActivity" - android:configChanges="orientation|screenSize|keyboardHidden" + android:name=".activity.ManageAccountsActivity" + android:configChanges="keyboardHidden|orientation" + android:excludeFromRecents="true" android:label="@string/app_name" - android:launchMode="singleTask" - android:windowSoftInputMode="stateHidden|adjustResize"> + android:launchMode="singleTask"> <intent-filter> <action android:name="android.intent.action.MAIN" /> <category android:name="android.intent.category.LAUNCHER" /> @@ -93,19 +93,24 @@ </intent-filter> </activity> <activity + android:name=".activity.MainActivity" + android:configChanges="orientation|screenSize|keyboardHidden" + android:label="@string/app_name" + android:documentLaunchMode="intoExisting" + android:windowSoftInputMode="stateHidden|adjustResize" /> + <activity android:name=".activity.SettingActivity" android:configChanges="keyboardHidden|orientation" android:label="@string/activity_setting" + android:excludeFromRecents="true" + android:launchMode="singleTask" android:parentActivityName="net.lacolaco.smileessence.activity.MainActivity" /> <activity - android:name=".activity.ManageAccountsActivity" - android:configChanges="keyboardHidden|orientation" - android:label="@string/activity_manage_accounts" - android:parentActivityName=".activity.ManageAccountsActivity" /> - <activity android:name=".activity.EditExtractionActivity" android:configChanges="keyboardHidden|orientation" android:label="@string/activity_edit_extraction" + android:excludeFromRecents="true" + android:launchMode="singleTask" android:parentActivityName="net.lacolaco.smileessence.activity.MainActivity" /> <activity android:name=".activity.LicenseActivity" @@ -115,6 +120,8 @@ android:name=".activity.OAuthActivity" android:configChanges="keyboardHidden|orientation" android:label="@string/activity_authenticate" + android:excludeFromRecents="false" + android:launchMode="singleTask" android:parentActivityName=".activity.ManageAccountsActivity" /> </application> </manifest> diff --git a/app/src/main/java/net/lacolaco/smileessence/Application.java b/app/src/main/java/net/lacolaco/smileessence/Application.java index e46d31d6..4ad94fb9 100644 --- a/app/src/main/java/net/lacolaco/smileessence/Application.java +++ b/app/src/main/java/net/lacolaco/smileessence/Application.java @@ -24,16 +24,18 @@ package net.lacolaco.smileessence; -import android.app.Activity; -import android.os.Bundle; +import android.support.annotation.StringRes; +import android.widget.Toast; import com.crashlytics.android.Crashlytics; import com.crashlytics.android.core.CrashlyticsCore; import io.fabric.sdk.android.Fabric; -import net.lacolaco.smileessence.activity.MainActivity; import net.lacolaco.smileessence.data.Account; import net.lacolaco.smileessence.data.OrmaHolder; import net.lacolaco.smileessence.logging.Logger; -import net.lacolaco.smileessence.preference.UserPreferenceHelper; + +import java.lang.ref.WeakReference; +import java.util.HashMap; +import java.util.Map; /** * プロセスと同期しているオブジェクト @@ -42,27 +44,9 @@ import net.lacolaco.smileessence.preference.UserPreferenceHelper; */ public class Application extends android.app.Application { private static Application instance; - private MainActivity lastUsedMainActivity; - private int resId; - - @Override - public void onCreate() { - super.onCreate(); - Fabric.with(this, new Crashlytics.Builder().core(new CrashlyticsCore.Builder().disabled(BuildConfig.DEBUG).build()).build()); - OrmaHolder.initialize(this); - instance = this; // プロセスの寿命の間 1 度しか呼ばれないので安全 - registerActivityLifecycleCallbacks(new ActivityLifeCycleListener()); - Logger.debug("onCreate"); - } - - // --------------------- reset --------------------- - public void resetState() { - lastUsedMainActivity = null; - resId = -1; - } - - // --------------------- get instance --------------------- + private static Map<Long, WeakReference<World>> worlds = new HashMap<>(); // XXX + @Deprecated public static Application getInstance() { Application obj = instance; if (obj == null) { @@ -72,59 +56,47 @@ public class Application extends android.app.Application { } } - public MainActivity getLastUsedMainActivity() { - return lastUsedMainActivity; - } - - // --------------------- theme --------------------- - public int getThemeResId() { - if (resId == -1) { - Logger.debug("setting theme index: " + UserPreferenceHelper.getInstance().getThemeIndex()); - resId = UserPreferenceHelper.getInstance().getThemeIndex() == 0 ? R.style.theme_dark : R.style.theme_light; - } - return resId; - } + // --------------------- get instance --------------------- - // --------------------- current account --------------------- - public Account getCurrentAccount() { - return lastUsedMainActivity != null ? lastUsedMainActivity.getCurrentAccount() : null; + public static void toast(@StringRes int id) { + Toast.makeText(instance, id, Toast.LENGTH_LONG).show(); } - public interface OnCurrentAccountChangedListener { // will be removed - void onCurrentAccountChanged(Account newAccount); + public static void toast(String text) { + Toast.makeText(instance, text, Toast.LENGTH_LONG).show(); } - private class ActivityLifeCycleListener implements ActivityLifecycleCallbacks { - @Override - public void onActivityCreated(Activity activity, Bundle savedInstanceState) { - } - - @Override - public void onActivityStarted(Activity activity) { - } - - @Override - public void onActivityResumed(Activity activity) { - if (activity instanceof MainActivity) - lastUsedMainActivity = (MainActivity) activity; - } - - @Override - public void onActivityPaused(Activity activity) { - if (activity instanceof MainActivity) - lastUsedMainActivity = null; - } + @Override + public void onCreate() { + super.onCreate(); + Fabric.with(this, new Crashlytics.Builder().core(new CrashlyticsCore.Builder().disabled(BuildConfig.DEBUG).build()).build()); + OrmaHolder.initialize(this); - @Override - public void onActivityStopped(Activity activity) { - } + // Load eagarly + Account.load(); + instance = this; // プロセスの寿命の間 1 度しか呼ばれないので安全 + Logger.debug("onCreate"); + } - @Override - public void onActivitySaveInstanceState(Activity activity, Bundle outState) { + @Deprecated + public static World getCurrentWorld() { + for (WeakReference<World> ww : worlds.values()) { + World w = ww.get(); + if (w != null) + return w; } + return null; + } - @Override - public void onActivityDestroyed(Activity activity) { + public static World getWorld(long id) { + WeakReference<World> ww = worlds.get(id); + if (ww != null) { + World w = ww.get(); + if (w != null) + return w; } + World w = new World(Account.get(id)); + worlds.put(id, new WeakReference<>(w)); + return w; } } diff --git a/app/src/main/java/net/lacolaco/smileessence/IntentRouter.java b/app/src/main/java/net/lacolaco/smileessence/IntentRouter.java index 5ba72d1e..84e41ff6 100644 --- a/app/src/main/java/net/lacolaco/smileessence/IntentRouter.java +++ b/app/src/main/java/net/lacolaco/smileessence/IntentRouter.java @@ -29,12 +29,11 @@ import android.content.Intent; import android.net.Uri; import android.os.Bundle; import android.text.TextUtils; +import android.widget.Toast; import net.lacolaco.smileessence.activity.MainActivity; import net.lacolaco.smileessence.command.CommandOpenUserDetail; -import net.lacolaco.smileessence.data.PostState; import net.lacolaco.smileessence.entity.Tweet; import net.lacolaco.smileessence.logging.Logger; -import net.lacolaco.smileessence.notification.Notificator; import net.lacolaco.smileessence.util.UIHandler; import net.lacolaco.smileessence.view.DialogHelper; import net.lacolaco.smileessence.view.dialog.StatusDetailDialogFragment; @@ -123,13 +122,9 @@ public class IntentRouter { } private static void showStatusDialog(Activity activity, long id) { - Tweet.fetchTask(id, Application.getInstance().getCurrentAccount()) - .onDoneUI(tweet -> { - StatusDetailDialogFragment fragment = new StatusDetailDialogFragment(); - fragment.setStatusID(tweet.getId()); - DialogHelper.showDialog(activity, fragment); - }) - .onFail(x -> Notificator.getInstance().alert(R.string.error_intent_status_cannot_load)) + Tweet.fetchTask(id, Application.getCurrentWorld().getAccount()) + .onDoneUI(tweet -> DialogHelper.showDialog(activity, StatusDetailDialogFragment.newInstance(tweet))) + .onFail(x -> Application.toast(R.string.error_intent_status_cannot_load)) .execute(); } @@ -139,7 +134,7 @@ public class IntentRouter { } private static void openPostPage(final MainActivity activity, final String str) { - new UIHandler().post(() -> PostState.newState().beginTransaction().setText(str).commitWithOpen(activity)); + new UIHandler().post(() -> activity.getWorld().getPostState().beginTransaction().setText(str).commitWithOpen(activity)); } private static void openPostPageWithImage(final MainActivity activity, final Uri imageUri) { diff --git a/app/src/main/java/net/lacolaco/smileessence/World.java b/app/src/main/java/net/lacolaco/smileessence/World.java new file mode 100644 index 00000000..ae9c68cd --- /dev/null +++ b/app/src/main/java/net/lacolaco/smileessence/World.java @@ -0,0 +1,252 @@ +package net.lacolaco.smileessence; + +import android.content.Context; +import android.support.annotation.StringRes; +import de.keyboardsurfer.android.widget.crouton.Configuration; +import de.keyboardsurfer.android.widget.crouton.Crouton; +import de.keyboardsurfer.android.widget.crouton.Style; +import net.lacolaco.smileessence.activity.MainActivity; +import net.lacolaco.smileessence.data.Account; +import net.lacolaco.smileessence.data.PostState; +import net.lacolaco.smileessence.entity.DirectMessage; +import net.lacolaco.smileessence.entity.Event; +import net.lacolaco.smileessence.entity.SavedSearch; +import net.lacolaco.smileessence.entity.Tweet; +import net.lacolaco.smileessence.logging.Logger; +import net.lacolaco.smileessence.preference.UserPreferenceHelper; +import net.lacolaco.smileessence.twitter.UserStreamListener; +import net.lacolaco.smileessence.twitter.task.Accounts; +import net.lacolaco.smileessence.twitter.task.Searches; +import net.lacolaco.smileessence.twitter.task.Users; +import net.lacolaco.smileessence.util.*; +import twitter4j.TwitterStream; + +import java.lang.ref.WeakReference; +import java.util.*; +import java.util.concurrent.ConcurrentHashMap; + +/** + * World contains data that are specific to an account. + */ +public class World { + private static final int NOTIFICATION_DURATION = 1000; + private Account account; + private int resId; // XXX: Fetch from Account + // XXX: Move to MainActivity + private PostState postState = new PostState(); + // Timelines + private final List<Tweet> tweets = new ArrayList<>(); + private final WeakHashMap<Object, Consumer<Tweet>> tweetNotifiers = new WeakHashMap<>(); + // Direct messages + private final Map<Long, DirectMessage> directMessages = new ConcurrentHashMap<>(); + private final WeakHashMap<Object, Consumer<DirectMessage>> directMessageNotifiers = new WeakHashMap<>(); + // Events + private final List<Event> events = new ArrayList<>(); + private final WeakHashMap<Object, Runnable> eventNotifiers = new WeakHashMap<>(); + // Streaming APIs + private TwitterStream stream; + private UserStreamListener userStreamListener; + // Lists + private final Set<String> listSubscriptions = Collections.newSetFromMap(new ConcurrentHashMap<>()); + // Mute + private final Set<Long> muteUserIds = Collections.newSetFromMap(new ConcurrentHashMap<>()); + // Saved searches + private final Map<Long, SavedSearch> savedSearches = new HashMap<>(); + // Notification + private WeakReference<MainActivity> mainActivity; + private boolean isMainActivityActive; + + public World(Account a) { + account = a; + } + + public Account getAccount() { + return account; + } + + @Deprecated + public void setAccount(Account a) { + account = a; + } + + public PostState getPostState() { + return postState; + } + + // Timelines + + public synchronized void addTimeline(Object key, Consumer<Tweet> notify) { + for (Tweet tweet : tweets) + notify.accept(tweet); + tweetNotifiers.put(key, notify); + } + + public synchronized void addTweet(Tweet tweet) { + tweets.add(tweet); + tweetNotifiers.forEach((o, c) -> c.accept(tweet)); + } + + public synchronized void addTweetAll(Collection<Tweet> ts) { + tweets.addAll(ts); + for (Tweet tweet : ts) { + tweetNotifiers.forEach((o, c) -> c.accept(tweet)); + } + } + + // Direct messages + + public synchronized void addDirectMessageTimeline(Object key, Consumer<DirectMessage> notify) { + directMessageNotifiers.put(key, notify); + } + + public void addDirectMessage(DirectMessage entity) { + if (directMessages.put(entity.getId(), entity) == null) + directMessageNotifiers.forEach((o, c) -> c.accept(entity)); + } + + // Events + + public synchronized void addEventNotifier(Object key, Runnable notify) { + eventNotifiers.put(key, notify); + } + + public List<Event> getEvents() { + return events; + } + + public void addEvent(Event e) { + events.add(e); + eventNotifiers.forEach((o, a) -> a.run()); + } + + // Streaming APIs + + public void setupStreaming() { + if (stream == null) { + stream = account.getTwitterStream(); + userStreamListener = new UserStreamListener(this); + stream.addListener(userStreamListener); + stream.addConnectionLifeCycleListener(userStreamListener); + stream.user(); + } + } + + public boolean isStreaming() { + return stream != null && userStreamListener.isConnected(); + } + + // Lists + + public BackgroundTask<List<String>, Void> refreshListSubscriptions() { + return new Users.GetManyTask(account) + .onDone(lists -> { + listSubscriptions.clear(); + listSubscriptions.addAll(lists); + }) + // .onFail(x -> { }) // TODO: error message? + .execute(); + } + + public Set<String> getListSubscriptions() { + return listSubscriptions; + } + + public boolean addListSubscription(String fullName) { + return listSubscriptions.add(fullName); + } + + public boolean removeListSubscription(String fullName) { + return listSubscriptions.remove(fullName); + } + + // Mute + + public List<BackgroundTask> refreshUserMuteList() { + List<BackgroundTask> tasks = new ArrayList<>(); + tasks.add(new Accounts.BlockIDsTask(account).onDone(muteUserIds::addAll).execute()); + tasks.add(new Accounts.MutesIDsTask(account).onDone(muteUserIds::addAll).execute()); + return tasks; + } + + public boolean isMutedUserListContains(long id) { + return muteUserIds.contains(id); + } + + // Saved search queries + + public Collection<SavedSearch> getSavedSearches() { + return savedSearches.values(); + } + + public BackgroundTask<List<SavedSearch>, Void> refreshSavedSearches() { + return new Searches.GetAllSavedSearchesTask(account).onDone(ssl -> { + savedSearches.clear(); + for (SavedSearch ss : ssl) + savedSearches.put(ss.getId(), ss); + }).execute(); + } + + // Notifications + + public void setMainActivity(MainActivity activity) { + mainActivity = new WeakReference<>(activity); + } + + public void setMainActivityActive(boolean yes) { + isMainActivityActive = yes; + } + + public void notify(String text) { + doNotify(NotificationType.INFO, text); + } + + public void notify(@StringRes int resId, Object... formatArgs) { + doNotify(NotificationType.INFO, resId, formatArgs); + } + + public void notifyError(String text) { + doNotify(NotificationType.ALERT, text); + } + + public void notifyError(@StringRes int resId, Object... formatArgs) { + doNotify(NotificationType.ALERT, resId, formatArgs); + } + + private void doNotify(NotificationType type, @StringRes int resId, Object... formatArgs) { + Context context = mainActivity.get(); + if (context != null) { + String text = context.getString(resId, formatArgs); + doNotify(type, text); + } else { + Logger.debug("MainActivity is dead"); + } + } + + private void doNotify(NotificationType type, String text) { + MainActivity activity = mainActivity.get(); + if (activity == null || activity.isFinishing()) { + Logger.debug(String.format("notify(log): %s", text)); + } else { + new UIHandler().post(() -> { + if (isMainActivityActive) { + Logger.debug(String.format("notify(crouton): %s", text)); + Configuration.Builder conf = new Configuration.Builder(); + conf.setDuration(NOTIFICATION_DURATION); + Style.Builder bstyle = new Style.Builder(); + bstyle.setConfiguration(conf.build()); + bstyle.setBackgroundColorValue(type == NotificationType.ALERT ? + Style.holoRedLight : Style.holoBlueLight); + Crouton.makeText(activity, text, bstyle.build()).show(); + } else { + Logger.debug(String.format("notify(toast): %s", text)); + Application.toast(text); + } + }); + } + } + + enum NotificationType { + INFO, + ALERT + } +} diff --git a/app/src/main/java/net/lacolaco/smileessence/activity/EditExtractionActivity.java b/app/src/main/java/net/lacolaco/smileessence/activity/EditExtractionActivity.java index a0cb91d2..3876d506 100644 --- a/app/src/main/java/net/lacolaco/smileessence/activity/EditExtractionActivity.java +++ b/app/src/main/java/net/lacolaco/smileessence/activity/EditExtractionActivity.java @@ -36,30 +36,22 @@ import android.widget.TextView; import net.lacolaco.smileessence.Application; import net.lacolaco.smileessence.R; import net.lacolaco.smileessence.data.ExtractionWord; -import net.lacolaco.smileessence.entity.IdObject; import net.lacolaco.smileessence.logging.Logger; import net.lacolaco.smileessence.view.DialogHelper; -import net.lacolaco.smileessence.view.adapter.OrderedCustomListAdapter; +import net.lacolaco.smileessence.view.adapter.CustomListAdapter; import net.lacolaco.smileessence.view.dialog.EditTextDialogFragment; -import net.lacolaco.smileessence.viewmodel.IViewModel; -public class EditExtractionActivity extends Activity implements AbsListView.MultiChoiceModeListener { - - // ------------------------------ FIELDS ------------------------------ - - private OrderedCustomListAdapter<ExtractionWordViewModel> adapter; +import java.util.ArrayList; +import java.util.List; - // --------------------- GETTER / SETTER METHODS --------------------- +public class EditExtractionActivity extends Activity implements AbsListView.MultiChoiceModeListener { + private List<ExtractionWord> list; + private CustomListAdapter<ExtractionWord> adapter; private ListView getListView() { return (ListView) findViewById(R.id.listview_edit_list); } - // ------------------------ INTERFACE METHODS ------------------------ - - - // --------------------- Interface Callback --------------------- - @Override public boolean onCreateActionMode(ActionMode mode, Menu menu) { menu.clear(); @@ -88,22 +80,39 @@ public class EditExtractionActivity extends Activity implements AbsListView.Mult public void onDestroyActionMode(ActionMode mode) { } - // --------------------- Interface MultiChoiceModeListener --------------------- - @Override public void onItemCheckedStateChanged(ActionMode mode, int position, long id, boolean checked) { } - // ------------------------ OVERRIDE METHODS ------------------------ - @Override protected void onCreate(Bundle savedInstanceState) { - setTheme(Application.getInstance().getThemeResId()); + Logger.debug("onCreate"); super.onCreate(savedInstanceState); setContentView(R.layout.layout_edit_list); - initializeViews(); - Logger.debug("onCreate"); + ListView listView = getListView(); + list = new ArrayList<>(); + adapter = new CustomListAdapter<ExtractionWord>() { + @Override + public View getView(int position, View convertView, ViewGroup parent) { + if (convertView == null) { + convertView = EditExtractionActivity.this.getLayoutInflater().inflate(R.layout.list_item_simple_text, null); + } + TextView textView = (TextView) convertView.findViewById(R.id.list_item_textview); + textView.setText(getItem(position).getPatternString()); + return convertView; + } + + @Override + protected List<ExtractionWord> getList() { + return list; + } + }; + list.addAll(ExtractionWord.cached()); + adapter.update(); + listView.setAdapter(adapter); + listView.setChoiceMode(ListView.CHOICE_MODE_MULTIPLE_MODAL); + listView.setMultiChoiceModeListener(this); } @Override @@ -135,13 +144,12 @@ public class EditExtractionActivity extends Activity implements AbsListView.Mult SparseBooleanArray checkedItems = getListView().getCheckedItemPositions(); for (int i = adapter.getCount() - 1; i > -1; i--) { if (checkedItems.get(i)) { - ExtractionWordViewModel vm = adapter.getItem(i); - vm.getExtractionWord().remove(); - adapter.removeItem(vm); + ExtractionWord ew = adapter.getItem(i); + list.remove(ew); + ew.remove(); } } - adapter.notifyDataSetChanged(); - updateListView(); + adapter.update(); } private void addNewExtractionWord() { @@ -152,59 +160,11 @@ public class EditExtractionActivity extends Activity implements AbsListView.Mult return; } ExtractionWord extractionWord = ExtractionWord.add(text); - adapter.addItem(new ExtractionWordViewModel(extractionWord)); - adapter.notifyDataSetChanged(); - updateListView(); + list.add(extractionWord); + adapter.update(); } }; dialogFragment.setParams(getString(R.string.dialog_title_add), ""); - DialogHelper.showDialog(this, dialogFragment); - } - - private void initializeViews() { - ListView listView = getListView(); - adapter = new OrderedCustomListAdapter<>(this); - for (ExtractionWord ew : ExtractionWord.cached()) { - adapter.addItem(new ExtractionWordViewModel(ew)); - } - adapter.update(); - listView.setAdapter(adapter); - listView.setChoiceMode(ListView.CHOICE_MODE_MULTIPLE_MODAL); - listView.setMultiChoiceModeListener(this); - } - - private void updateListView() { - getListView().requestLayout(); - } - - - // --------------------- Interface IViewModel --------------------- - - - private static class ExtractionWordViewModel implements IViewModel, IdObject { - private final ExtractionWord ew; - - public ExtractionWordViewModel(ExtractionWord ew) { - this.ew = ew; - } - - public ExtractionWord getExtractionWord() { - return ew; - } - - @Override - public View getView(Activity activity, LayoutInflater inflater, View convertedView) { - if (convertedView == null) { - convertedView = inflater.inflate(R.layout.list_item_simple_text, null); - } - TextView textView = (TextView) convertedView.findViewById(R.id.list_item_textview); - textView.setText(ew.getPatternString()); - return convertedView; - } - - @Override - public long getId() { - return ew.getPatternString().hashCode(); - } + dialogFragment.show(getFragmentManager(), "EDIT_TEXT"); } } diff --git a/app/src/main/java/net/lacolaco/smileessence/activity/LicenseActivity.java b/app/src/main/java/net/lacolaco/smileessence/activity/LicenseActivity.java index 74cf3a50..23957c57 100644 --- a/app/src/main/java/net/lacolaco/smileessence/activity/LicenseActivity.java +++ b/app/src/main/java/net/lacolaco/smileessence/activity/LicenseActivity.java @@ -46,7 +46,6 @@ public class LicenseActivity extends Activity { apacheFiles.add(getString(R.string.library_name_crouton)); apacheFiles.add(getString(R.string.library_name_pull_to_refresh)); apacheFiles.add(getString(R.string.library_name_volley)); - apacheFiles.add(getString(R.string.library_name_guava)); apacheFiles.add(getString(R.string.library_name_twitter_text)); return apacheFiles; } @@ -55,7 +54,6 @@ public class LicenseActivity extends Activity { @Override public void onCreate(Bundle savedInstanceState) { - setTheme(Application.getInstance().getThemeResId()); super.onCreate(savedInstanceState); setContentView(R.layout.layout_license); diff --git a/app/src/main/java/net/lacolaco/smileessence/activity/MainActivity.java b/app/src/main/java/net/lacolaco/smileessence/activity/MainActivity.java index 4e1b50e0..f6351f30 100644 --- a/app/src/main/java/net/lacolaco/smileessence/activity/MainActivity.java +++ b/app/src/main/java/net/lacolaco/smileessence/activity/MainActivity.java @@ -26,88 +26,49 @@ package net.lacolaco.smileessence.activity; import android.app.ActionBar; import android.app.Activity; -import android.content.Context; import android.content.Intent; -import android.content.pm.PackageManager; import android.database.Cursor; import android.net.Uri; -import android.os.Build; import android.os.Bundle; import android.provider.MediaStore; -import android.support.annotation.NonNull; -import android.support.v4.app.ActivityCompat; -import android.support.v4.content.ContextCompat; import android.support.v4.view.ViewPager; import android.view.Menu; import android.view.MenuItem; import android.view.WindowManager; import android.widget.ImageView; import de.keyboardsurfer.android.widget.crouton.Crouton; -import net.lacolaco.smileessence.Application; -import net.lacolaco.smileessence.BuildConfig; -import net.lacolaco.smileessence.IntentRouter; -import net.lacolaco.smileessence.R; +import net.lacolaco.smileessence.*; import net.lacolaco.smileessence.data.Account; import net.lacolaco.smileessence.data.ExtractionWord; -import net.lacolaco.smileessence.data.PostState; import net.lacolaco.smileessence.entity.RBinding; import net.lacolaco.smileessence.entity.User; import net.lacolaco.smileessence.logging.Logger; -import net.lacolaco.smileessence.notification.Notificator; -import net.lacolaco.smileessence.preference.InternalPreferenceHelper; -import net.lacolaco.smileessence.twitter.UserStreamListener; import net.lacolaco.smileessence.twitter.task.Users; -import net.lacolaco.smileessence.util.*; +import net.lacolaco.smileessence.util.BitmapOptimizer; +import net.lacolaco.smileessence.util.BitmapURLTask; +import net.lacolaco.smileessence.util.IntentUtils; +import net.lacolaco.smileessence.util.UIObserverBundle; import net.lacolaco.smileessence.view.adapter.PageListAdapter; import net.lacolaco.smileessence.view.dialog.ConfirmDialogFragment; import net.lacolaco.smileessence.view.page.*; -import twitter4j.TwitterStream; - -import java.lang.reflect.Field; -import java.util.Collections; -import java.util.Set; -import java.util.WeakHashMap; - -public class MainActivity extends Activity implements Application.OnCurrentAccountChangedListener, ViewPager.OnPageChangeListener { - // ------------------------------ FIELDS ------------------------------ +public class MainActivity extends Activity implements ViewPager.OnPageChangeListener { public static final int REQUEST_GET_PICTURE_FROM_GALLERY = 11; - private static final int REQUEST_MANAGE_ACCOUNT = 13; - private static final int REQUEST_WRITE_EXTERNAL_STORAGE_PERMISSION = 14; - private Account currentAccount; - private final Set<Application.OnCurrentAccountChangedListener> currentAccountChangedListeners = Collections.newSetFromMap(new WeakHashMap<>()); /* will be removed eventually */ + private final UIObserverBundle currentUserBundle = new UIObserverBundle(); + private World world; private ViewPager viewPager; private ImageView currentAccountIconImageView; private PageListAdapter pagerAdapter; - private TwitterStream stream; - private UserStreamListener userStreamListener; - private final UIObserverBundle currentUserBundle = new UIObserverBundle(); - - public Account getCurrentAccount() { - return currentAccount; - } - - public void setCurrentAccount(Account val) { - Logger.debug(String.format("setCurrentAccount: %s", val.getUser().getScreenName())); - currentAccount = val; - for (Application.OnCurrentAccountChangedListener listener : currentAccountChangedListeners) { - new UIHandler().post(() -> listener.onCurrentAccountChanged(val)); - } - } - - public void addOnCurrentAccountChangedListener(Application.OnCurrentAccountChangedListener listener) { - currentAccountChangedListeners.add(listener); - } - public boolean isStreaming() { - return userStreamListener != null && userStreamListener.isConnected(); + public World getWorld() { + return world; } - public void setSelectedPageIndex(int position) { + private void setSelectedPageIndex(int position) { setSelectedPageIndex(position, true); } - public void setSelectedPageIndex(int position, boolean smooth) { + private void setSelectedPageIndex(int position, boolean smooth) { viewPager.setCurrentItem(position, smooth); } @@ -125,15 +86,15 @@ public class MainActivity extends Activity implements Application.OnCurrentAccou assert c != null; c.moveToFirst(); String path = c.getString(c.getColumnIndex(MediaStore.MediaColumns.DATA)); - String rotatedPath = BitmapOptimizer.rotateImageByExif(this, path); - PostState.getState().beginTransaction() + String rotatedPath = path; // BitmapOptimizer.rotateImageByExif(this, path); + world.getPostState().beginTransaction() .setMediaFilePath(rotatedPath) .commitWithOpen(this); - Notificator.getInstance().publish(R.string.notice_select_image_succeeded); + world.notify(R.string.notice_select_image_succeeded); c.close(); } catch (Exception e) { e.printStackTrace(); - Notificator.getInstance().alert(R.string.notice_select_image_failed); + world.notifyError(R.string.notice_select_image_failed); } } @@ -171,29 +132,20 @@ public class MainActivity extends Activity implements Application.OnCurrentAccou @Override public void finish() { if (viewPager == null) { - forceFinish(); + super.finish(); return; } int homeIndex = pagerAdapter.getIndex(HomeFragment.class); if (viewPager.getCurrentItem() != homeIndex) { viewPager.setCurrentItem(homeIndex, true); } else { - ConfirmDialogFragment.show(this, getString(R.string.dialog_confirm_finish_app), this::forceFinish); + ConfirmDialogFragment.show(this, getString(R.string.dialog_confirm_finish_app), super::finish); } } - public void forceFinish() { - super.finish(); - } - @Override protected void onActivityResult(int requestCode, int resultCode, Intent data) { switch (requestCode) { - case REQUEST_MANAGE_ACCOUNT: - if (resultCode == RESULT_CANCELED && getCurrentAccount() == null) { - forceFinish(); - } - break; case REQUEST_GET_PICTURE_FROM_GALLERY: getImageUri(requestCode, resultCode, data); break; @@ -203,61 +155,91 @@ public class MainActivity extends Activity implements Application.OnCurrentAccou @Override public void onCreate(Bundle savedInstanceState) { Logger.debug("onCreate"); - Application app = (Application) getApplication(); - app.resetState(); - setTheme(app.getThemeResId()); super.onCreate(savedInstanceState); + + Uri uri = getIntent().getData(); + if (uri == null) { + throw new IllegalStateException("[BUG] data not set"); + } + String userIdValue = uri.getQueryParameter("user_id"); + if (userIdValue == null) + throw new IllegalStateException("[BUG] user_id not set"); + long userId = Long.parseLong(userIdValue); + world = Application.getWorld(userId); + world.setMainActivity(this); + + // XXX + Account account = world.getAccount(); + + setTheme(account.themeIndex == 0 ? R.style.theme_dark : R.style.theme_light); setContentView(R.layout.layout_main); viewPager = (ViewPager) findViewById(R.id.viewPager); pagerAdapter = new PageListAdapter(this); viewPager.addOnPageChangeListener(this); + getActionBar().setDisplayHomeAsUpEnabled(true); currentAccountIconImageView = (ImageView) findViewById(android.R.id.home); currentAccountIconImageView.setScaleType(ImageView.ScaleType.FIT_XY); - Notificator.getInstance().setDefault(this); - Account.load(); + // TODO: tab order? + Bundle args = new Bundle(); + args.putLong(PageFragment.KEY_USER_ID, account.getUserId()); + pagerAdapter.addPage(PostFragment.class, getString(R.string.page_name_post), args, false); + pagerAdapter.addPage(HomeFragment.class, getString(R.string.page_name_home), args, false); + pagerAdapter.addPage(MentionsFragment.class, getString(R.string.page_name_mentions), args, false); + pagerAdapter.addPage(HistoryFragment.class, getString(R.string.page_name_history), args, false); + pagerAdapter.addPage(MessagesFragment.class, getString(R.string.page_name_messages), args, false); + pagerAdapter.addPage(SearchFragment.class, getString(R.string.page_name_search), args, false); + pagerAdapter.addPage(UserListFragment.class, getString(R.string.page_name_list), args, false); + pagerAdapter.notifyDataSetChanged(); + viewPager.setOffscreenPageLimit(pagerAdapter.getCount()); + viewPager.setAdapter(pagerAdapter); + setSelectedPageIndex(pagerAdapter.getIndex(HomeFragment.class), false); + ExtractionWord.load(); - initializePages(); - addOnCurrentAccountChangedListener(this); - int wextPermission = ContextCompat.checkSelfPermission(this, android.Manifest.permission.WRITE_EXTERNAL_STORAGE); - if (wextPermission == PackageManager.PERMISSION_GRANTED) { - startMainLogic(); - } else { - requestPermission(); - } - } + // update cache + world.refreshListSubscriptions(); + world.refreshUserMuteList(); + world.refreshSavedSearches(); + new Users.GetTask(account, account.getUserId()).execute(); - private void requestPermission() { - ActivityCompat.requestPermissions(this, new String[]{android.Manifest.permission.WRITE_EXTERNAL_STORAGE}, REQUEST_WRITE_EXTERNAL_STORAGE_PERMISSION); - } + User user = account.getUser(); - @Override - public void onRequestPermissionsResult(int requestCode, @NonNull String permissions[], @NonNull int[] grantResults) { - switch (requestCode) { - case REQUEST_WRITE_EXTERNAL_STORAGE_PERMISSION: { - if (grantResults.length > 0 && grantResults[0] == PackageManager.PERMISSION_GRANTED) { - // permission granted; start main logic - startMainLogic(); - } else { - // permission denied; どうする? - Notificator.getInstance().alert(R.string.notice_error_storage_permission); - forceFinish(); - } - break; + // Set application title + setTitle(); + + // update actionbar + Runnable update = () -> { + setTitle(); + updateActionBarTitle(); + String newUrl = user.getProfileImageUrlOriginal(); + if (newUrl != null) { + new BitmapURLTask(newUrl, currentAccountIconImageView).execute(); + } + }; + update.run(); //first run + + currentUserBundle.detachAll(); + currentUserBundle.attach(user, changes -> { + if (changes.contains(RBinding.BASIC)) update.run(); + }); + + // refresh all pages + for (int i = 0; i < pagerAdapter.getCount(); ++i) { + PageFragment pf = pagerAdapter.getCachedFragment(i); + if (pf != null && pf.isAdded()) { + Logger.debug(String.format("PageFragment %s is already attached; refreshing", pf.getClass().getName())); + pf.refresh(); } } + + // start user stream + world.setupStreaming(); } - private void startMainLogic() { - Account account = getLastUsedAccount(); - if (account != null) { - setCurrentAccount(account); - IntentRouter.onNewIntent(this, getIntent()); - } else { - startActivityForResult(new Intent(this, ManageAccountsActivity.class), REQUEST_MANAGE_ACCOUNT); - } + private void setTitle() { + setTitle(getString(R.string.app_name) + " - @" + world.getAccount().getUser().getScreenName()); } @Override @@ -265,19 +247,10 @@ public class MainActivity extends Activity implements Application.OnCurrentAccou super.onDestroy(); currentUserBundle.detachAll(); Crouton.cancelAllCroutons(); - if (stream != null) { - new Thread(stream::shutdown).start(); - } Logger.debug("onDestroy"); } @Override - protected void onNewIntent(Intent intent) { - IntentRouter.onNewIntent(this, intent); - super.onNewIntent(intent); - } - - @Override public boolean onCreateOptionsMenu(Menu menu) { getMenuInflater().inflate(R.menu.main, menu); return true; @@ -286,52 +259,46 @@ public class MainActivity extends Activity implements Application.OnCurrentAccou @Override public boolean onOptionsItemSelected(MenuItem item) { switch (item.getItemId()) { - case R.id.actionbar_post: { - openPostPage(); + case android.R.id.home: { + Intent intent = new Intent(this, ManageAccountsActivity.class); + intent.putExtra(ManageAccountsActivity.INTENT_KEY_NOINIT, true); + startActivity(intent); return true; } - case R.id.actionbar_setting: { - startActivity(new Intent(this, SettingActivity.class)); + case R.id.actionbar_post: + openPostPage(); return true; - } - case R.id.actionbar_accounts: { - startActivity(new Intent(this, ManageAccountsActivity.class)); + case R.id.actionbar_setting: + startActivity(new Intent(this, SettingActivity.class)); return true; - } - case R.id.actionbar_edit_extraction: { + case R.id.actionbar_edit_extraction: startActivity(new Intent(this, EditExtractionActivity.class)); return true; - } - case R.id.actionbar_aclog: { - IntentUtils.openUri(this, getCurrentAccount().getUser().getAclogTimelineURL()); + case R.id.actionbar_aclog: + IntentUtils.openUri(this, world.getAccount().getUser().getAclogTimelineURL()); return true; - } - case R.id.actionbar_report: { - PostState.getState().beginTransaction() + case R.id.actionbar_report: + world.getPostState().beginTransaction() .appendText(getString(R.string.text_message_to_author, BuildConfig.VERSION_NAME)) .commitWithOpen(this); return true; - } - default: { - return false; - } + default: + return super.onOptionsItemSelected(item); } } @Override protected void onPause() { - super.onPause(); Logger.debug("onPause"); - getWindow().clearFlags(WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON); - Notificator.getInstance().onBackground(); + super.onPause(); + world.setMainActivityActive(false); } @Override protected void onResume() { - super.onResume(); Logger.debug("onResume"); - getWindow().addFlags(WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON); - Notificator.getInstance().onForeground(); + super.onResume(); + world.setMainActivityActive(true); } // --------------------- Interface OnPageChangeListener --------------------- @@ -355,97 +322,20 @@ public class MainActivity extends Activity implements Application.OnCurrentAccou private void getImageUri(int requestCode, int resultCode, Intent data) { if (resultCode != RESULT_OK) { Logger.error(requestCode); - Notificator.getInstance().alert(R.string.notice_select_image_failed); + world.notifyError(R.string.notice_select_image_failed); finish(); return; } openPostPageWithImage(data.getData()); } - private void startStream() { - if (stream != null) { - new Thread(stream::cleanUp).start(); - } - stream = getCurrentAccount().getTwitterStream(); - userStreamListener = new UserStreamListener(getCurrentAccount()); - stream.addListener(userStreamListener); - stream.addConnectionLifeCycleListener(userStreamListener); - stream.user(); - } - - @Override - public void onCurrentAccountChanged(Account account) { - // update cache - account.refreshListSubscriptions(); - account.refreshUserMuteList(); - account.refreshSavedSearches(); - new Users.GetTask(account, account.getUserId()).execute(); - - User user = account.getUser(); - - // update actionbar - Runnable update = () -> { - updateActionBarTitle(); - String newUrl = user.getProfileImageUrlOriginal(); - if (newUrl != null) { - new BitmapURLTask(newUrl, currentAccountIconImageView).execute(); - } - }; - update.run(); //first run - - currentUserBundle.detachAll(); - currentUserBundle.attach(user, changes -> { - if (changes.contains(RBinding.BASIC)) update.run(); - }); - - // refresh all pages - for (int i = 0; i < pagerAdapter.getCount(); ++i) { - PageFragment pf = pagerAdapter.getCachedFragment(i); - if (pf != null && pf.isAdded()) { - Logger.debug(String.format("PageFragment %s is already attached; refreshing", pf.getClass().getName())); - pf.refresh(); - } - } - - // start user stream - startStream(); - } - private void updateActionBarTitle() { ActionBar actionBar = getActionBar(); - Account currentAccount = getCurrentAccount(); - if (actionBar != null && currentAccount != null) { + Account currentAccount = world.getAccount(); + if (actionBar != null) { String screenName = currentAccount.getUser().getScreenName(); String pageTitle = pagerAdapter.getName(viewPager.getCurrentItem()); setTitle(String.format("%s / %s", screenName, pageTitle)); } } - - // TODO: tab order? - private void initializePages() { - pagerAdapter.addPage(PostFragment.class, getString(R.string.page_name_post), null, false); - pagerAdapter.addPage(HomeFragment.class, getString(R.string.page_name_home), null, false); - pagerAdapter.addPage(MentionsFragment.class, getString(R.string.page_name_mentions), null, false); - pagerAdapter.addPage(HistoryFragment.class, getString(R.string.page_name_history), null, false); - pagerAdapter.addPage(MessagesFragment.class, getString(R.string.page_name_messages), null, false); - pagerAdapter.addPage(SearchFragment.class, getString(R.string.page_name_search), null, false); - pagerAdapter.addPage(UserListFragment.class, getString(R.string.page_name_list), null, false); - pagerAdapter.notifyDataSetChanged(); - viewPager.setOffscreenPageLimit(pagerAdapter.getCount()); - viewPager.setAdapter(pagerAdapter); - setSelectedPageIndex(pagerAdapter.getIndex(HomeFragment.class), false); - PostState.newState().beginTransaction().commit(); - } - - private Account getLastUsedAccount() { - long lastId = InternalPreferenceHelper.getInstance().get(R.string.key_last_used_account_id, -1L); - Account account = null; - if (lastId != -1) { - account = Account.get(lastId); - } - if (account == null && Account.count() > 0) { - account = Account.all().get(0); - } - return account; - } } diff --git a/app/src/main/java/net/lacolaco/smileessence/activity/ManageAccountsActivity.java b/app/src/main/java/net/lacolaco/smileessence/activity/ManageAccountsActivity.java index e95e9dd9..28d99ab6 100644 --- a/app/src/main/java/net/lacolaco/smileessence/activity/ManageAccountsActivity.java +++ b/app/src/main/java/net/lacolaco/smileessence/activity/ManageAccountsActivity.java @@ -26,7 +26,12 @@ package net.lacolaco.smileessence.activity; import android.app.Activity; import android.content.Intent; +import android.content.pm.PackageManager; +import android.net.Uri; import android.os.Bundle; +import android.support.annotation.NonNull; +import android.support.v4.app.ActivityCompat; +import android.support.v4.content.ContextCompat; import android.view.Menu; import android.view.MenuItem; import android.view.View; @@ -35,11 +40,10 @@ import android.widget.*; import com.android.volley.toolbox.NetworkImageView; import net.lacolaco.smileessence.Application; import net.lacolaco.smileessence.R; +import net.lacolaco.smileessence.World; import net.lacolaco.smileessence.data.Account; import net.lacolaco.smileessence.data.ImageCache; import net.lacolaco.smileessence.logging.Logger; -import net.lacolaco.smileessence.notification.Notificator; -import net.lacolaco.smileessence.preference.InternalPreferenceHelper; import net.lacolaco.smileessence.twitter.OAuthSession; import net.lacolaco.smileessence.view.dialog.ConfirmDialogFragment; @@ -47,25 +51,64 @@ import java.util.ArrayList; import java.util.List; public class ManageAccountsActivity extends Activity implements AdapterView.OnItemClickListener, AdapterView.OnItemLongClickListener { + public static final String INTENT_KEY_NOINIT = "noInit"; private static final int REQUEST_OAUTH = 10; + private static final int REQUEST_WRITE_EXTERNAL_STORAGE_PERMISSION = 11; private EditAccountsAdapter adapter; - private Account newAccount; @Override protected void onCreate(Bundle savedInstanceState) { - setTheme(Application.getInstance().getThemeResId()); super.onCreate(savedInstanceState); - setContentView(R.layout.layout_edit_list); - newAccount = Application.getInstance().getCurrentAccount(); + // Check if it is initiated from launcher + if (!getIntent().getBooleanExtra(INTENT_KEY_NOINIT, false)) { + int wextPermission = ContextCompat.checkSelfPermission(this, android.Manifest.permission.WRITE_EXTERNAL_STORAGE); + if (wextPermission != PackageManager.PERMISSION_GRANTED) { + ActivityCompat.requestPermissions(this, new String[]{android.Manifest.permission.WRITE_EXTERNAL_STORAGE}, REQUEST_WRITE_EXTERNAL_STORAGE_PERMISSION); + } + + // Skip this activity if app is already started + World currentWorld = Application.getCurrentWorld(); + if (currentWorld != null) { + goToWorld(currentWorld); + return; + } + } + setContentView(R.layout.layout_edit_list); adapter = new EditAccountsAdapter(); ListView listView = (ListView) findViewById(R.id.listview_edit_list); listView.setAdapter(adapter); listView.setOnItemClickListener(this); listView.setOnItemLongClickListener(this); + } - Logger.debug("onCreate"); + @Override + public void onRequestPermissionsResult(int requestCode, @NonNull String permissions[], @NonNull int[] grantResults) { + switch (requestCode) { + case REQUEST_WRITE_EXTERNAL_STORAGE_PERMISSION: { + if (grantResults.length > 0 && grantResults[0] == PackageManager.PERMISSION_GRANTED) { + // OK + World currentWorld = Application.getCurrentWorld(); + if (currentWorld != null) { + goToWorld(currentWorld); + } + } else { + Application.toast(R.string.notice_error_storage_permission); + // TODO: Kill Process? + finish(); + } + break; + } + } + } + + private void goToWorld(World world) { + // Continue the existing MainActivity + Intent intent = new Intent(this, MainActivity.class); + intent.setData(Uri.parse("smileessence://mainactivity/?user_id=" + world.getAccount().getUserId())); + finish(); + startActivity(intent); } @Override @@ -79,10 +122,7 @@ public class ManageAccountsActivity extends Activity implements AdapterView.OnIt @Override public void onItemClick(AdapterView<?> adapterView, View view, int i, long l) { Account account = adapter.getItem(i); - if (account != newAccount) { - newAccount = account; - adapter.notifyDataSetChanged(); - } + goToWorld(Application.getWorld(account.getUserId())); } @Override @@ -93,14 +133,10 @@ public class ManageAccountsActivity extends Activity implements AdapterView.OnIt ConfirmDialogFragment.show(this, getString(R.string.dialog_confirm_clear_account, account.getUser().getScreenName()), () -> { adapter.removeAt(i); Account.unregister(account.getUserId()); - if (account == newAccount) { - newAccount = adapter.getItem(0); - adapter.notifyDataSetChanged(); - } }, false); return true; } else { - Notificator.getInstance().alert(R.string.notice_cant_remove_last_account); + Application.toast(R.string.notice_cant_remove_last_account); return false; } } @@ -125,18 +161,13 @@ public class ManageAccountsActivity extends Activity implements AdapterView.OnIt } private void safeFinish() { - if (newAccount != null) { - if (newAccount != Application.getInstance().getCurrentAccount()) { - Application.getInstance().getLastUsedMainActivity().setCurrentAccount(newAccount); - InternalPreferenceHelper.getInstance().set(R.string.key_last_used_account_id, newAccount.getUserId()); - } - setResult(RESULT_OK); - finish(); + World currentWorld = Application.getCurrentWorld(); + + if (currentWorld != null) { + goToWorld(currentWorld); } else { - ConfirmDialogFragment.show(this, getString(R.string.notice_no_account_selected), () -> { - setResult(RESULT_CANCELED); - finish(); - }); + setResult(RESULT_CANCELED); + finish(); } } @@ -160,13 +191,10 @@ public class ManageAccountsActivity extends Activity implements AdapterView.OnIt data.getStringExtra(OAuthSession.KEY_TOKEN_SECRET), data.getLongExtra(OAuthSession.KEY_USER_ID, -1L), data.getStringExtra(OAuthSession.KEY_SCREEN_NAME)); - if (newAccount == null) { - newAccount = account; - } adapter.add(account); } else { Logger.error(requestCode); - Notificator.getInstance().alert(R.string.notice_error_authenticate); + Application.toast(R.string.notice_error_authenticate); } } @@ -205,9 +233,6 @@ public class ManageAccountsActivity extends Activity implements AdapterView.OnIt String text = "@" + account.getUser().getScreenName(); textView.setText(text); - RadioButton radioButton = (RadioButton) convertView.findViewById(R.id.account_radio_button); - radioButton.setChecked(account == newAccount); - return convertView; } diff --git a/app/src/main/java/net/lacolaco/smileessence/activity/OAuthActivity.java b/app/src/main/java/net/lacolaco/smileessence/activity/OAuthActivity.java index 70520874..e3d15bc2 100644 --- a/app/src/main/java/net/lacolaco/smileessence/activity/OAuthActivity.java +++ b/app/src/main/java/net/lacolaco/smileessence/activity/OAuthActivity.java @@ -34,14 +34,12 @@ import android.view.View; import android.widget.Button; import android.widget.EditText; import android.widget.TextView; +import net.lacolaco.smileessence.Application; import net.lacolaco.smileessence.R; -import net.lacolaco.smileessence.notification.Notificator; import net.lacolaco.smileessence.twitter.OAuthSession; import twitter4j.auth.AccessToken; public class OAuthActivity extends Activity implements View.OnClickListener, TextWatcher { - - private TextView linkTextView; private EditText pinEditText; private Button authButton; private OAuthSession oauthSession; @@ -51,7 +49,7 @@ public class OAuthActivity extends Activity implements View.OnClickListener, Tex super.onCreate(savedInstanceState); setContentView(R.layout.layout_oauth); - linkTextView = (TextView) findViewById(R.id.textView_oauth_link); + TextView linkTextView = (TextView) findViewById(R.id.textView_oauth_link); pinEditText = (EditText) findViewById(R.id.editText_oauth_pin); pinEditText.addTextChangedListener(this); authButton = (Button) findViewById(R.id.button_oauth_auth); @@ -63,7 +61,7 @@ public class OAuthActivity extends Activity implements View.OnClickListener, Tex if (!TextUtils.isEmpty(url)) { linkTextView.setText(url); } else { - Notificator.getInstance().alert(R.string.notice_error_authenticate_request); + Application.toast(R.string.notice_error_authenticate_request); finish(); } } diff --git a/app/src/main/java/net/lacolaco/smileessence/activity/SettingActivity.java b/app/src/main/java/net/lacolaco/smileessence/activity/SettingActivity.java index c9370025..87f44e16 100644 --- a/app/src/main/java/net/lacolaco/smileessence/activity/SettingActivity.java +++ b/app/src/main/java/net/lacolaco/smileessence/activity/SettingActivity.java @@ -32,12 +32,8 @@ import net.lacolaco.smileessence.Application; import net.lacolaco.smileessence.R; public class SettingActivity extends Activity { - - // ------------------------ OVERRIDE METHODS ------------------------ - @Override protected void onCreate(Bundle savedInstanceState) { - setTheme(Application.getInstance().getThemeResId()); super.onCreate(savedInstanceState); setContentView(R.layout.layout_setting); } diff --git a/app/src/main/java/net/lacolaco/smileessence/command/Command.java b/app/src/main/java/net/lacolaco/smileessence/command/Command.java index 33a65912..0225b886 100644 --- a/app/src/main/java/net/lacolaco/smileessence/command/Command.java +++ b/app/src/main/java/net/lacolaco/smileessence/command/Command.java @@ -24,86 +24,19 @@ package net.lacolaco.smileessence.command; -import android.app.Activity; -import android.view.LayoutInflater; -import android.view.View; -import android.widget.TextView; -import net.lacolaco.smileessence.R; -import net.lacolaco.smileessence.command.message.MessageCommandCopyTextToClipboard; -import net.lacolaco.smileessence.command.status.*; -import net.lacolaco.smileessence.command.user.*; -import net.lacolaco.smileessence.entity.DirectMessage; -import net.lacolaco.smileessence.entity.Tweet; -import net.lacolaco.smileessence.entity.User; -import net.lacolaco.smileessence.preference.UserPreferenceHelper; -import net.lacolaco.smileessence.viewmodel.IViewModel; +import net.lacolaco.smileessence.activity.MainActivity; -import java.util.ArrayList; -import java.util.List; +public abstract class Command { + private final MainActivity activity; -public abstract class Command implements IViewModel { - - // ------------------------------ FIELDS ------------------------------ - - private final Activity activity; - - // -------------------------- STATIC METHODS -------------------------- - - public Command(Activity activity) { + public Command(MainActivity activity) { this.activity = activity; } - public static List<Command> getUserCommands(Activity activity, User user) { - List<Command> commands = new ArrayList<>(); - commands.add(new UserCommandAddToReply(activity, user)); - commands.add(new UserCommandSendMessage(activity, user)); - commands.add(new UserCommandBlock(activity, user)); - commands.add(new UserCommandUnblock(activity, user)); - commands.add(new UserCommandReportForSpam(activity, user)); - commands.add(new UserCommandOpenAclog(activity, user)); - return commands; - } - - public static List<Command> getStatusCommands(Activity activity, Tweet tweet) { - List<Command> commands = new ArrayList<>(); - commands.add(new StatusCommandAddToReply(activity, tweet)); - commands.add(new StatusCommandOpenTalkView(activity, tweet)); - commands.add(new StatusCommandOpenInBrowser(activity, tweet)); - commands.add(new StatusCommandCopyTextToClipboard(activity, tweet)); - commands.add(new StatusCommandCopyURLToClipboard(activity, tweet)); - return commands; - } - - public static List<Command> getMessageCommands(Activity activity, DirectMessage message) { - List<Command> commands = new ArrayList<>(); - commands.add(new MessageCommandCopyTextToClipboard(activity, message)); - return commands; - } - - // --------------------- GETTER / SETTER METHODS --------------------- - - protected Activity getActivity() { + protected MainActivity getActivity() { return activity; } - // ------------------------ INTERFACE METHODS ------------------------ - - - // --------------------- Interface IViewModel --------------------- - - @Override - public final View getView(Activity activity, LayoutInflater inflater, View convertedView) { - if (convertedView == null) { - convertedView = inflater.inflate(R.layout.menu_item_simple_text, null); - } - TextView textView = (TextView) convertedView.findViewById(R.id.list_item_textview); - textView.setTextSize(UserPreferenceHelper.getInstance().getTextSize()); - textView.setText(getText()); - return convertedView; - } - - // -------------------------- OTHER METHODS -------------------------- - public abstract boolean execute(); public abstract String getText(); diff --git a/app/src/main/java/net/lacolaco/smileessence/command/CommandAddHashtag.java b/app/src/main/java/net/lacolaco/smileessence/command/CommandAddHashtag.java index 5b68ade1..b2de5c21 100644 --- a/app/src/main/java/net/lacolaco/smileessence/command/CommandAddHashtag.java +++ b/app/src/main/java/net/lacolaco/smileessence/command/CommandAddHashtag.java @@ -24,8 +24,7 @@ package net.lacolaco.smileessence.command; -import android.app.Activity; -import net.lacolaco.smileessence.data.PostState; +import net.lacolaco.smileessence.activity.MainActivity; public class CommandAddHashtag extends Command { @@ -35,7 +34,7 @@ public class CommandAddHashtag extends Command { // --------------------------- CONSTRUCTORS --------------------------- - public CommandAddHashtag(Activity activity, String hashtag) { + public CommandAddHashtag(MainActivity activity, String hashtag) { super(activity); this.hashtag = hashtag; } @@ -51,7 +50,7 @@ public class CommandAddHashtag extends Command { @Override public boolean execute() { - PostState.getState().beginTransaction().appendText(" #" + hashtag).commit(); + getActivity().getWorld().getPostState().beginTransaction().appendText(" #" + hashtag).commit(); return true; } } diff --git a/app/src/main/java/net/lacolaco/smileessence/command/CommandOpenSearch.java b/app/src/main/java/net/lacolaco/smileessence/command/CommandOpenSearch.java deleted file mode 100644 index f4a4321a..00000000 --- a/app/src/main/java/net/lacolaco/smileessence/command/CommandOpenSearch.java +++ /dev/null @@ -1,53 +0,0 @@ -/* - * The MIT License (MIT) - * - * Copyright (c) 2012-2014 lacolaco.net - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in all - * copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - * SOFTWARE. - */ - -package net.lacolaco.smileessence.command; - -import android.app.Activity; -import net.lacolaco.smileessence.activity.MainActivity; -import net.lacolaco.smileessence.entity.SavedSearch; - -public class CommandOpenSearch extends Command { - private final SavedSearch query; - - public CommandOpenSearch(Activity activity, SavedSearch query) { - super(activity); - this.query = query; - } - - public SavedSearch getQuery() { - return query; - } - - @Override - public String getText() { - return query.getQuery(); - } - - @Override - public boolean execute() { - ((MainActivity) getActivity()).openSearchPage(query.getQuery()); - return true; - } -} diff --git a/app/src/main/java/net/lacolaco/smileessence/command/CommandOpenURL.java b/app/src/main/java/net/lacolaco/smileessence/command/CommandOpenURL.java index b43676a5..c62e2601 100644 --- a/app/src/main/java/net/lacolaco/smileessence/command/CommandOpenURL.java +++ b/app/src/main/java/net/lacolaco/smileessence/command/CommandOpenURL.java @@ -24,7 +24,7 @@ package net.lacolaco.smileessence.command; -import android.app.Activity; +import net.lacolaco.smileessence.activity.MainActivity; import net.lacolaco.smileessence.util.IntentUtils; public class CommandOpenURL extends Command { @@ -35,7 +35,7 @@ public class CommandOpenURL extends Command { // --------------------------- CONSTRUCTORS --------------------------- - public CommandOpenURL(Activity activity, String url) { + public CommandOpenURL(MainActivity activity, String url) { super(activity); this.url = url; } diff --git a/app/src/main/java/net/lacolaco/smileessence/command/CommandOpenUserDetail.java b/app/src/main/java/net/lacolaco/smileessence/command/CommandOpenUserDetail.java index 39fc5822..600e0bc0 100644 --- a/app/src/main/java/net/lacolaco/smileessence/command/CommandOpenUserDetail.java +++ b/app/src/main/java/net/lacolaco/smileessence/command/CommandOpenUserDetail.java @@ -24,10 +24,8 @@ package net.lacolaco.smileessence.command; -import android.app.Activity; -import net.lacolaco.smileessence.Application; import net.lacolaco.smileessence.R; -import net.lacolaco.smileessence.notification.Notificator; +import net.lacolaco.smileessence.activity.MainActivity; import net.lacolaco.smileessence.twitter.task.Users; import net.lacolaco.smileessence.view.DialogHelper; import net.lacolaco.smileessence.view.dialog.UserDetailDialogFragment; @@ -40,7 +38,7 @@ public class CommandOpenUserDetail extends Command { // --------------------------- CONSTRUCTORS --------------------------- - public CommandOpenUserDetail(Activity activity, String screenName) { + public CommandOpenUserDetail(MainActivity activity, String screenName) { super(activity); this.screenName = screenName; } @@ -56,13 +54,13 @@ public class CommandOpenUserDetail extends Command { @Override public boolean execute() { - new Users.GetTask(Application.getInstance().getCurrentAccount(), screenName) + new Users.GetTask(getActivity().getWorld().getAccount(), screenName) .onDoneUI(user -> { UserDetailDialogFragment fragment = new UserDetailDialogFragment(); fragment.setUserID(user.getId()); DialogHelper.showDialog(getActivity(), fragment); }) - .onFail(x -> Notificator.getInstance().alert(R.string.notice_error_show_user)) + .onFail(x -> getActivity().getWorld().notifyError(R.string.notice_error_show_user)) .execute(); return false; diff --git a/app/src/main/java/net/lacolaco/smileessence/command/CommandOpenUserList.java b/app/src/main/java/net/lacolaco/smileessence/command/CommandOpenUserList.java deleted file mode 100644 index 5b2c47e3..00000000 --- a/app/src/main/java/net/lacolaco/smileessence/command/CommandOpenUserList.java +++ /dev/null @@ -1,58 +0,0 @@ -/* - * The MIT License (MIT) - * - * Copyright (c) 2012-2014 lacolaco.net - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in all - * copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - * SOFTWARE. - */ - -package net.lacolaco.smileessence.command; - -import android.app.Activity; -import net.lacolaco.smileessence.activity.MainActivity; - -public class CommandOpenUserList extends Command { - - // ------------------------------ FIELDS ------------------------------ - - private final String listFullName; - - // --------------------------- CONSTRUCTORS --------------------------- - - public CommandOpenUserList(Activity activity, String listFullName) { - super(activity); - this.listFullName = listFullName; - } - - // --------------------- GETTER / SETTER METHODS --------------------- - - @Override - public String getText() { - return listFullName; - } - - // -------------------------- OTHER METHODS -------------------------- - - @Override - public boolean execute() { - MainActivity activity = (MainActivity) getActivity(); - activity.openUserListPage(listFullName); - return true; - } -} diff --git a/app/src/main/java/net/lacolaco/smileessence/command/IConfirmable.java b/app/src/main/java/net/lacolaco/smileessence/command/IConfirmable.java deleted file mode 100644 index 0c0fddc8..00000000 --- a/app/src/main/java/net/lacolaco/smileessence/command/IConfirmable.java +++ /dev/null @@ -1,32 +0,0 @@ -/* - * The MIT License (MIT) - * - * Copyright (c) 2012-2014 lacolaco.net - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in all - * copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - * SOFTWARE. - */ - -package net.lacolaco.smileessence.command; - -/** - * Marker interface to make command confirmable - */ -public interface IConfirmable { - -} diff --git a/app/src/main/java/net/lacolaco/smileessence/command/message/MessageCommand.java b/app/src/main/java/net/lacolaco/smileessence/command/message/MessageCommand.java deleted file mode 100644 index b33b8428..00000000 --- a/app/src/main/java/net/lacolaco/smileessence/command/message/MessageCommand.java +++ /dev/null @@ -1,49 +0,0 @@ -/* - * The MIT License (MIT) - * - * Copyright (c) 2012-2014 lacolaco.net - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in all - * copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - * SOFTWARE. - */ - -package net.lacolaco.smileessence.command.message; - -import android.app.Activity; -import net.lacolaco.smileessence.command.Command; -import net.lacolaco.smileessence.entity.DirectMessage; - -public abstract class MessageCommand extends Command { - - // ------------------------------ FIELDS ------------------------------ - - private final DirectMessage message; - - // --------------------------- CONSTRUCTORS --------------------------- - - public MessageCommand(Activity activity, DirectMessage message) { - super(activity); - this.message = message; - } - - // --------------------- GETTER / SETTER METHODS --------------------- - - protected DirectMessage getMessage() { - return message; - } -} diff --git a/app/src/main/java/net/lacolaco/smileessence/command/message/MessageCommandCopyTextToClipboard.java b/app/src/main/java/net/lacolaco/smileessence/command/message/MessageCommandCopyTextToClipboard.java deleted file mode 100644 index 1c2d2663..00000000 --- a/app/src/main/java/net/lacolaco/smileessence/command/message/MessageCommandCopyTextToClipboard.java +++ /dev/null @@ -1,56 +0,0 @@ -/* - * The MIT License (MIT) - * - * Copyright (c) 2012-2015 lacolaco.net - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in all - * copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - * SOFTWARE. - */ - -package net.lacolaco.smileessence.command.message; - -import android.app.Activity; -import net.lacolaco.smileessence.R; -import net.lacolaco.smileessence.entity.DirectMessage; -import net.lacolaco.smileessence.notification.Notificator; -import net.lacolaco.smileessence.util.SystemServiceHelper; - -public class MessageCommandCopyTextToClipboard extends MessageCommand { - - // --------------------------- CONSTRUCTORS --------------------------- - - public MessageCommandCopyTextToClipboard(Activity activity, DirectMessage message) { - super(activity, message); - } - - // --------------------- GETTER / SETTER METHODS --------------------- - - @Override - public String getText() { - return getActivity().getString(R.string.command_status_copy_text_to_clipboard); - } - - // -------------------------- OTHER METHODS -------------------------- - - @Override - public boolean execute() { - SystemServiceHelper.copyToClipboard(getActivity(), "message text", getMessage().getText()); - Notificator.getInstance().publish(R.string.notice_copy_clipboard); - return true; - } -} diff --git a/app/src/main/java/net/lacolaco/smileessence/command/status/StatusCommand.java b/app/src/main/java/net/lacolaco/smileessence/command/status/StatusCommand.java deleted file mode 100644 index 1dbad2b2..00000000 --- a/app/src/main/java/net/lacolaco/smileessence/command/status/StatusCommand.java +++ /dev/null @@ -1,53 +0,0 @@ -/* - * The MIT License (MIT) - * - * Copyright (c) 2012-2014 lacolaco.net - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in all - * copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - * SOFTWARE. - */ - -package net.lacolaco.smileessence.command.status; - -import android.app.Activity; -import net.lacolaco.smileessence.command.Command; -import net.lacolaco.smileessence.entity.Tweet; - -public abstract class StatusCommand extends Command { - - // ------------------------------ FIELDS ------------------------------ - - private final Tweet tweet; - - // --------------------------- CONSTRUCTORS --------------------------- - - public StatusCommand(Activity activity, Tweet tweet) { - super(activity); - this.tweet = tweet; - } - - // --------------------- GETTER / SETTER METHODS --------------------- - - protected final Tweet getOriginalStatus() { - return tweet.getOriginalTweet(); - } - - protected final Tweet getStatus() { - return tweet; - } -} diff --git a/app/src/main/java/net/lacolaco/smileessence/command/status/StatusCommandAddToReply.java b/app/src/main/java/net/lacolaco/smileessence/command/status/StatusCommandAddToReply.java deleted file mode 100644 index e843f881..00000000 --- a/app/src/main/java/net/lacolaco/smileessence/command/status/StatusCommandAddToReply.java +++ /dev/null @@ -1,57 +0,0 @@ -/* - * The MIT License (MIT) - * - * Copyright (c) 2012-2014 lacolaco.net - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in all - * copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - * SOFTWARE. - */ - -package net.lacolaco.smileessence.command.status; - -import android.app.Activity; -import net.lacolaco.smileessence.R; -import net.lacolaco.smileessence.data.PostState; -import net.lacolaco.smileessence.entity.Tweet; -import net.lacolaco.smileessence.notification.Notificator; - -public class StatusCommandAddToReply extends StatusCommand { - - // --------------------------- CONSTRUCTORS --------------------------- - - public StatusCommandAddToReply(Activity activity, Tweet tweet) { - super(activity, tweet); - } - - // --------------------- GETTER / SETTER METHODS --------------------- - - @Override - public String getText() { - return getActivity().getString(R.string.command_status_add_to_reply); - } - - // -------------------------- OTHER METHODS -------------------------- - - @Override - public boolean execute() { - String text = String.format("@%s ", getOriginalStatus().getUser().getScreenName()); - PostState.getState().beginTransaction().insertText(0, text).moveCursor(text.length()).commit(); - Notificator.getInstance().publish(R.string.notice_add_to_reply); - return true; - } -} diff --git a/app/src/main/java/net/lacolaco/smileessence/command/status/StatusCommandCopyTextToClipboard.java b/app/src/main/java/net/lacolaco/smileessence/command/status/StatusCommandCopyTextToClipboard.java deleted file mode 100644 index 6263cb44..00000000 --- a/app/src/main/java/net/lacolaco/smileessence/command/status/StatusCommandCopyTextToClipboard.java +++ /dev/null @@ -1,56 +0,0 @@ -/* - * The MIT License (MIT) - * - * Copyright (c) 2012-2015 lacolaco.net - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in all - * copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - * SOFTWARE. - */ - -package net.lacolaco.smileessence.command.status; - -import android.app.Activity; -import net.lacolaco.smileessence.R; -import net.lacolaco.smileessence.entity.Tweet; -import net.lacolaco.smileessence.notification.Notificator; -import net.lacolaco.smileessence.util.SystemServiceHelper; - -public class StatusCommandCopyTextToClipboard extends StatusCommand { - - // --------------------------- CONSTRUCTORS --------------------------- - - public StatusCommandCopyTextToClipboard(Activity activity, Tweet tweet) { - super(activity, tweet); - } - - // --------------------- GETTER / SETTER METHODS --------------------- - - @Override - public String getText() { - return getActivity().getString(R.string.command_status_copy_text_to_clipboard); - } - - // -------------------------- OTHER METHODS -------------------------- - - @Override - public boolean execute() { - SystemServiceHelper.copyToClipboard(getActivity(), "tweet text", getOriginalStatus().getText()); - Notificator.getInstance().publish(R.string.notice_copy_clipboard); - return true; - } -} diff --git a/app/src/main/java/net/lacolaco/smileessence/command/status/StatusCommandCopyURLToClipboard.java b/app/src/main/java/net/lacolaco/smileessence/command/status/StatusCommandCopyURLToClipboard.java deleted file mode 100644 index 2140048b..00000000 --- a/app/src/main/java/net/lacolaco/smileessence/command/status/StatusCommandCopyURLToClipboard.java +++ /dev/null @@ -1,57 +0,0 @@ -/* - * The MIT License (MIT) - * - * Copyright (c) 2012-2015 lacolaco.net - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in all - * copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - * SOFTWARE. - */ - -package net.lacolaco.smileessence.command.status; - -import android.app.Activity; -import net.lacolaco.smileessence.R; -import net.lacolaco.smileessence.entity.Tweet; -import net.lacolaco.smileessence.notification.Notificator; -import net.lacolaco.smileessence.util.SystemServiceHelper; - -public class StatusCommandCopyURLToClipboard extends StatusCommand { - - // --------------------------- CONSTRUCTORS --------------------------- - - public StatusCommandCopyURLToClipboard(Activity activity, Tweet tweet) { - super(activity, tweet); - } - - // --------------------- GETTER / SETTER METHODS --------------------- - - @Override - public String getText() { - return getActivity().getString(R.string.command_status_copy_url_to_clipboard); - } - - // -------------------------- OTHER METHODS -------------------------- - - @Override - public boolean execute() { - String statusURL = getOriginalStatus().getTwitterUrl(); - SystemServiceHelper.copyToClipboard(getActivity(), "tweet url", statusURL); - Notificator.getInstance().publish(R.string.notice_copy_clipboard); - return true; - } -} diff --git a/app/src/main/java/net/lacolaco/smileessence/command/status/StatusCommandOpenInBrowser.java b/app/src/main/java/net/lacolaco/smileessence/command/status/StatusCommandOpenInBrowser.java deleted file mode 100644 index 55f22086..00000000 --- a/app/src/main/java/net/lacolaco/smileessence/command/status/StatusCommandOpenInBrowser.java +++ /dev/null @@ -1,54 +0,0 @@ -/* - * The MIT License (MIT) - * - * Copyright (c) 2012-2014 lacolaco.net - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in all - * copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - * SOFTWARE. - */ - -package net.lacolaco.smileessence.command.status; - -import android.app.Activity; -import net.lacolaco.smileessence.R; -import net.lacolaco.smileessence.entity.Tweet; -import net.lacolaco.smileessence.util.IntentUtils; - -public class StatusCommandOpenInBrowser extends StatusCommand { - - // --------------------------- CONSTRUCTORS --------------------------- - - public StatusCommandOpenInBrowser(Activity activity, Tweet tweet) { - super(activity, tweet); - } - - // --------------------- GETTER / SETTER METHODS --------------------- - - @Override - public String getText() { - return getActivity().getString(R.string.command_status_open_in_browser); - } - - // -------------------------- OTHER METHODS -------------------------- - - @Override - public boolean execute() { - IntentUtils.openUri(getActivity(), getOriginalStatus().getTwitterUrl()); - return true; - } -} diff --git a/app/src/main/java/net/lacolaco/smileessence/command/status/StatusCommandOpenTalkView.java b/app/src/main/java/net/lacolaco/smileessence/command/status/StatusCommandOpenTalkView.java deleted file mode 100644 index e56af074..00000000 --- a/app/src/main/java/net/lacolaco/smileessence/command/status/StatusCommandOpenTalkView.java +++ /dev/null @@ -1,57 +0,0 @@ -/* - * The MIT License (MIT) - * - * Copyright (c) 2012-2014 lacolaco.net - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in all - * copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - * SOFTWARE. - */ - -package net.lacolaco.smileessence.command.status; - -import android.app.Activity; -import net.lacolaco.smileessence.R; -import net.lacolaco.smileessence.entity.Tweet; -import net.lacolaco.smileessence.view.DialogHelper; -import net.lacolaco.smileessence.view.dialog.TalkChainDialogFragment; - -public class StatusCommandOpenTalkView extends StatusCommand { - - // --------------------------- CONSTRUCTORS --------------------------- - - public StatusCommandOpenTalkView(Activity activity, Tweet tweet) { - super(activity, tweet); - } - - // --------------------- GETTER / SETTER METHODS --------------------- - - @Override - public String getText() { - return getActivity().getString(R.string.command_status_open_talk_view); - } - - // -------------------------- OTHER METHODS -------------------------- - - @Override - public boolean execute() { - TalkChainDialogFragment dialogFragment = new TalkChainDialogFragment(); - dialogFragment.setStatusID(getOriginalStatus().getId()); - DialogHelper.showDialog(getActivity(), dialogFragment); - return false; - } -} diff --git a/app/src/main/java/net/lacolaco/smileessence/command/user/UserCommand.java b/app/src/main/java/net/lacolaco/smileessence/command/user/UserCommand.java deleted file mode 100644 index 3a486304..00000000 --- a/app/src/main/java/net/lacolaco/smileessence/command/user/UserCommand.java +++ /dev/null @@ -1,49 +0,0 @@ -/* - * The MIT License (MIT) - * - * Copyright (c) 2012-2014 lacolaco.net - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in all - * copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - * SOFTWARE. - */ - -package net.lacolaco.smileessence.command.user; - -import android.app.Activity; -import net.lacolaco.smileessence.command.Command; -import net.lacolaco.smileessence.entity.User; - -public abstract class UserCommand extends Command { - - // ------------------------------ FIELDS ------------------------------ - - private final User user; - - // --------------------------- CONSTRUCTORS --------------------------- - - public UserCommand(Activity activity, User user) { - super(activity); - this.user = user; - } - - // --------------------- GETTER / SETTER METHODS --------------------- - - protected User getUser() { - return user; - } -} diff --git a/app/src/main/java/net/lacolaco/smileessence/command/user/UserCommandAddToReply.java b/app/src/main/java/net/lacolaco/smileessence/command/user/UserCommandAddToReply.java deleted file mode 100644 index a224a635..00000000 --- a/app/src/main/java/net/lacolaco/smileessence/command/user/UserCommandAddToReply.java +++ /dev/null @@ -1,57 +0,0 @@ -/* - * The MIT License (MIT) - * - * Copyright (c) 2012-2014 lacolaco.net - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in all - * copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - * SOFTWARE. - */ - -package net.lacolaco.smileessence.command.user; - -import android.app.Activity; -import net.lacolaco.smileessence.R; -import net.lacolaco.smileessence.data.PostState; -import net.lacolaco.smileessence.entity.User; -import net.lacolaco.smileessence.notification.Notificator; - -public class UserCommandAddToReply extends UserCommand { - - // --------------------------- CONSTRUCTORS --------------------------- - - public UserCommandAddToReply(Activity activity, User user) { - super(activity, user); - } - - // --------------------- GETTER / SETTER METHODS --------------------- - - @Override - public String getText() { - return getActivity().getString(R.string.command_user_add_to_reply); - } - - // -------------------------- OTHER METHODS -------------------------- - - @Override - public boolean execute() { - String text = String.format("@%s ", getUser().getScreenName()); - PostState.getState().beginTransaction().insertText(0, text).moveCursor(text.length()).commit(); - Notificator.getInstance().publish(R.string.notice_add_to_reply); - return true; - } -} diff --git a/app/src/main/java/net/lacolaco/smileessence/command/user/UserCommandBlock.java b/app/src/main/java/net/lacolaco/smileessence/command/user/UserCommandBlock.java deleted file mode 100644 index c4461c33..00000000 --- a/app/src/main/java/net/lacolaco/smileessence/command/user/UserCommandBlock.java +++ /dev/null @@ -1,60 +0,0 @@ -/* - * The MIT License (MIT) - * - * Copyright (c) 2012-2014 lacolaco.net - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in all - * copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - * SOFTWARE. - */ - -package net.lacolaco.smileessence.command.user; - -import android.app.Activity; -import net.lacolaco.smileessence.Application; -import net.lacolaco.smileessence.R; -import net.lacolaco.smileessence.command.IConfirmable; -import net.lacolaco.smileessence.entity.User; -import net.lacolaco.smileessence.notification.Notificator; -import net.lacolaco.smileessence.twitter.task.Users; - -public class UserCommandBlock extends UserCommand implements IConfirmable { - - // --------------------------- CONSTRUCTORS --------------------------- - - public UserCommandBlock(Activity activity, User user) { - super(activity, user); - } - - // --------------------- GETTER / SETTER METHODS --------------------- - - @Override - public String getText() { - return getActivity().getString(R.string.command_user_block); - } - - // -------------------------- OTHER METHODS -------------------------- - - @Override - public boolean execute() { - new Users.BlockTask(Application.getInstance().getCurrentAccount(), getUser().getId()) - .onDone(user -> Notificator.getInstance().publish(R.string.notice_block_succeeded)) - .onFail(ex -> Notificator.getInstance().alert(R.string.notice_block_failed)) - .execute(); - return true; - } -} diff --git a/app/src/main/java/net/lacolaco/smileessence/command/user/UserCommandOpenAclog.java b/app/src/main/java/net/lacolaco/smileessence/command/user/UserCommandOpenAclog.java deleted file mode 100644 index 6d037c8b..00000000 --- a/app/src/main/java/net/lacolaco/smileessence/command/user/UserCommandOpenAclog.java +++ /dev/null @@ -1,54 +0,0 @@ -/* - * The MIT License (MIT) - * - * Copyright (c) 2012-2014 lacolaco.net - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in all - * copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - * SOFTWARE. - */ - -package net.lacolaco.smileessence.command.user; - -import android.app.Activity; -import net.lacolaco.smileessence.R; -import net.lacolaco.smileessence.entity.User; -import net.lacolaco.smileessence.util.IntentUtils; - -public class UserCommandOpenAclog extends UserCommand { - - // --------------------------- CONSTRUCTORS --------------------------- - - public UserCommandOpenAclog(Activity activity, User user) { - super(activity, user); - } - - // --------------------- GETTER / SETTER METHODS --------------------- - - @Override - public String getText() { - return getActivity().getString(R.string.command_user_open_aclog); - } - - // -------------------------- OTHER METHODS -------------------------- - - @Override - public boolean execute() { - IntentUtils.openUri(getActivity(), getUser().getAclogTimelineURL()); - return true; - } -} diff --git a/app/src/main/java/net/lacolaco/smileessence/command/user/UserCommandReportForSpam.java b/app/src/main/java/net/lacolaco/smileessence/command/user/UserCommandReportForSpam.java deleted file mode 100644 index a05c5e82..00000000 --- a/app/src/main/java/net/lacolaco/smileessence/command/user/UserCommandReportForSpam.java +++ /dev/null @@ -1,60 +0,0 @@ -/* - * The MIT License (MIT) - * - * Copyright (c) 2012-2014 lacolaco.net - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in all - * copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - * SOFTWARE. - */ - -package net.lacolaco.smileessence.command.user; - -import android.app.Activity; -import net.lacolaco.smileessence.Application; -import net.lacolaco.smileessence.R; -import net.lacolaco.smileessence.command.IConfirmable; -import net.lacolaco.smileessence.entity.User; -import net.lacolaco.smileessence.notification.Notificator; -import net.lacolaco.smileessence.twitter.task.Users; - -public class UserCommandReportForSpam extends UserCommand implements IConfirmable { - - // --------------------------- CONSTRUCTORS --------------------------- - - public UserCommandReportForSpam(Activity activity, User user) { - super(activity, user); - } - - // --------------------- GETTER / SETTER METHODS --------------------- - - @Override - public String getText() { - return getActivity().getString(R.string.command_user_r4s); - } - - // -------------------------- OTHER METHODS -------------------------- - - @Override - public boolean execute() { - new Users.ReportForSpamTask(Application.getInstance().getCurrentAccount(), getUser().getId()) - .onDone(user -> Notificator.getInstance().publish(R.string.notice_r4s_succeeded)) - .onFail(ex -> Notificator.getInstance().alert(R.string.notice_r4s_failed)) - .execute(); - return true; - } -} diff --git a/app/src/main/java/net/lacolaco/smileessence/command/user/UserCommandSendMessage.java b/app/src/main/java/net/lacolaco/smileessence/command/user/UserCommandSendMessage.java deleted file mode 100644 index a09a3f91..00000000 --- a/app/src/main/java/net/lacolaco/smileessence/command/user/UserCommandSendMessage.java +++ /dev/null @@ -1,57 +0,0 @@ -/* - * The MIT License (MIT) - * - * Copyright (c) 2012-2014 lacolaco.net - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in all - * copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - * SOFTWARE. - */ - -package net.lacolaco.smileessence.command.user; - -import android.app.Activity; -import net.lacolaco.smileessence.R; -import net.lacolaco.smileessence.entity.User; -import net.lacolaco.smileessence.view.DialogHelper; -import net.lacolaco.smileessence.view.dialog.SendMessageDialogFragment; - -public class UserCommandSendMessage extends UserCommand { - - // --------------------------- CONSTRUCTORS --------------------------- - - public UserCommandSendMessage(Activity activity, User user) { - super(activity, user); - } - - // --------------------- GETTER / SETTER METHODS --------------------- - - @Override - public String getText() { - return getActivity().getString(R.string.command_user_send_message); - } - - // -------------------------- OTHER METHODS -------------------------- - - @Override - public boolean execute() { - SendMessageDialogFragment dialogFragment = new SendMessageDialogFragment(); - dialogFragment.setScreenName(getUser().getScreenName()); - DialogHelper.showDialog(getActivity(), dialogFragment); - return true; - } -} diff --git a/app/src/main/java/net/lacolaco/smileessence/command/user/UserCommandUnblock.java b/app/src/main/java/net/lacolaco/smileessence/command/user/UserCommandUnblock.java deleted file mode 100644 index a4d9f893..00000000 --- a/app/src/main/java/net/lacolaco/smileessence/command/user/UserCommandUnblock.java +++ /dev/null @@ -1,60 +0,0 @@ -/* - * The MIT License (MIT) - * - * Copyright (c) 2012-2014 lacolaco.net - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in all - * copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - * SOFTWARE. - */ - -package net.lacolaco.smileessence.command.user; - -import android.app.Activity; -import net.lacolaco.smileessence.Application; -import net.lacolaco.smileessence.R; -import net.lacolaco.smileessence.command.IConfirmable; -import net.lacolaco.smileessence.entity.User; -import net.lacolaco.smileessence.notification.Notificator; -import net.lacolaco.smileessence.twitter.task.Users; - -public class UserCommandUnblock extends UserCommand implements IConfirmable { - - // --------------------------- CONSTRUCTORS --------------------------- - - public UserCommandUnblock(Activity activity, User user) { - super(activity, user); - } - - // --------------------- GETTER / SETTER METHODS --------------------- - - @Override - public String getText() { - return getActivity().getString(R.string.command_user_unblock); - } - - // -------------------------- OTHER METHODS -------------------------- - - @Override - public boolean execute() { - new Users.UnblockTask(Application.getInstance().getCurrentAccount(), getUser().getId()) - .onDone(user -> Notificator.getInstance().publish(R.string.notice_unblock_succeeded)) - .onFail(x -> Notificator.getInstance().alert(R.string.notice_unblock_failed)) - .execute(); - return true; - } -} diff --git a/app/src/main/java/net/lacolaco/smileessence/data/Account.java b/app/src/main/java/net/lacolaco/smileessence/data/Account.java index e540de44..280f9a09 100644 --- a/app/src/main/java/net/lacolaco/smileessence/data/Account.java +++ b/app/src/main/java/net/lacolaco/smileessence/data/Account.java @@ -27,14 +27,7 @@ package net.lacolaco.smileessence.data; import com.github.gfx.android.orma.annotation.Column; import com.github.gfx.android.orma.annotation.PrimaryKey; import com.github.gfx.android.orma.annotation.Table; -import net.lacolaco.smileessence.entity.DirectMessage; -import net.lacolaco.smileessence.entity.SavedSearch; -import net.lacolaco.smileessence.entity.Tweet; import net.lacolaco.smileessence.entity.User; -import net.lacolaco.smileessence.twitter.task.Accounts; -import net.lacolaco.smileessence.twitter.task.Searches; -import net.lacolaco.smileessence.twitter.task.Users; -import net.lacolaco.smileessence.util.BackgroundTask; import twitter4j.Twitter; import twitter4j.TwitterFactory; import twitter4j.TwitterStream; @@ -43,15 +36,10 @@ import twitter4j.auth.AccessToken; import twitter4j.conf.ConfigurationBuilder; import java.util.*; -import java.util.concurrent.ConcurrentHashMap; @Table public class Account { - private static Map<Long, Account> cache; // model id -> Account - private User user; - private final Set<String> listSubscriptions = Collections.newSetFromMap(new ConcurrentHashMap<>()); - private final Set<Long> muteUserIds = Collections.newSetFromMap(new ConcurrentHashMap<>()); - + private static Map<Long, Account> cache; @PrimaryKey public long userId; @Column @@ -60,20 +48,22 @@ public class Account { public String oauthToken; @Column public String oauthTokenSecret; + @Column(defaultExpr = "0") + public int themeIndex; + + private User user; public Account() { } - // --------------------- static methods --------------------- public static synchronized Account get(long i) { if (cache == null) { - throw new IllegalStateException("Load first"); + throw new IllegalStateException("[BUG] Load first"); } - return cache.get(i); - } - - public static synchronized int count() { - return cache.size(); + Account a = cache.get(i); + if (a == null) + throw new IllegalStateException("[BUG] Account with userId == " + i + " not found"); + return a; } public static synchronized List<Account> all() { @@ -105,6 +95,7 @@ public class Account { account.screenName = screenName; account.oauthToken = token; account.oauthTokenSecret = tokenSecret; + account.themeIndex = 0; relation().upserter().execute(account); @@ -155,53 +146,4 @@ public class Account { return user; } - // --------------------- Helper methods --------------------- - - public boolean canDelete(Tweet tweet) { - return tweet.getOriginalTweet().getUser() == getUser(); - } - - public boolean canDelete(DirectMessage message) { - return message.getSender() == getUser() || - message.getRecipient() == getUser(); - } - - // --------------------- List subscription cache --------------------- - public BackgroundTask<List<String>, Void> refreshListSubscriptions() { - return new Users.GetManyTask(this) - .onDone(lists -> { - listSubscriptions.clear(); - listSubscriptions.addAll(lists); - }) - // .onFail(x -> { }) // TODO: error message? - .execute(); - } - - public Set<String> getListSubscriptions() { - return listSubscriptions; - } - - public boolean addListSubscription(String fullName) { - return listSubscriptions.add(fullName); - } - - public boolean removeListSubscription(String fullName) { - return listSubscriptions.remove(fullName); - } - - // --------------------- User mute cache --------------------- - public List<BackgroundTask> refreshUserMuteList() { - List<BackgroundTask> tasks = new ArrayList<>(); - tasks.add(new Accounts.BlockIDsTask(this).onDone(muteUserIds::addAll).execute()); - tasks.add(new Accounts.MutesIDsTask(this).onDone(muteUserIds::addAll).execute()); - return tasks; - } - - public boolean isMutedUserListContains(long id) { - return muteUserIds.contains(id); - } - - public BackgroundTask<List<SavedSearch>, Void> refreshSavedSearches() { - return new Searches.GetAllSavedSearchesTask(this).onDone(SavedSearch::replace).execute(); - } }
\ No newline at end of file diff --git a/app/src/main/java/net/lacolaco/smileessence/data/ExtractionWord.java b/app/src/main/java/net/lacolaco/smileessence/data/ExtractionWord.java index 88e4539c..a0206db2 100644 --- a/app/src/main/java/net/lacolaco/smileessence/data/ExtractionWord.java +++ b/app/src/main/java/net/lacolaco/smileessence/data/ExtractionWord.java @@ -36,24 +36,24 @@ import java.util.regex.Pattern; @Table public class ExtractionWord { private static Set<ExtractionWord> cache; - private static final Object mutex = new Object(); - private Pattern pattern; - @PrimaryKey String patternString; + private Pattern pattern; - // --------------------- static methods --------------------- - public static List<ExtractionWord> cached() { - synchronized (mutex) { - return new ArrayList<>(cache); - } + public ExtractionWord() { + } + + private ExtractionWord(String patternString) { + this.patternString = patternString; + } + + public static synchronized List<ExtractionWord> cached() { + return new ArrayList<>(cache); } public static synchronized void load() { - synchronized (mutex) { - OrmaDatabase orma = OrmaHolder.getORMA(); - cache = new HashSet<>(orma.selectFromExtractionWord().toList()); - } + OrmaDatabase orma = OrmaHolder.getORMA(); + cache = new HashSet<>(orma.selectFromExtractionWord().toList()); } private static ExtractionWord_Relation relation() { @@ -63,19 +63,10 @@ public class ExtractionWord { public static synchronized ExtractionWord add(String patternString) { ExtractionWord extractionWord = new ExtractionWord(patternString); relation().upserter().execute(extractionWord); - synchronized (mutex) { - cache.add(extractionWord); - } + cache.add(extractionWord); return extractionWord; } - public ExtractionWord() { - } - - private ExtractionWord(String patternString) { - this.patternString = patternString; - } - public Pattern getPattern() { if (pattern == null) pattern = Pattern.compile(patternString); @@ -90,4 +81,4 @@ public class ExtractionWord { relation().deleter().patternStringEq(patternString).execute(); cache.remove(this); } -} +}
\ No newline at end of file diff --git a/app/src/main/java/net/lacolaco/smileessence/data/ImageCache.java b/app/src/main/java/net/lacolaco/smileessence/data/ImageCache.java index 124ae6d1..e7a31716 100644 --- a/app/src/main/java/net/lacolaco/smileessence/data/ImageCache.java +++ b/app/src/main/java/net/lacolaco/smileessence/data/ImageCache.java @@ -36,7 +36,6 @@ public class ImageCache { // ------------------------------ FIELDS ------------------------------ private static ImageCache instance = new ImageCache(); - private RequestQueue requestQueue; private ImageLoader imageLoader; // -------------------------- STATIC METHODS -------------------------- @@ -44,7 +43,7 @@ public class ImageCache { private ImageCache() { int cacheSizeInBytes = 64 * 1024 * 1024; // 64MB Cache diskCache = new DiskBasedCache(Application.getInstance().getCacheDir(), cacheSizeInBytes); - requestQueue = new RequestQueue(diskCache, new BasicNetwork(new HurlStack())); + RequestQueue requestQueue = new RequestQueue(diskCache, new BasicNetwork(new HurlStack())); imageLoader = new ImageLoader(requestQueue, new ImageLruCache()); requestQueue.start(); } diff --git a/app/src/main/java/net/lacolaco/smileessence/data/PostState.java b/app/src/main/java/net/lacolaco/smileessence/data/PostState.java index 6f517763..4bbd83a4 100644 --- a/app/src/main/java/net/lacolaco/smileessence/data/PostState.java +++ b/app/src/main/java/net/lacolaco/smileessence/data/PostState.java @@ -30,34 +30,12 @@ import net.lacolaco.smileessence.view.DialogHelper; import twitter4j.StatusUpdate; public class PostState { - - // ------------------------------ FIELDS ------------------------------ - - private static PostState instance = new PostState(); private String text = ""; - private Tweet inReplyTo = null; + private Tweet inReplyTo; private String mediaFilePath = ""; private boolean directMessage = false; private OnPostStateChangeListener listener; - private int selectionStart = 0; - private int selectionEnd = 0; - - // -------------------------- STATIC METHODS -------------------------- - - private PostState() { - } - - public static PostState getState() { - return instance; - } - - // --------------------------- CONSTRUCTORS --------------------------- - - public static PostState newState() { - return instance = new PostState().setListener(instance.listener); - } - - // --------------------- GETTER / SETTER METHODS --------------------- + private int selectionStart, selectionEnd; public Tweet getInReplyTo() { return inReplyTo; @@ -90,8 +68,6 @@ public class PostState { return this; } - // -------------------------- OTHER METHODS -------------------------- - public PostStateTransaction beginTransaction() { return new PostStateTransaction(this); } @@ -138,10 +114,10 @@ public class PostState { } public static class PostStateTransaction { - - private PostState state; + private PostState origState, state; private PostStateTransaction(PostState state) { + this.origState = state; this.state = new PostState().copy(state); } @@ -183,13 +159,20 @@ public class PostState { return this; } + public PostStateTransaction clear() { + state.text = ""; + state.selectionStart = state.selectionEnd = 0; + state.inReplyTo = null; + return this; + } + public void commit() { - PostState.getState().copy(state).postStateChange(); + origState.copy(state).postStateChange(); } public void commitWithOpen(MainActivity activity) { DialogHelper.closeAll(activity); - PostState.getState().copy(state).postStateChange(); + origState.copy(state).postStateChange(); activity.openPostPage(); } diff --git a/app/src/main/java/net/lacolaco/smileessence/entity/DirectMessage.java b/app/src/main/java/net/lacolaco/smileessence/entity/DirectMessage.java index 67524c36..5b19ee74 100644 --- a/app/src/main/java/net/lacolaco/smileessence/entity/DirectMessage.java +++ b/app/src/main/java/net/lacolaco/smileessence/entity/DirectMessage.java @@ -1,27 +1,26 @@ package net.lacolaco.smileessence.entity; -import com.google.common.cache.Cache; -import com.google.common.cache.CacheBuilder; import net.lacolaco.smileessence.util.ListUtils; -import java.util.ArrayList; import java.util.Date; import java.util.List; +import java.util.Map; +import java.util.concurrent.ConcurrentHashMap; -public class DirectMessage extends EntitySupport { - private static Cache<Long, DirectMessage> storage = CacheBuilder.newBuilder().weakValues().build(); - - public synchronized static DirectMessage fetch(long statusId) { - return storage.getIfPresent(statusId); - } +public class DirectMessage extends EntitySupport implements IdObject { + private static Map<Long, DirectMessage> storage = new ConcurrentHashMap<>(); + private long id; + private User sender; + private User recipient; + private String text; + private Date createdAt; - @Deprecated - public synchronized static List<DirectMessage> cached() { - return new ArrayList<>(storage.asMap().values()); + private DirectMessage(twitter4j.DirectMessage st) { + update(st); } - public synchronized static void remove(long statusId) { - storage.invalidate(statusId); + public synchronized static DirectMessage fetch(long statusId) { + return storage.get(statusId); } public synchronized static DirectMessage fromTwitter(twitter4j.DirectMessage st) { @@ -39,17 +38,6 @@ public class DirectMessage extends EntitySupport { return ListUtils.map(sts, DirectMessage::fromTwitter); } - // インスタンス - private long id; - private User sender; - private User recipient; - private String text; - private Date createdAt; - - private DirectMessage(twitter4j.DirectMessage st) { - update(st); - } - private void update(twitter4j.DirectMessage message) { id = message.getId(); sender = User.fromTwitter(message.getSender()); @@ -60,6 +48,7 @@ public class DirectMessage extends EntitySupport { updateEntities(message); } + @Override public long getId() { return id; } diff --git a/app/src/main/java/net/lacolaco/smileessence/entity/Event.java b/app/src/main/java/net/lacolaco/smileessence/entity/Event.java new file mode 100644 index 00000000..e2002cb9 --- /dev/null +++ b/app/src/main/java/net/lacolaco/smileessence/entity/Event.java @@ -0,0 +1,62 @@ +package net.lacolaco.smileessence.entity; + +import java.util.Date; + +public class Event { + private final Date createdAt; + private final EnumEvent event; + private final User source; + private final Tweet targetObject; + + public Event(EnumEvent e, User s) { + this(e, s, null); + } + + public Event(EnumEvent e, User s, Tweet t) { + event = e; + createdAt = new Date(); + source = s; + targetObject = t; + } + + public Date getCreatedAt() { + return createdAt; + } + + public EnumEvent getEvent() { + return event; + } + + public User getSource() { + return source; + } + + public Tweet getTargetObject() { + return targetObject; + } + + public String getFormattedString() { + return String.format(event.getFormat(), source.getScreenName()); + } + + public enum EnumEvent { + FAVORITED("Favorited by %s"), + UNFAVORITED("Unfavorited by %s"), + RETWEETED("Retweeted by %s"), + MENTIONED("Replied by %s"), + FOLLOWED("Followed by %s"), + BLOCKED("Blocked by %s"), + UNBLOCKED("Unblocked by %s"), + RECEIVE_MESSAGE("Received a direct message from %s"); + + private final String format; + + EnumEvent(String f) { + format = f; + } + + public String getFormat() { + return format; + } + } +} diff --git a/app/src/main/java/net/lacolaco/smileessence/entity/SavedSearch.java b/app/src/main/java/net/lacolaco/smileessence/entity/SavedSearch.java index 6ea6dea4..fcb87605 100644 --- a/app/src/main/java/net/lacolaco/smileessence/entity/SavedSearch.java +++ b/app/src/main/java/net/lacolaco/smileessence/entity/SavedSearch.java @@ -6,29 +6,6 @@ import java.util.List; import java.util.Map; public class SavedSearch implements IdObject { - private static Map<Long, SavedSearch> storage = new HashMap<>(); - - public synchronized static Collection<SavedSearch> cached() { - return storage.values(); - } - - public synchronized static void replace(List<SavedSearch> list) { - storage = new HashMap<>(); - for (SavedSearch ss : list) - storage.put(ss.getId(), ss); - } - - public synchronized static SavedSearch fromTwitter(twitter4j.SavedSearch obj) { - SavedSearch cached = storage.get(obj.getId()); - - /* SavedSearch should be immutable */ - if (cached == null) { - cached = new SavedSearch(obj.getId(), obj.getQuery()); - } - return cached; - } - - // インスタンス private long id; private String query; @@ -37,6 +14,10 @@ public class SavedSearch implements IdObject { this.query = query; } + public synchronized static SavedSearch fromTwitter(twitter4j.SavedSearch obj) { + return new SavedSearch(obj.getId(), obj.getQuery()); + } + public long getId() { return id; } diff --git a/app/src/main/java/net/lacolaco/smileessence/entity/Tweet.java b/app/src/main/java/net/lacolaco/smileessence/entity/Tweet.java index 2e70d705..4aa461fa 100644 --- a/app/src/main/java/net/lacolaco/smileessence/entity/Tweet.java +++ b/app/src/main/java/net/lacolaco/smileessence/entity/Tweet.java @@ -1,8 +1,6 @@ package net.lacolaco.smileessence.entity; import android.net.Uri; -import com.google.common.cache.Cache; -import com.google.common.cache.CacheBuilder; import net.lacolaco.smileessence.data.Account; import net.lacolaco.smileessence.twitter.task.Tweets; import net.lacolaco.smileessence.util.BackgroundTask; @@ -12,11 +10,27 @@ import twitter4j.Status; import java.util.*; import java.util.concurrent.ConcurrentHashMap; -public class Tweet extends EntitySupport { - private static Cache<Long, Tweet> storage = CacheBuilder.newBuilder().softValues().build(); +public class Tweet extends EntitySupport implements IdObject { + private static Map<Long, Tweet> storage = new ConcurrentHashMap<>(); + private final long id; + private User user; + private String text; + private Date createdAt; + private String source; + private boolean isRetweet; + private Tweet retweetedTweet; + private long inReplyToStatusId; + private int favoriteCount; + private int retweetCount; + private Set<Long> favoriters; + private Map<Long, Long> retweets; + + private Tweet(long id) { + this.id = id; + } public synchronized static Tweet fetch(long statusId) { - return storage.getIfPresent(statusId); + return storage.get(statusId); } public synchronized static BackgroundTask<Tweet, Void> fetchTask(long statusId, Account account) { @@ -33,14 +47,10 @@ public class Tweet extends EntitySupport { } } - public synchronized static void remove(long statusId) { - storage.invalidate(statusId); - } - public synchronized static Tweet fromTwitter(final twitter4j.Status st, long myUserId) { Tweet t = fetch(st.getId()); if (t == null) { - t = new Tweet(); + t = new Tweet(st.getId()); storage.put(st.getId(), t); } @@ -52,23 +62,6 @@ public class Tweet extends EntitySupport { return ListUtils.map(sts, st -> fromTwitter(st, myUserId)); } - // インスタンス - private long id; - private User user; - private String text; - private Date createdAt; - private String source; - private boolean isRetweet; - private Tweet retweetedTweet; - private long inReplyToStatusId; - private int favoriteCount; - private int retweetCount; - private Set<Long> favoriters; - private Map<Long, Long> retweets; - - private Tweet() { - } - @Override protected void finalize() throws Throwable { try { @@ -82,7 +75,8 @@ public class Tweet extends EntitySupport { } private void update(twitter4j.Status status, long myUserId) { - id = status.getId(); + if (id != status.getId()) + throw new IllegalStateException("Invalid update"); user = User.fromTwitter(status.getUser()); createdAt = status.getCreatedAt(); source = status.getSource(); @@ -126,6 +120,7 @@ public class Tweet extends EntitySupport { return String.format("https://twitter.com/%s/status/%s", getUser().getScreenName(), id); } + @Override public long getId() { return id; } diff --git a/app/src/main/java/net/lacolaco/smileessence/entity/User.java b/app/src/main/java/net/lacolaco/smileessence/entity/User.java index e1e3013f..a460fff2 100644 --- a/app/src/main/java/net/lacolaco/smileessence/entity/User.java +++ b/app/src/main/java/net/lacolaco/smileessence/entity/User.java @@ -1,14 +1,32 @@ package net.lacolaco.smileessence.entity; -import com.google.common.cache.Cache; -import com.google.common.cache.CacheBuilder; import net.lacolaco.smileessence.util.UIObservable; +import java.util.Map; +import java.util.concurrent.ConcurrentHashMap; + public class User extends UIObservable { - private static Cache<Long, User> storage = CacheBuilder.newBuilder().weakValues().build(); + private static Map<Long, User> storage = new ConcurrentHashMap<>(); + private long id; + private boolean isProtected; + private String screenName; + private String name; + private String profileImageUrl; + private String profileBannerUrl; + private String description; + private String location; + private String url; + private int favoritesCount; + private int statusesCount; + private int friendsCount; + private int followersCount; + private boolean isVerified; + + private User() { + } public synchronized static User fetch(long userId) { - return storage.getIfPresent(userId); + return storage.get(userId); } public synchronized static User fromTwitter(final twitter4j.User st) { @@ -36,25 +54,6 @@ public class User extends UIObservable { } } - // インスタンス - private long id; - private boolean isProtected; - private String screenName; - private String name; - private String profileImageUrl; - private String profileBannerUrl; - private String description; - private String location; - private String url; - private int favoritesCount; - private int statusesCount; - private int friendsCount; - private int followersCount; - private boolean isVerified; - - private User() { - } - private void update(twitter4j.User user) { id = user.getId(); @@ -120,13 +119,9 @@ public class User extends UIObservable { } public String getProfileImageUrlOriginal() { - return getProfileImageUrlWithSuffix(""); - } - - private String getProfileImageUrlWithSuffix(String suffix) { String original = profileImageUrl; if (original != null) { - String url = original.substring(0, original.lastIndexOf("_")) + suffix; + String url = original.substring(0, original.lastIndexOf("_")); int extIndex = original.lastIndexOf("."); if (extIndex > original.lastIndexOf("/")) { url += original.substring(extIndex); diff --git a/app/src/main/java/net/lacolaco/smileessence/notification/NotificationType.java b/app/src/main/java/net/lacolaco/smileessence/notification/NotificationType.java deleted file mode 100644 index 0c2e5002..00000000 --- a/app/src/main/java/net/lacolaco/smileessence/notification/NotificationType.java +++ /dev/null @@ -1,30 +0,0 @@ -/* - * The MIT License (MIT) - * - * Copyright (c) 2012-2014 lacolaco.net - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in all - * copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - * SOFTWARE. - */ - -package net.lacolaco.smileessence.notification; - -public enum NotificationType { - INFO, - ALERT -} diff --git a/app/src/main/java/net/lacolaco/smileessence/notification/Notificator.java b/app/src/main/java/net/lacolaco/smileessence/notification/Notificator.java deleted file mode 100644 index b1426d59..00000000 --- a/app/src/main/java/net/lacolaco/smileessence/notification/Notificator.java +++ /dev/null @@ -1,120 +0,0 @@ -/* - * The MIT License (MIT) - * - * Copyright (c) 2012-2014 lacolaco.net - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in all - * copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - * SOFTWARE. - */ - -package net.lacolaco.smileessence.notification; - -import android.app.Activity; -import android.support.annotation.StringRes; -import android.widget.Toast; -import de.keyboardsurfer.android.widget.crouton.Configuration; -import de.keyboardsurfer.android.widget.crouton.Crouton; -import de.keyboardsurfer.android.widget.crouton.Style; -import net.lacolaco.smileessence.Application; -import net.lacolaco.smileessence.logging.Logger; -import net.lacolaco.smileessence.util.UIHandler; - -import java.lang.ref.WeakReference; - -public class Notificator { - private static final Notificator instance = new Notificator(); - private static final int DURATION = 1000; - private WeakReference<Activity> weakActivity; - private boolean isForeground; - - public static Notificator getInstance() { - return instance; - } - - private Notificator() { - } - - public void setDefault(Activity activity) { - weakActivity = new WeakReference<>(activity); - } - - public void publish(String text) { - publish(NotificationType.INFO, text); - } - - public void publish(@StringRes int resId, Object... formatArgs) { - publish(NotificationType.INFO, resId, formatArgs); - } - - public void alert(String text) { - publish(NotificationType.ALERT, text); - } - - public void alert(@StringRes int resId, Object... formatArgs) { - publish(NotificationType.ALERT, resId, formatArgs); - } - - private void publish(NotificationType type, @StringRes int resId, Object... formatArgs) { - String text = Application.getInstance().getApplicationContext().getString(resId, formatArgs); - publish(type, text); - } - - private void publish(NotificationType type, String text) { - Activity activity = weakActivity.get(); - if (activity == null || activity.isFinishing()) { - Logger.debug(String.format("notify(log): %s", text)); - } else { - new UIHandler().post(() -> { - if (isForeground) { - Logger.debug(String.format("notify(crouton): %s", text)); - Crouton.makeText(activity, text, getStyle(type)).show(); - } else { - Logger.debug(String.format("notify(toast): %s", text)); - Toast.makeText(activity, text, Toast.LENGTH_LONG).show(); - } - }); - } - } - - public void onForeground() { - isForeground = true; - } - - public void onBackground() { - isForeground = false; - Crouton.cancelAllCroutons(); - } - - private Style getStyle(NotificationType type) { - Configuration.Builder conf = new Configuration.Builder(); - conf.setDuration(DURATION); - Style.Builder style = new Style.Builder(); - style.setConfiguration(conf.build()); - switch (type) { - case INFO: { - style.setBackgroundColorValue(Style.holoBlueLight); - break; - } - case ALERT: { - style.setBackgroundColorValue(Style.holoRedLight); - break; - } - } - return style.build(); - } -} diff --git a/app/src/main/java/net/lacolaco/smileessence/preference/InternalPreferenceHelper.java b/app/src/main/java/net/lacolaco/smileessence/preference/InternalPreferenceHelper.java index 798b4963..9d500cd4 100644 --- a/app/src/main/java/net/lacolaco/smileessence/preference/InternalPreferenceHelper.java +++ b/app/src/main/java/net/lacolaco/smileessence/preference/InternalPreferenceHelper.java @@ -35,11 +35,11 @@ public class InternalPreferenceHelper extends SharedPreferenceHelper { private static final String FILE_NAME = "AppPreference"; private static final InternalPreferenceHelper instance = new InternalPreferenceHelper(); - public static InternalPreferenceHelper getInstance() { - return instance; + private InternalPreferenceHelper() { } - private InternalPreferenceHelper() { + public static InternalPreferenceHelper getInstance() { + return instance; } // --------------------------- OVERRIDE --------------------------- diff --git a/app/src/main/java/net/lacolaco/smileessence/preference/UserPreferenceHelper.java b/app/src/main/java/net/lacolaco/smileessence/preference/UserPreferenceHelper.java index 584a3474..e3eb95ea 100644 --- a/app/src/main/java/net/lacolaco/smileessence/preference/UserPreferenceHelper.java +++ b/app/src/main/java/net/lacolaco/smileessence/preference/UserPreferenceHelper.java @@ -34,11 +34,11 @@ public class UserPreferenceHelper extends SharedPreferenceHelper { private static final UserPreferenceHelper instance = new UserPreferenceHelper(); - public static UserPreferenceHelper getInstance() { - return instance; + private UserPreferenceHelper() { } - private UserPreferenceHelper() { + public static UserPreferenceHelper getInstance() { + return instance; } // --------------------- GETTER / SETTER METHODS --------------------- diff --git a/app/src/main/java/net/lacolaco/smileessence/twitter/OAuthSession.java b/app/src/main/java/net/lacolaco/smileessence/twitter/OAuthSession.java index aff9e9c2..160e710a 100644 --- a/app/src/main/java/net/lacolaco/smileessence/twitter/OAuthSession.java +++ b/app/src/main/java/net/lacolaco/smileessence/twitter/OAuthSession.java @@ -31,15 +31,10 @@ import twitter4j.auth.AccessToken; import twitter4j.auth.RequestToken; public class OAuthSession { - - // ------------------------------ FIELDS ------------------------------ - - public static final String CALLBACK_OAUTH = "oauth://smileessence"; public static final String KEY_TOKEN = "token"; public static final String KEY_TOKEN_SECRET = "tokenSecret"; public static final String KEY_SCREEN_NAME = "screenName"; public static final String KEY_USER_ID = "userID"; - private static final String OAUTH_VERIFIER = "oauth_verifier"; private RequestToken requestToken; // --------------------- GETTER / SETTER METHODS --------------------- diff --git a/app/src/main/java/net/lacolaco/smileessence/twitter/StatusFilter.java b/app/src/main/java/net/lacolaco/smileessence/twitter/StatusFilter.java deleted file mode 100644 index 6e09d533..00000000 --- a/app/src/main/java/net/lacolaco/smileessence/twitter/StatusFilter.java +++ /dev/null @@ -1,107 +0,0 @@ -/* - * The MIT License (MIT) - * - * Copyright (c) 2012-2014 lacolaco.net - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in all - * copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - * SOFTWARE. - */ - -package net.lacolaco.smileessence.twitter; - -import net.lacolaco.smileessence.Application; -import net.lacolaco.smileessence.entity.DirectMessage; -import net.lacolaco.smileessence.entity.Tweet; -import net.lacolaco.smileessence.util.Consumer; -import net.lacolaco.smileessence.viewmodel.EventViewModel; - -import java.util.HashMap; -import java.util.Map; -import java.util.WeakHashMap; - -public class StatusFilter { - private Map<Class<?>, Map<Object, Consumer<?>>> addHandlers = new HashMap<>(); - private Map<Class<?>, Map<Object, Consumer<Long>>> removeHandlers = new HashMap<>(); - private static StatusFilter instance = new StatusFilter(); - - public static StatusFilter getInstance() { - return instance; - } - - public synchronized <T> void register(Object key, Class<T> klass, Consumer<T> addHandler, Consumer<Long> removeHandler) { - Map<Object, Consumer<?>> addMap = addHandlers.get(klass); - if (addMap == null) { - addMap = new WeakHashMap<>(); - addHandlers.put(klass, addMap); - } - addMap.put(key, addHandler); - - if (removeHandler != null) { - Map<Object, Consumer<Long>> removeMap = removeHandlers.get(klass); - if (removeMap == null) { - removeMap = new WeakHashMap<>(); - removeHandlers.put(klass, removeMap); - } - removeMap.put(key, removeHandler); - } - } - - public synchronized <T> void unregister(Object key) { - for (Map<Object, ?> aMap : addHandlers.values()) { - aMap.remove(key); - } - for (Map<Object, ?> rMap : removeHandlers.values()) { - rMap.remove(key); - } - } - - // -------------------------- STATIC METHODS -------------------------- - - public void filter(Tweet tweet) { - if (!Application.getInstance().getCurrentAccount().isMutedUserListContains(tweet.getOriginalTweet().getUser().getId())) { - filter(Tweet.class, tweet); - } - } - - public void filter(DirectMessage message) { - filter(DirectMessage.class, message); - } - - public void filter(EventViewModel event) { - filter(EventViewModel.class, event); - } - - public <T> void filter(Class<T> klass, T status) { - Map<Object, Consumer<?>> map = addHandlers.get(klass); - if (map != null) { - for (Consumer f_ : map.values()) { - //noinspection unchecked - f_.accept(status); - } - } - } - - public void remove(Class klass, long id) { - Map<Object, Consumer<Long>> map = removeHandlers.get(klass); - if (map != null) { - for (Consumer<Long> f : map.values()) { - f.accept(id); - } - } - } -} diff --git a/app/src/main/java/net/lacolaco/smileessence/twitter/UserStreamListener.java b/app/src/main/java/net/lacolaco/smileessence/twitter/UserStreamListener.java index 8b05bc16..acfb44be 100644 --- a/app/src/main/java/net/lacolaco/smileessence/twitter/UserStreamListener.java +++ b/app/src/main/java/net/lacolaco/smileessence/twitter/UserStreamListener.java @@ -25,53 +25,38 @@ package net.lacolaco.smileessence.twitter; import net.lacolaco.smileessence.R; -import net.lacolaco.smileessence.data.Account; +import net.lacolaco.smileessence.World; import net.lacolaco.smileessence.entity.DirectMessage; +import net.lacolaco.smileessence.entity.Event; import net.lacolaco.smileessence.entity.Tweet; import net.lacolaco.smileessence.entity.User; import net.lacolaco.smileessence.logging.Logger; -import net.lacolaco.smileessence.notification.Notificator; -import net.lacolaco.smileessence.viewmodel.EventViewModel; -import net.lacolaco.smileessence.viewmodel.MessageViewModel; -import net.lacolaco.smileessence.viewmodel.StatusViewModel; import twitter4j.ConnectionLifeCycleListener; import twitter4j.Status; import twitter4j.StatusDeletionNotice; public class UserStreamListener implements twitter4j.UserStreamListener, ConnectionLifeCycleListener { - - // ------------------------------ FIELDS ------------------------------ - - private final Account account; + private final World world; private boolean connected = false; - // --------------------------- CONSTRUCTORS --------------------------- - - public UserStreamListener(Account account) { - this.account = account; + public UserStreamListener(World world) { + this.world = world; } - // --------------------- GETTER / SETTER METHODS --------------------- - public boolean isConnected() { return connected; } - // ------------------------ INTERFACE METHODS ------------------------ - - - // --------------------- Interface ConnectionLifeCycleListener --------------------- - @Override public void onConnect() { connected = true; - Notificator.getInstance().publish(R.string.notice_stream_connect); + world.notify(R.string.notice_stream_connect); } @Override public void onDisconnect() { connected = false; - Notificator.getInstance().publish(R.string.notice_stream_disconnect); + world.notify(R.string.notice_stream_disconnect); } @Override @@ -82,22 +67,24 @@ public class UserStreamListener implements twitter4j.UserStreamListener, Connect @Override public void onStatus(Status status) { - Tweet tweet = Tweet.fromTwitter(status, account.getUserId()); - StatusFilter.getInstance().filter(tweet); + User user = world.getAccount().getUser(); + Tweet tweet = Tweet.fromTwitter(status, user.getId()); + world.addTweet(tweet); if (tweet.isRetweet()) { - if (tweet.getOriginalTweet().getUser().getId() == account.getUserId()) { - addToHistory(new EventViewModel(EventViewModel.EnumEvent.RETWEETED, tweet.getUser(), tweet)); + if (tweet.getOriginalTweet().getUser().getId() == user.getId()) { + addToHistory(new Event(Event.EnumEvent.RETWEETED, tweet.getUser(), tweet)); } - } else if (tweet.getMentions().contains(account.getUser().getScreenName())) { - EventViewModel mentioned = new EventViewModel(EventViewModel.EnumEvent.MENTIONED, tweet.getUser(), tweet); - Notificator.getInstance().publish(mentioned.getFormattedString()); + } else if (tweet.getMentions().contains(user.getScreenName())) { + Event mentioned = new Event(Event.EnumEvent.MENTIONED, tweet.getUser(), tweet); + world.notify(mentioned.getFormattedString()); } } @Override public void onDeletionNotice(StatusDeletionNotice statusDeletionNotice) { - StatusFilter.getInstance().remove(StatusViewModel.class, statusDeletionNotice.getStatusId()); - Tweet.remove(statusDeletionNotice.getStatusId()); + // FIXME + // StatusFilter.getInstance().remove(StatusViewModel.class, statusDeletionNotice.getStatusId()); + // Tweet.remove(statusDeletionNotice.getStatusId()); } @Override @@ -123,8 +110,9 @@ public class UserStreamListener implements twitter4j.UserStreamListener, Connect @Override public void onDeletionNotice(long directMessageId, long userId) { - StatusFilter.getInstance().remove(MessageViewModel.class, directMessageId); - DirectMessage.remove(directMessageId); + // FIXME + // StatusFilter.getInstance().remove(MessageViewModel.class, directMessageId); + // DirectMessage.remove(directMessageId); } @Override @@ -133,26 +121,26 @@ public class UserStreamListener implements twitter4j.UserStreamListener, Connect @Override public void onFavorite(twitter4j.User source, twitter4j.User target, Status favoritedStatus) { - Tweet tweet = Tweet.fromTwitter(favoritedStatus, account.getUserId()); + Tweet tweet = Tweet.fromTwitter(favoritedStatus, world.getAccount().getUserId()); tweet.addFavoriter(source.getId()); - if (User.fromTwitter(target) == account.getUser()) { - addToHistory(new EventViewModel(EventViewModel.EnumEvent.FAVORITED, User.fromTwitter(source), tweet)); + if (User.fromTwitter(target) == world.getAccount().getUser()) { + addToHistory(new Event(Event.EnumEvent.FAVORITED, User.fromTwitter(source), tweet)); } } @Override public void onUnfavorite(twitter4j.User source, twitter4j.User target, twitter4j.Status unfavoritedStatus) { - Tweet tweet = Tweet.fromTwitter(unfavoritedStatus, account.getUserId()); + Tweet tweet = Tweet.fromTwitter(unfavoritedStatus, world.getAccount().getUserId()); tweet.removeFavoriter(source.getId()); - if (User.fromTwitter(target) == account.getUser()) { - addToHistory(new EventViewModel(EventViewModel.EnumEvent.UNFAVORITED, User.fromTwitter(source), tweet)); + if (User.fromTwitter(target) == world.getAccount().getUser()) { + addToHistory(new Event(Event.EnumEvent.UNFAVORITED, User.fromTwitter(source), tweet)); } } @Override public void onFollow(twitter4j.User source, twitter4j.User followedUser) { - if (User.fromTwitter(followedUser) == account.getUser()) { - addToHistory(new EventViewModel(EventViewModel.EnumEvent.FOLLOWED, User.fromTwitter(source))); + if (User.fromTwitter(followedUser) == world.getAccount().getUser()) { + addToHistory(new Event(Event.EnumEvent.FOLLOWED, User.fromTwitter(source))); } } @@ -163,9 +151,9 @@ public class UserStreamListener implements twitter4j.UserStreamListener, Connect @Override public void onDirectMessage(twitter4j.DirectMessage directMessage) { DirectMessage message = DirectMessage.fromTwitter(directMessage); - StatusFilter.getInstance().filter(message); - if (message.getRecipient() == account.getUser()) { - addToHistory(new EventViewModel(EventViewModel.EnumEvent.RECEIVE_MESSAGE, User.fromTwitter(directMessage.getSender()))); + world.addDirectMessage(message); + if (message.getRecipient() == world.getAccount().getUser()) { + addToHistory(new Event(Event.EnumEvent.RECEIVE_MESSAGE, message.getSender())); } } @@ -179,17 +167,17 @@ public class UserStreamListener implements twitter4j.UserStreamListener, Connect @Override public void onUserListSubscription(twitter4j.User subscriber, twitter4j.User listOwner, twitter4j.UserList list) { - account.addListSubscription(list.getFullName()); + world.addListSubscription(list.getFullName()); } @Override public void onUserListUnsubscription(twitter4j.User subscriber, twitter4j.User listOwner, twitter4j.UserList list) { - account.removeListSubscription(list.getFullName()); + world.removeListSubscription(list.getFullName()); } @Override public void onUserListCreation(twitter4j.User listOwner, twitter4j.UserList list) { - account.addListSubscription(list.getFullName()); + world.addListSubscription(list.getFullName()); } @Override @@ -198,7 +186,7 @@ public class UserStreamListener implements twitter4j.UserStreamListener, Connect @Override public void onUserListDeletion(twitter4j.User listOwner, twitter4j.UserList list) { - account.removeListSubscription(list.getFullName()); + world.removeListSubscription(list.getFullName()); } @Override @@ -216,15 +204,15 @@ public class UserStreamListener implements twitter4j.UserStreamListener, Connect @Override public void onBlock(twitter4j.User source, twitter4j.User blockedUser) { - if (User.fromTwitter(blockedUser) == account.getUser()) { - addToHistory(new EventViewModel(EventViewModel.EnumEvent.BLOCKED, User.fromTwitter(source))); + if (User.fromTwitter(blockedUser) == world.getAccount().getUser()) { + addToHistory(new Event(Event.EnumEvent.BLOCKED, User.fromTwitter(source))); } } @Override public void onUnblock(twitter4j.User source, twitter4j.User unblockedUser) { - if (User.fromTwitter(unblockedUser) == account.getUser()) { - addToHistory(new EventViewModel(EventViewModel.EnumEvent.UNBLOCKED, User.fromTwitter(source))); + if (User.fromTwitter(unblockedUser) == world.getAccount().getUser()) { + addToHistory(new Event(Event.EnumEvent.UNBLOCKED, User.fromTwitter(source))); } } @@ -240,8 +228,8 @@ public class UserStreamListener implements twitter4j.UserStreamListener, Connect public void onQuotedTweet(twitter4j.User source, twitter4j.User target, twitter4j.Status quotingTweet) { } - private void addToHistory(EventViewModel mentioned) { - StatusFilter.getInstance().filter(mentioned); - Notificator.getInstance().publish(mentioned.getFormattedString()); + private void addToHistory(Event mentioned) { + world.addEvent(mentioned); + world.notify(mentioned.getFormattedString()); } } diff --git a/app/src/main/java/net/lacolaco/smileessence/twitter/task/Accounts.java b/app/src/main/java/net/lacolaco/smileessence/twitter/task/Accounts.java index 369a0974..7842e349 100644 --- a/app/src/main/java/net/lacolaco/smileessence/twitter/task/Accounts.java +++ b/app/src/main/java/net/lacolaco/smileessence/twitter/task/Accounts.java @@ -13,15 +13,10 @@ import java.util.List; public class Accounts { public static class AccessTokenTask extends BackgroundTask<AccessToken, Void> { - - // ------------------------------ FIELDS ------------------------------ - private final Twitter twitter; private final RequestToken requestToken; private final String pinCode; - // --------------------------- CONSTRUCTORS --------------------------- - public AccessTokenTask(Twitter twitter, RequestToken requestToken, String pinCode) { this.twitter = twitter; this.requestToken = requestToken; @@ -35,13 +30,8 @@ public class Accounts { } public static class RequestTokenTask extends BackgroundTask<RequestToken, Void> { - - // ------------------------------ FIELDS ------------------------------ - private final Twitter twitter; - // --------------------------- CONSTRUCTORS --------------------------- - public RequestTokenTask(Twitter twitter) { this.twitter = twitter; } @@ -53,17 +43,12 @@ public class Accounts { } public static class BlockIDsTask extends BackgroundTask<List<Long>, Void> { - private final Account account; - // --------------------------- CONSTRUCTORS --------------------------- - public BlockIDsTask(Account account) { this.account = account; } - // ------------------------ OVERRIDE METHODS ------------------------ - @Override protected List<Long> doInBackground() throws TwitterException { List<Long> idList = new ArrayList<>(); @@ -84,14 +69,10 @@ public class Accounts { public static class MutesIDsTask extends BackgroundTask<List<Long>, Void> { private final Account account; - // --------------------------- CONSTRUCTORS --------------------------- - public MutesIDsTask(Account account) { this.account = account; } - // ------------------------ OVERRIDE METHODS ------------------------ - @Override protected List<Long> doInBackground() throws TwitterException { List<Long> idList = new ArrayList<>(); diff --git a/app/src/main/java/net/lacolaco/smileessence/twitter/task/Messages.java b/app/src/main/java/net/lacolaco/smileessence/twitter/task/Messages.java index 533a242a..ff13a07c 100644 --- a/app/src/main/java/net/lacolaco/smileessence/twitter/task/Messages.java +++ b/app/src/main/java/net/lacolaco/smileessence/twitter/task/Messages.java @@ -9,23 +9,16 @@ import java.util.List; public class Messages { public static class CreateTask extends BackgroundTask<DirectMessage, Void> { - - // ------------------------------ FIELDS ------------------------------ - private final Account account; - private final String userID; + private final long userID; private final String text; - // --------------------------- CONSTRUCTORS --------------------------- - - public CreateTask(Account account, String screenName, String text) { + public CreateTask(Account account, long userID, String text) { this.account = account; - this.userID = screenName; + this.userID = userID; this.text = text; } - // ------------------------ OVERRIDE METHODS ------------------------ - @Override protected DirectMessage doInBackground() throws TwitterException { return DirectMessage.fromTwitter(account.getTwitter().directMessages().sendDirectMessage(userID, text)); @@ -33,21 +26,14 @@ public class Messages { } public static class DestroyTask extends BackgroundTask<DirectMessage, Void> { - - // ------------------------------ FIELDS ------------------------------ - private final Account account; private final long messageID; - // --------------------------- CONSTRUCTORS --------------------------- - public DestroyTask(Account account, long messageID) { this.account = account; this.messageID = messageID; } - // ------------------------ OVERRIDE METHODS ------------------------ - @Override protected DirectMessage doInBackground() throws TwitterException { return DirectMessage.fromTwitter(account.getTwitter().directMessages().destroyDirectMessage(messageID)); @@ -55,19 +41,12 @@ public class Messages { } public static class GetAllReceived extends TimelineTask<DirectMessage> { - - // ------------------------------ FIELDS ------------------------------ - private final Account account; - // --------------------------- CONSTRUCTORS --------------------------- - public GetAllReceived(Account account) { this.account = account; } - // ------------------------ OVERRIDE METHODS ------------------------ - @Override protected List<DirectMessage> doInBackground() throws TwitterException { return DirectMessage.fromTwitter(account.getTwitter().directMessages().getDirectMessages(getPaging())); @@ -75,19 +54,12 @@ public class Messages { } public static class GetAllSent extends TimelineTask<DirectMessage> { - - // ------------------------------ FIELDS ------------------------------ - private final Account account; - // --------------------------- CONSTRUCTORS --------------------------- - public GetAllSent(Account account) { this.account = account; } - // ------------------------ OVERRIDE METHODS ------------------------ - @Override protected List<DirectMessage> doInBackground() throws TwitterException { return DirectMessage.fromTwitter(account.getTwitter().directMessages().getSentDirectMessages(getPaging())); diff --git a/app/src/main/java/net/lacolaco/smileessence/twitter/task/Tweets.java b/app/src/main/java/net/lacolaco/smileessence/twitter/task/Tweets.java index 016f699c..dcad94dc 100644 --- a/app/src/main/java/net/lacolaco/smileessence/twitter/task/Tweets.java +++ b/app/src/main/java/net/lacolaco/smileessence/twitter/task/Tweets.java @@ -19,21 +19,14 @@ import java.util.List; public class Tweets { public static class GetTask extends BackgroundTask<Tweet, Void> { - - // ------------------------------ FIELDS ------------------------------ - private final Account account; private final long id; - // --------------------------- CONSTRUCTORS --------------------------- - public GetTask(Account account, long id) { this.account = account; this.id = id; } - // ------------------------ OVERRIDE METHODS ------------------------ - @Override protected Tweet doInBackground() throws TwitterException { return Tweet.fromTwitter(account.getTwitter().tweets().showStatus(id), account.getUserId()); @@ -41,18 +34,13 @@ public class Tweets { } public static class CreateTask extends BackgroundTask<Tweet, Void> { - - // ------------------------------ FIELDS ------------------------------ - - private static final int MEDIA_SIZE_LIMIT = 2 * 1024 * 1024; + private static final int MEDIA_SIZE_LIMIT = 5 * 1024 * 1024; private final Account account; private final StatusUpdate update; private final String mediaPath; private String tempFilePath; private boolean resizeFlag; - // --------------------------- CONSTRUCTORS --------------------------- - public CreateTask(Account account, StatusUpdate update, String mediaPath, boolean resize) { this.account = account; this.update = update; @@ -60,8 +48,6 @@ public class Tweets { resizeFlag = resize; } - // --------------------- GETTER / SETTER METHODS --------------------- - private File getMediaFile() { File file = new File(mediaPath); if (file.length() >= MEDIA_SIZE_LIMIT && resizeFlag) { @@ -85,21 +71,17 @@ public class Tweets { e.printStackTrace(); Logger.error(e); } finally { - if (fos != null) { - try { - fos.close(); - } catch (IOException e) { - e.printStackTrace(); - Logger.error(e); - } + try { + if (fos != null) fos.close(); + } catch (IOException e) { + e.printStackTrace(); + Logger.error(e); } } } return file; } - // ------------------------ OVERRIDE METHODS ------------------------ - @Override protected Tweet doInBackground() throws TwitterException { try { @@ -119,25 +101,18 @@ public class Tweets { } public static class DestroyTask extends BackgroundTask<Tweet, Void> { - - // ------------------------------ FIELDS ------------------------------ - private final Account account; private final long statusID; - // --------------------------- CONSTRUCTORS --------------------------- - public DestroyTask(Account account, long statusID) { this.account = account; this.statusID = statusID; } - // ------------------------ OVERRIDE METHODS ------------------------ - @Override protected Tweet doInBackground() throws TwitterException { Tweet t = Tweet.fromTwitter(account.getTwitter().tweets().destroyStatus(statusID), account.getUserId()); - Tweet.remove(t.getId()); + // FIXME: Tweet.remove(t.getId()); return t; } } diff --git a/app/src/main/java/net/lacolaco/smileessence/twitter/task/Users.java b/app/src/main/java/net/lacolaco/smileessence/twitter/task/Users.java index 27c6e54e..60b62841 100644 --- a/app/src/main/java/net/lacolaco/smileessence/twitter/task/Users.java +++ b/app/src/main/java/net/lacolaco/smileessence/twitter/task/Users.java @@ -12,15 +12,10 @@ import java.util.List; public class Users { public static class GetTask extends BackgroundTask<User, Void> { - - // ------------------------------ FIELDS ------------------------------ - private final Account account; private final long userID; private final String screenName; - // --------------------------- CONSTRUCTORS --------------------------- - public GetTask(Account account, long userID) { this.account = account; this.userID = userID; @@ -33,8 +28,6 @@ public class Users { this.userID = -1; } - // ------------------------ OVERRIDE METHODS ------------------------ - @Override protected User doInBackground() throws TwitterException { if (screenName != null) { @@ -46,17 +39,12 @@ public class Users { } public static class GetManyTask extends BackgroundTask<List<String>, Void> { - private final Account account; - // --------------------------- CONSTRUCTORS --------------------------- - public GetManyTask(Account account) { this.account = account; } - // ------------------------ OVERRIDE METHODS ------------------------ - @Override protected List<String> doInBackground() throws TwitterException { return ListUtils.map(account.getTwitter().list().getUserLists(account.getUserId()), UserList::getFullName); @@ -64,21 +52,14 @@ public class Users { } public static class FollowTask extends BackgroundTask<User, Void> { - - // ------------------------------ FIELDS ------------------------------ - private final Account account; private final long userID; - // --------------------------- CONSTRUCTORS --------------------------- - public FollowTask(Account account, long userID) { this.account = account; this.userID = userID; } - // ------------------------ OVERRIDE METHODS ------------------------ - @Override protected User doInBackground() throws TwitterException { return User.fromTwitter(account.getTwitter().friendsFollowers().createFriendship(userID)); @@ -86,21 +67,14 @@ public class Users { } public static class UnfollowTask extends BackgroundTask<User, Void> { - - // ------------------------------ FIELDS ------------------------------ - private final Account account; private final long userID; - // --------------------------- CONSTRUCTORS --------------------------- - public UnfollowTask(Account account, long userID) { this.account = account; this.userID = userID; } - // ------------------------ OVERRIDE METHODS ------------------------ - @Override protected User doInBackground() throws TwitterException { return User.fromTwitter(account.getTwitter().friendsFollowers().destroyFriendship(userID)); @@ -108,21 +82,14 @@ public class Users { } public static class BlockTask extends BackgroundTask<User, Void> { - - // ------------------------------ FIELDS ------------------------------ - private final Account account; private final long userID; - // --------------------------- CONSTRUCTORS --------------------------- - public BlockTask(Account account, long userID) { this.account = account; this.userID = userID; } - // ------------------------ OVERRIDE METHODS ------------------------ - @Override protected User doInBackground() throws TwitterException { return User.fromTwitter(account.getTwitter().users().createBlock(userID)); @@ -130,21 +97,14 @@ public class Users { } public static class ReportForSpamTask extends BackgroundTask<User, Void> { - - // ------------------------------ FIELDS ------------------------------ - private final Account account; private final long userID; - // --------------------------- CONSTRUCTORS --------------------------- - public ReportForSpamTask(Account account, long userID) { this.account = account; this.userID = userID; } - // ------------------------ OVERRIDE METHODS ------------------------ - @Override protected User doInBackground() throws TwitterException { return User.fromTwitter(account.getTwitter().spamReporting().reportSpam(userID)); @@ -152,21 +112,14 @@ public class Users { } public static class UnblockTask extends BackgroundTask<User, Void> { - - // ------------------------------ FIELDS ------------------------------ - private final Account account; private final long userID; - // --------------------------- CONSTRUCTORS --------------------------- - public UnblockTask(Account account, long userID) { this.account = account; this.userID = userID; } - // ------------------------ OVERRIDE METHODS ------------------------ - @Override protected User doInBackground() throws TwitterException { return User.fromTwitter(account.getTwitter().users().destroyBlock(userID)); @@ -174,14 +127,9 @@ public class Users { } public static class ShowFriendshipTask extends BackgroundTask<Relationship, Void> { - - // ------------------------------ FIELDS ------------------------------ - private final Account account; private final long userID; - // --------------------------- CONSTRUCTORS --------------------------- - public ShowFriendshipTask(Account account, long userID) { this.account = account; this.userID = userID; diff --git a/app/src/main/java/net/lacolaco/smileessence/util/BackgroundTask.java b/app/src/main/java/net/lacolaco/smileessence/util/BackgroundTask.java index 90671b26..b6d985e2 100644 --- a/app/src/main/java/net/lacolaco/smileessence/util/BackgroundTask.java +++ b/app/src/main/java/net/lacolaco/smileessence/util/BackgroundTask.java @@ -4,12 +4,12 @@ import android.os.AsyncTask; import net.lacolaco.smileessence.logging.Logger; public abstract class BackgroundTask<Result, Progress> { + private final InnerAsyncTask task; private Consumer<Result> then; private Consumer<Progress> progress; private Consumer<Exception> fail; private Runnable finish; private Exception exception; - private final InnerAsyncTask task; public BackgroundTask() { this.task = new InnerAsyncTask(); diff --git a/app/src/main/java/net/lacolaco/smileessence/util/Function.java b/app/src/main/java/net/lacolaco/smileessence/util/Function.java index a4c60899..5e374e8e 100644 --- a/app/src/main/java/net/lacolaco/smileessence/util/Function.java +++ b/app/src/main/java/net/lacolaco/smileessence/util/Function.java @@ -2,15 +2,4 @@ package net.lacolaco.smileessence.util; public interface Function<T, R> { R apply(T t); - /*default <V> Function<V, R> compose(Function<? super V, ? extends T> before) { - Objects.requireNonNull(before); - return (V v) -> apply(before.apply(v)); - } - default <V> Function<T, V> andThen(Function<? super R, ? extends V> after) { - Objects.requireNonNull(after); - return (T t) -> after.apply(apply(t)); - } - static <T> Function<T, T> identity() { - return t -> t; - }*/ } diff --git a/app/src/main/java/net/lacolaco/smileessence/util/IntentUtils.java b/app/src/main/java/net/lacolaco/smileessence/util/IntentUtils.java index 51d0e777..9ec4aa46 100644 --- a/app/src/main/java/net/lacolaco/smileessence/util/IntentUtils.java +++ b/app/src/main/java/net/lacolaco/smileessence/util/IntentUtils.java @@ -29,8 +29,8 @@ import android.content.Intent; import android.content.pm.PackageManager; import android.content.pm.ResolveInfo; import android.net.Uri; +import net.lacolaco.smileessence.Application; import net.lacolaco.smileessence.R; -import net.lacolaco.smileessence.notification.Notificator; import java.util.List; @@ -50,7 +50,7 @@ public class IntentUtils { activity.startActivity(intent); return true; } else { - Notificator.getInstance().alert(R.string.notice_error_start_activity); + Application.toast(R.string.notice_error_start_activity); } return false; } @@ -81,7 +81,7 @@ public class IntentUtils { activity.startActivityForResult(intent, requestCode); return true; } else { - Notificator.getInstance().alert(R.string.notice_error_start_activity); + Application.toast(R.string.notice_error_start_activity); } return false; } diff --git a/app/src/main/java/net/lacolaco/smileessence/util/UIHandler.java b/app/src/main/java/net/lacolaco/smileessence/util/UIHandler.java index b1742c05..f228f23f 100644 --- a/app/src/main/java/net/lacolaco/smileessence/util/UIHandler.java +++ b/app/src/main/java/net/lacolaco/smileessence/util/UIHandler.java @@ -28,8 +28,6 @@ import android.os.Handler; import android.os.Looper; public class UIHandler extends Handler { - // --------------------------- CONSTRUCTORS --------------------------- - public UIHandler() { super(Looper.getMainLooper()); } diff --git a/app/src/main/java/net/lacolaco/smileessence/view/ColoredRelativeLayout.java b/app/src/main/java/net/lacolaco/smileessence/view/ColoredRelativeLayout.java index 8b623361..33fc05ac 100644 --- a/app/src/main/java/net/lacolaco/smileessence/view/ColoredRelativeLayout.java +++ b/app/src/main/java/net/lacolaco/smileessence/view/ColoredRelativeLayout.java @@ -4,19 +4,17 @@ import android.content.Context; import android.content.res.TypedArray; import android.graphics.Canvas; import android.graphics.Paint; -import android.support.v4.content.ContextCompat; import android.util.AttributeSet; import android.widget.RelativeLayout; import net.lacolaco.smileessence.R; public class ColoredRelativeLayout extends RelativeLayout { - private int highlightColors[] = new int[4]; + public static final int HIGHLIGHT_NONE = 0; private final Paint paint = new Paint(); + private int highlightColors[] = new int[4]; private boolean showAccent = false; - public static final int HIGHLIGHT_NONE = 0; - public ColoredRelativeLayout(Context context) { this(context, null); } diff --git a/app/src/main/java/net/lacolaco/smileessence/view/Partials.java b/app/src/main/java/net/lacolaco/smileessence/view/Partials.java new file mode 100644 index 00000000..c6f8ffef --- /dev/null +++ b/app/src/main/java/net/lacolaco/smileessence/view/Partials.java @@ -0,0 +1,233 @@ +package net.lacolaco.smileessence.view; + +import android.app.Activity; +import android.text.Html; +import android.view.View; +import android.view.ViewGroup; +import android.widget.ImageView; +import android.widget.ListView; +import android.widget.TextView; +import com.android.volley.toolbox.NetworkImageView; +import net.lacolaco.smileessence.Application; +import net.lacolaco.smileessence.R; +import net.lacolaco.smileessence.activity.MainActivity; +import net.lacolaco.smileessence.data.Account; +import net.lacolaco.smileessence.data.ImageCache; +import net.lacolaco.smileessence.entity.DirectMessage; +import net.lacolaco.smileessence.entity.RBinding; +import net.lacolaco.smileessence.entity.Tweet; +import net.lacolaco.smileessence.preference.UserPreferenceHelper; +import net.lacolaco.smileessence.util.StringUtils; +import net.lacolaco.smileessence.util.UIObserverBundle; +import net.lacolaco.smileessence.view.adapter.CustomListAdapter; +import net.lacolaco.smileessence.view.dialog.MessageDetailDialogFragment; +import net.lacolaco.smileessence.view.dialog.StatusDetailDialogFragment; +import net.lacolaco.smileessence.view.dialog.UserDetailDialogFragment; +import net.lacolaco.smileessence.view.listener.ListItemClickListener; + +import java.lang.ref.WeakReference; +import java.util.ArrayList; +import java.util.List; + +public class Partials { + public static View getTweetView(Tweet tweet, Activity activity, View convertView, boolean expandEmbeddedTweets) { + if (convertView == null) { + convertView = activity.getLayoutInflater().inflate(R.layout.list_item_status, null); + } + UIObserverBundle bundle = (UIObserverBundle) convertView.getTag(); + if (bundle != null) { + bundle.detachAll(); + } else { + bundle = new UIObserverBundle(); + convertView.setTag(bundle); + } + + convertView.setOnClickListener(new ListItemClickListener(activity, () -> DialogHelper.showDialog(activity, StatusDetailDialogFragment.newInstance(tweet)))); + + updateViewUser(tweet, activity, convertView); + updateViewBody(tweet, activity, convertView); + updateViewFavorited(tweet, convertView); + updateViewEmbeddeds(tweet, activity, convertView, expandEmbeddedTweets); + + final WeakReference<View> weakView = new WeakReference<>(convertView); + final WeakReference<Activity> weakActivity = new WeakReference<>(activity); + bundle.attach(tweet.getOriginalTweet(), changes -> { + View strongView = weakView.get(); + if (strongView != null && changes.contains(RBinding.FAVORITERS)) + updateViewFavorited(tweet, strongView); + }); + bundle.attach(tweet.getUser(), changes -> { + View strongView = weakView.get(); + Activity strongActivity = weakActivity.get(); + if (strongView != null && strongActivity != null && changes.contains(RBinding.BASIC)) + updateViewUser(tweet, strongActivity, strongView); + }); + + return convertView; + } + + + private static void updateViewEmbeddeds(Tweet tweet, Activity activity, View convertView, boolean expandEmbeddedTweets) { + final ListView embeddedStatus = (ListView) convertView.findViewById(R.id.listview_status_embedded_status); + if (expandEmbeddedTweets) { + final List<Tweet> list = new ArrayList<>(); + CustomListAdapter<Tweet> embeddedTweetsAdapter = new CustomListAdapter<Tweet>() { + @Override + protected List<Tweet> getList() { + return list; + } + + @Override + public View getView(int position, View convertView, ViewGroup parent) { + return Partials.getTweetView(getItem(position), activity, convertView, false); + } + }; + + Account account = Application.getCurrentWorld().getAccount(); + for (long id : tweet.getEmbeddedStatusIDs()) { + Tweet.fetchTask(id, account).onDone(t -> list.add(t)).execute(); + } + embeddedStatus.setAdapter(embeddedTweetsAdapter); + embeddedStatus.setVisibility(View.VISIBLE); + } else { + embeddedStatus.setAdapter(null); // view may be reused, set null explicitly + embeddedStatus.setVisibility(View.GONE); + } + } + + private static void updateViewUser(Tweet tweet, Activity activity, View convertView) { + int textSize = UserPreferenceHelper.getInstance().getTextSize(); + + NetworkImageView icon = (NetworkImageView) convertView.findViewById(R.id.imageview_status_icon); + String iconUrl = tweet.getOriginalTweet().getUser().getProfileImageUrlOriginal(); + ImageCache.getInstance().setImageToView(iconUrl, icon); + icon.setOnClickListener(v -> onIconClick(tweet, activity)); + + TextView header = (TextView) convertView.findViewById(R.id.textview_status_header); + header.setTextSize(textSize); + header.setText(tweet.getOriginalTweet().getUser().getFormattedName()); + + ((ColoredRelativeLayout) convertView).setAccentVisibility(tweet.getUser() == Application.getCurrentWorld().getAccount().getUser()); + } + + private static void updateViewBody(Tweet tweet, Activity activity, View convertView) { + int textSize = UserPreferenceHelper.getInstance().getTextSize(); + + TextView content = (TextView) convertView.findViewById(R.id.textview_status_text); + content.setTextSize(textSize); + String rawText = tweet.getOriginalTweet().getText(); + content.setText(rawText); + TextView footer = (TextView) convertView.findViewById(R.id.textview_status_footer); + footer.setTextSize(textSize - 2); + footer.setText(getFooterText(tweet)); + + ColoredRelativeLayout typedView = (ColoredRelativeLayout) convertView; + if (tweet.isRetweet()) { + typedView.setHighlight(2); + } else if (tweet.getOriginalTweet().getMentions().contains(Application.getCurrentWorld().getAccount().getUser().getScreenName())) { + typedView.setHighlight(1); + } else { + typedView.setHighlight(0); + } + } + + private static void updateViewFavorited(Tweet tweet, View convertView) { + ImageView favorited = (ImageView) convertView.findViewById(R.id.imageview_status_favorited); + favorited.setVisibility(tweet.isFavoritedBy(Application.getCurrentWorld().getAccount().getUserId()) ? View.VISIBLE : View.GONE); + } + + private static void onIconClick(Tweet tweet, Activity activity) { + UserDetailDialogFragment dialogFragment = new UserDetailDialogFragment(); + dialogFragment.setUserID(tweet.getOriginalTweet().getUser().getId()); + DialogHelper.showDialog(activity, dialogFragment); + } + + private static String getFooterText(Tweet tweet) { + StringBuilder builder = new StringBuilder(); + if (tweet.isRetweet()) { + builder + .append("(RT: ") + .append(tweet.getUser().getScreenName()) + .append(") "); + } + builder.append(StringUtils.dateToString(tweet.getOriginalTweet().getCreatedAt())); + builder.append(" via "); + builder.append(Html.fromHtml(tweet.getOriginalTweet().getSource())); + return builder.toString(); + } + + public static View getDirectMessageView(DirectMessage directMessage, Activity activity, View convertView) { + if (convertView == null) { + convertView = activity.getLayoutInflater().inflate(R.layout.list_item_status, null); + } + UIObserverBundle bundle = (UIObserverBundle) convertView.getTag(); + if (bundle != null) { + bundle.detachAll(); + } else { + bundle = new UIObserverBundle(); + convertView.setTag(bundle); + } + + convertView.setOnClickListener(new ListItemClickListener(activity, () -> { + MessageDetailDialogFragment dialogFragment = new MessageDetailDialogFragment(); + dialogFragment.setMessageID(directMessage.getId()); + DialogHelper.showDialog(activity, dialogFragment); + })); + + ImageView favorited = (ImageView) convertView.findViewById(R.id.imageview_status_favorited); + favorited.setVisibility(View.GONE); + + updateViewSender(directMessage, activity, convertView); + updateViewBody(directMessage, activity, convertView); + + final WeakReference<View> weakView = new WeakReference<>(convertView); + final WeakReference<MainActivity> weakActivity = new WeakReference<>((MainActivity) activity); + bundle.attach(directMessage.getSender(), changes -> { + View strongView = weakView.get(); + MainActivity strongActivity = weakActivity.get(); + if (strongView != null && strongActivity != null && changes.contains(RBinding.BASIC)) + updateViewSender(directMessage, strongActivity, strongView); + }); + + return convertView; + } + + private static String getFooterText(DirectMessage directMessage, Account account) { + StringBuilder builder = new StringBuilder(); + builder.append(StringUtils.dateToString(directMessage.getCreatedAt())); + if (directMessage.getSender().getId() == account.getUserId()) { + builder.append(" to @").append(directMessage.getRecipient().getScreenName()); + } + return builder.toString(); + } + + private static void updateViewSender(DirectMessage directMessage, Activity activity, View convertView) { + int textSize = UserPreferenceHelper.getInstance().getTextSize(); + + NetworkImageView icon = (NetworkImageView) convertView.findViewById(R.id.imageview_status_icon); + String iconUrl = directMessage.getSender().getProfileImageUrlOriginal(); + ImageCache.getInstance().setImageToView(iconUrl, icon); + icon.setOnClickListener(v -> { + UserDetailDialogFragment dialogFragment = new UserDetailDialogFragment(); + dialogFragment.setUserID(directMessage.getSender().getId()); + DialogHelper.showDialog(activity, dialogFragment); + }); + + TextView header = (TextView) convertView.findViewById(R.id.textview_status_header); + header.setTextSize(textSize); + header.setText(directMessage.getSender().getFormattedName()); + + ((ColoredRelativeLayout) convertView).setAccentVisibility(directMessage.getSender() == Application.getCurrentWorld().getAccount().getUser()); + } + + private static void updateViewBody(DirectMessage directMessage, Activity activity, View convertView) { + int textSize = UserPreferenceHelper.getInstance().getTextSize(); + + TextView content = (TextView) convertView.findViewById(R.id.textview_status_text); + content.setTextSize(textSize); + content.setText(directMessage.getText()); + TextView footer = (TextView) convertView.findViewById(R.id.textview_status_footer); + footer.setTextSize(textSize - 2); + footer.setText(getFooterText(directMessage, Application.getCurrentWorld().getAccount())); + } +} diff --git a/app/src/main/java/net/lacolaco/smileessence/view/SettingFragment.java b/app/src/main/java/net/lacolaco/smileessence/view/SettingFragment.java index d9891a49..7ed9636b 100644 --- a/app/src/main/java/net/lacolaco/smileessence/view/SettingFragment.java +++ b/app/src/main/java/net/lacolaco/smileessence/view/SettingFragment.java @@ -24,6 +24,7 @@ package net.lacolaco.smileessence.view; +import android.app.AlertDialog; import android.content.Intent; import android.content.SharedPreferences; import android.os.Bundle; @@ -32,39 +33,30 @@ import android.preference.ListPreference; import android.preference.Preference; import android.preference.PreferenceFragment; import android.text.TextUtils; +import android.view.LayoutInflater; +import android.view.View; +import android.widget.TextView; import net.lacolaco.smileessence.Application; import net.lacolaco.smileessence.BuildConfig; import net.lacolaco.smileessence.R; import net.lacolaco.smileessence.activity.LicenseActivity; -import net.lacolaco.smileessence.activity.ManageAccountsActivity; -import net.lacolaco.smileessence.notification.Notificator; -import net.lacolaco.smileessence.view.dialog.AppInfoDialogFragment; import static android.content.SharedPreferences.OnSharedPreferenceChangeListener; public class SettingFragment extends PreferenceFragment implements OnSharedPreferenceChangeListener, Preference.OnPreferenceChangeListener, Preference.OnPreferenceClickListener { - private static final int TEXT_SIZE_MIN = 8; - private static final int TEXT_SIZE_MAX = 24; - - // --------------------- Interface OnPreferenceChangeListener --------------------- - @Override public boolean onPreferenceChange(Preference preference, Object newValue) { String newValueStr = String.valueOf(newValue); if (preference.getKey().contentEquals(getString(R.string.key_setting_text_size))) { if (TextUtils.isDigitsOnly(newValueStr)) { - int newTextSize = Integer.parseInt(newValueStr); - if (TEXT_SIZE_MIN <= newTextSize && newTextSize <= TEXT_SIZE_MAX) { - return true; - } - Notificator.getInstance().alert(R.string.error_setting_text_size_range); + return true; } else { - Notificator.getInstance().alert(R.string.error_setting_text_size_not_number); + Application.toast(R.string.error_setting_text_size_not_number); } return false; } else if (preference.getKey().contentEquals(getString(R.string.key_setting_theme))) { - Notificator.getInstance().publish(R.string.notice_theme_changed); + Application.toast(R.string.notice_theme_changed); } return true; } @@ -76,8 +68,6 @@ public class SettingFragment extends PreferenceFragment implements OnSharedPrefe String key = preference.getKey(); if (key.contentEquals(getString(R.string.key_setting_application_information))) { openAppInfoDialog(); - } else if (key.contentEquals(getString(R.string.key_setting_accounts))) { - openManageAccountsActivity(); } else if (key.contentEquals(getString(R.string.key_setting_licenses))) { openLicenseActivity(); } @@ -97,8 +87,6 @@ public class SettingFragment extends PreferenceFragment implements OnSharedPrefe public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); addPreferencesFromResource(R.xml.setting); - Preference manageAccounts = findPreference(R.string.key_setting_accounts); - manageAccounts.setOnPreferenceClickListener(this); EditTextPreference textSizePreference = (EditTextPreference) findPreference(R.string.key_setting_text_size); textSizePreference.setSummary(textSizePreference.getText()); textSizePreference.setOnPreferenceChangeListener(this); @@ -137,14 +125,17 @@ public class SettingFragment extends PreferenceFragment implements OnSharedPrefe getActivity().startActivity(intent); } - private void openManageAccountsActivity() { - Intent intent = new Intent(getActivity(), ManageAccountsActivity.class); - getActivity().startActivity(intent); - } - private void openAppInfoDialog() { - AppInfoDialogFragment dialog = new AppInfoDialogFragment(); - DialogHelper.showDialog(getActivity(), dialog); + LayoutInflater inflater = getActivity().getLayoutInflater(); + View contentView = inflater.inflate(R.layout.dialog_app_info, null); + TextView versionTextView = (TextView) contentView.findViewById(R.id.versionTextView); + versionTextView.setText(BuildConfig.VERSION_NAME + " (rev: " + BuildConfig.VERSION_CODE + "; upstream: " + getString(R.string.app_version_full) + ")"); + + new AlertDialog.Builder(getActivity()) + .setTitle(R.string.dialog_title_about) + .setView(contentView) + .setPositiveButton(R.string.alert_dialog_ok, (dialog, which) -> dialog.dismiss()) + .create().show(); } private void setSummaryCurrentValue() { diff --git a/app/src/main/java/net/lacolaco/smileessence/view/ThreeStateButton.java b/app/src/main/java/net/lacolaco/smileessence/view/ThreeStateButton.java index 7554e2fb..d5358db5 100644 --- a/app/src/main/java/net/lacolaco/smileessence/view/ThreeStateButton.java +++ b/app/src/main/java/net/lacolaco/smileessence/view/ThreeStateButton.java @@ -43,14 +43,14 @@ public class ThreeStateButton extends Button { setState(STATE_OFF); } + public int getState() { + return state; + } + public void setState(int s) { state = s; setText(texts[state]); setBackground(backgrounds[state]); setEnabled(state != STATE_LOCKED); } - - public int getState() { - return state; - } } diff --git a/app/src/main/java/net/lacolaco/smileessence/view/adapter/CustomListAdapter.java b/app/src/main/java/net/lacolaco/smileessence/view/adapter/CustomListAdapter.java index 802a0dd3..6d7420fb 100644 --- a/app/src/main/java/net/lacolaco/smileessence/view/adapter/CustomListAdapter.java +++ b/app/src/main/java/net/lacolaco/smileessence/view/adapter/CustomListAdapter.java @@ -1,37 +1,20 @@ package net.lacolaco.smileessence.view.adapter; -import android.app.Activity; -import android.view.View; -import android.view.ViewGroup; import android.widget.BaseAdapter; import net.lacolaco.smileessence.util.UIHandler; -import net.lacolaco.smileessence.viewmodel.IViewModel; import java.util.ArrayList; +import java.util.Collections; import java.util.List; -public abstract class CustomListAdapter<T extends IViewModel> extends BaseAdapter { - - // ------------------------------ FIELDS ------------------------------ - - protected boolean isNotifiable = true; +public abstract class CustomListAdapter<T> extends BaseAdapter { + private boolean isNotifiable = true; private List<T> frozenList = new ArrayList<>(); - private Activity activity; - - // --------------------------- CONSTRUCTORS --------------------------- - - CustomListAdapter(Activity activity) { - this.activity = activity; - } - - // --------------------- GETTER / SETTER METHODS --------------------- public final void setNotifiable(boolean notifiable) { isNotifiable = notifiable; } - // --------------------- Interface BaseAdapter --------------------- - @Override public final int getCount() { return frozenList.size(); @@ -48,21 +31,12 @@ public abstract class CustomListAdapter<T extends IViewModel> extends BaseAdapte } @Override - public final View getView(int position, View convertView, ViewGroup parent) { - return getItem(position).getView(activity, activity.getLayoutInflater(), convertView); - } - - // ------------------------ OVERRIDE METHODS ------------------------ - - @Override public final void notifyDataSetChanged() { - frozenList = getFrozenList(); + frozenList = Collections.unmodifiableList(getList()); super.notifyDataSetChanged(); } - // -------------------------- OTHER METHODS -------------------------- - - protected abstract List<T> getFrozenList(); + protected abstract List<T> getList(); public void update() { if (isNotifiable) { diff --git a/app/src/main/java/net/lacolaco/smileessence/view/adapter/EventListAdapter.java b/app/src/main/java/net/lacolaco/smileessence/view/adapter/EventListAdapter.java index 18741e02..2ce0386d 100644 --- a/app/src/main/java/net/lacolaco/smileessence/view/adapter/EventListAdapter.java +++ b/app/src/main/java/net/lacolaco/smileessence/view/adapter/EventListAdapter.java @@ -25,13 +25,92 @@ package net.lacolaco.smileessence.view.adapter; import android.app.Activity; -import net.lacolaco.smileessence.viewmodel.EventViewModel; +import android.view.View; +import android.view.ViewGroup; +import android.widget.ImageView; +import android.widget.TextView; +import com.android.volley.toolbox.NetworkImageView; +import net.lacolaco.smileessence.R; +import net.lacolaco.smileessence.World; +import net.lacolaco.smileessence.data.ImageCache; +import net.lacolaco.smileessence.entity.Event; +import net.lacolaco.smileessence.entity.RBinding; +import net.lacolaco.smileessence.preference.UserPreferenceHelper; +import net.lacolaco.smileessence.util.StringUtils; +import net.lacolaco.smileessence.util.UIObserverBundle; +import net.lacolaco.smileessence.view.DialogHelper; +import net.lacolaco.smileessence.view.dialog.UserDetailDialogFragment; +import net.lacolaco.smileessence.view.listener.ListItemClickListener; -public class EventListAdapter extends UnorderedCustomListAdapter<EventViewModel> { +import java.lang.ref.WeakReference; +import java.util.List; - // --------------------------- CONSTRUCTORS --------------------------- +public class EventListAdapter extends CustomListAdapter<Event> { + private final World world; + private final Activity activity; - public EventListAdapter(Activity activity) { - super(activity); + public EventListAdapter(World world, Activity activity) { + super(); + this.world = world; + this.activity = activity; + } + + @Override + protected List<Event> getList() { + return world.getEvents(); + } + + @Override + public View getView(int position, View convertView, ViewGroup parent) { + Event event = getItem(position); + if (convertView == null) { + convertView = activity.getLayoutInflater().inflate(R.layout.list_item_status, null); + } + UIObserverBundle bundle = (UIObserverBundle) convertView.getTag(); + if (bundle != null) { + bundle.detachAll(); + } else { + bundle = new UIObserverBundle(); + convertView.setTag(bundle); + } + + int textSize = UserPreferenceHelper.getInstance().getTextSize(); + + TextView header = (TextView) convertView.findViewById(R.id.textview_status_header); + header.setTextSize(textSize); + + updateViewUser(event, convertView); + + TextView content = (TextView) convertView.findViewById(R.id.textview_status_text); + content.setTextSize(textSize); + content.setText(event.getTargetObject() != null ? event.getTargetObject().getText() : ""); + TextView footer = (TextView) convertView.findViewById(R.id.textview_status_footer); + footer.setTextSize(textSize - 2); + footer.setText(StringUtils.dateToString(event.getCreatedAt())); + ImageView favorited = (ImageView) convertView.findViewById(R.id.imageview_status_favorited); + favorited.setVisibility(View.GONE); + convertView.setOnClickListener(new ListItemClickListener(activity, () -> { + UserDetailDialogFragment fragment = new UserDetailDialogFragment(); + fragment.setUserID(event.getSource().getId()); + DialogHelper.showDialog(activity, fragment); + })); + + final WeakReference<View> weakView = new WeakReference<>(convertView); + bundle.attach(event.getSource(), changes -> { + View strongView = weakView.get(); + if (strongView != null && changes.contains(RBinding.BASIC)) + updateViewUser(event, strongView); + }); + + return convertView; + } + + private void updateViewUser(Event event, View convertedView) { + NetworkImageView icon = (NetworkImageView) convertedView.findViewById(R.id.imageview_status_icon); + String iconUrl = event.getSource().getProfileImageUrlOriginal(); + ImageCache.getInstance().setImageToView(iconUrl, icon); + + TextView header = (TextView) convertedView.findViewById(R.id.textview_status_header); + header.setText(event.getFormattedString()); } } diff --git a/app/src/main/java/net/lacolaco/smileessence/view/adapter/MessageListAdapter.java b/app/src/main/java/net/lacolaco/smileessence/view/adapter/MessageListAdapter.java index 114f9e58..c2a53df9 100644 --- a/app/src/main/java/net/lacolaco/smileessence/view/adapter/MessageListAdapter.java +++ b/app/src/main/java/net/lacolaco/smileessence/view/adapter/MessageListAdapter.java @@ -25,23 +25,28 @@ package net.lacolaco.smileessence.view.adapter; import android.app.Activity; -import net.lacolaco.smileessence.viewmodel.MessageViewModel; +import android.view.View; +import android.view.ViewGroup; +import net.lacolaco.smileessence.entity.DirectMessage; +import net.lacolaco.smileessence.view.Partials; -public class MessageListAdapter extends OrderedCustomListAdapter<MessageViewModel> { - - // --------------------------- CONSTRUCTORS --------------------------- +public class MessageListAdapter extends OrderedCustomListAdapter<DirectMessage> { + private final Activity activity; public MessageListAdapter(Activity activity) { - super(activity); + this.activity = activity; } - // --------------------- GETTER / SETTER METHODS --------------------- - public long getLastID() { - return getItem(getCount() - 1).getDirectMessage().getId(); + return getItem(getCount() - 1).getId(); } public long getTopID() { - return getItem(0).getDirectMessage().getId(); + return getItem(0).getId(); + } + + @Override + public View getView(int position, View convertView, ViewGroup parent) { + return Partials.getDirectMessageView(getItem(position), activity, convertView); } } diff --git a/app/src/main/java/net/lacolaco/smileessence/view/adapter/OrderedCustomListAdapter.java b/app/src/main/java/net/lacolaco/smileessence/view/adapter/OrderedCustomListAdapter.java index 43d04b2e..3de58658 100644 --- a/app/src/main/java/net/lacolaco/smileessence/view/adapter/OrderedCustomListAdapter.java +++ b/app/src/main/java/net/lacolaco/smileessence/view/adapter/OrderedCustomListAdapter.java @@ -1,66 +1,31 @@ -/* - * The MIT License (MIT) - * - * Copyright (c) 2012-2014 lacolaco.net - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in all - * copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - * SOFTWARE. - */ - package net.lacolaco.smileessence.view.adapter; -import android.app.Activity; import net.lacolaco.smileessence.entity.IdObject; -import net.lacolaco.smileessence.viewmodel.IViewModel; import java.util.*; -public class OrderedCustomListAdapter<T extends IViewModel & IdObject> extends CustomListAdapter<T> { - - // ------------------------------ FIELDS ------------------------------ - +public abstract class OrderedCustomListAdapter<T extends IdObject> extends CustomListAdapter<T> { private final Map<Long, T> treeMap; - // --------------------------- CONSTRUCTORS --------------------------- - - public OrderedCustomListAdapter(Activity activity) { - this(activity, Long::compare); + public OrderedCustomListAdapter() { + this(Long::compare); } - public OrderedCustomListAdapter(Activity activity, Comparator<Long> comparator) { - super(activity); - this.treeMap = new TreeMap<>(Collections.reverseOrder(comparator)); // 降順 + public OrderedCustomListAdapter(Comparator<Long> comparator) { + super(); + this.treeMap = new TreeMap<>(Collections.reverseOrder(comparator)); } - // ------------------------ OVERRIDE METHODS ------------------------ - @Override - protected synchronized List<T> getFrozenList() { - return Collections.unmodifiableList(new ArrayList<>(treeMap.values())); + protected synchronized List<T> getList() { + return new ArrayList<>(treeMap.values()); } - // -------------------------- OTHER METHODS -------------------------- - - public synchronized void addItem(T item) { + public synchronized void add(T item) { treeMap.put(item.getId(), item); } - public synchronized void addItems(List<T> items) { + public synchronized void addAll(Collection<T> items) { for (T item : items) { treeMap.put(item.getId(), item); } @@ -70,16 +35,7 @@ public class OrderedCustomListAdapter<T extends IViewModel & IdObject> extends C treeMap.clear(); } - public synchronized T removeItem(T item) { + public synchronized T remove(T item) { return treeMap.remove(item.getId()); } - - public synchronized int removeItemById(long id) { - T item = treeMap.remove(id); - if (item == null) { - return 0; - } else { - return 1; - } - } } diff --git a/app/src/main/java/net/lacolaco/smileessence/view/adapter/SearchListAdapter.java b/app/src/main/java/net/lacolaco/smileessence/view/adapter/SearchListAdapter.java deleted file mode 100644 index 48657748..00000000 --- a/app/src/main/java/net/lacolaco/smileessence/view/adapter/SearchListAdapter.java +++ /dev/null @@ -1,65 +0,0 @@ -/* - * The MIT License (MIT) - * - * Copyright (c) 2012-2014 lacolaco.net - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in all - * copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - * SOFTWARE. - */ - -package net.lacolaco.smileessence.view.adapter; - -import android.app.Activity; - -public class SearchListAdapter extends StatusListAdapter { - private String query; - private OnQueryChangeListener listener; - - // --------------------------- CONSTRUCTORS --------------------------- - - public SearchListAdapter(Activity activity) { - super(activity); - } - - // --------------------- GETTER / SETTER METHODS --------------------- - - public String getQuery() { - return query; - } - - public void setOnQueryChangeListener(OnQueryChangeListener listener) { - this.listener = listener; - } - - // -------------------------- OTHER METHODS -------------------------- - - public void initSearch(String query) { - this.query = query; - clear(); - if (listener != null) { - listener.onQueryChange(query); - } - } - - // -------------------------- INNER CLASSES -------------------------- - - public interface OnQueryChangeListener { - - void onQueryChange(String newQuery); - } -} diff --git a/app/src/main/java/net/lacolaco/smileessence/view/adapter/StatusListAdapter.java b/app/src/main/java/net/lacolaco/smileessence/view/adapter/StatusListAdapter.java deleted file mode 100644 index 5fda8d56..00000000 --- a/app/src/main/java/net/lacolaco/smileessence/view/adapter/StatusListAdapter.java +++ /dev/null @@ -1,71 +0,0 @@ -/* - * The MIT License (MIT) - * - * Copyright (c) 2012-2014 lacolaco.net - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in all - * copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - * SOFTWARE. - */ - -package net.lacolaco.smileessence.view.adapter; - -import android.app.Activity; -import net.lacolaco.smileessence.entity.Tweet; -import net.lacolaco.smileessence.viewmodel.StatusViewModel; - -public class StatusListAdapter extends OrderedCustomListAdapter<StatusViewModel> { - - // --------------------------- CONSTRUCTORS --------------------------- - - public StatusListAdapter(Activity activity) { - super(activity); - } - - // --------------------- GETTER / SETTER METHODS --------------------- - - public long getLastID() { - if (getCount() > 0) { - return getItem(getCount() - 1).getTweet().getId(); - } else { - return -1; - } - } - - public long getTopID() { - if (getCount() > 0) { - return getItem(0).getTweet().getId(); - } else { - return -1; - } - } - - // -------------------------- OTHER METHODS -------------------------- - - @Override - public synchronized int removeItemById(long statusID) { - int count = 0; - count += super.removeItemById(statusID); - Tweet t = Tweet.fetch(statusID); - if (t != null) { - for (long retweetId : t.getRetweets().values()) { - count += super.removeItemById(retweetId); - } - } - return count; - } -} diff --git a/app/src/main/java/net/lacolaco/smileessence/view/adapter/TimelineAdapter.java b/app/src/main/java/net/lacolaco/smileessence/view/adapter/TimelineAdapter.java new file mode 100644 index 00000000..0dbe8d53 --- /dev/null +++ b/app/src/main/java/net/lacolaco/smileessence/view/adapter/TimelineAdapter.java @@ -0,0 +1,39 @@ +package net.lacolaco.smileessence.view.adapter; + +import android.app.Activity; +import android.view.View; +import android.view.ViewGroup; +import net.lacolaco.smileessence.entity.Tweet; +import net.lacolaco.smileessence.view.Partials; + +import java.util.*; + +public class TimelineAdapter extends OrderedCustomListAdapter<Tweet> { + private final Activity activity; + + public TimelineAdapter(Activity activity) { + super(); + this.activity = activity; + } + + public long getLastID() { + if (getCount() > 0) { + return getItem(getCount() - 1).getId(); + } else { + return -1; + } + } + + public long getTopID() { + if (getCount() > 0) { + return getItem(0).getId(); + } else { + return -1; + } + } + + @Override + public View getView(int position, View convertView, ViewGroup parent) { + return Partials.getTweetView(getItem(position), activity, convertView, true); + } +} diff --git a/app/src/main/java/net/lacolaco/smileessence/view/adapter/UnorderedCustomListAdapter.java b/app/src/main/java/net/lacolaco/smileessence/view/adapter/UnorderedCustomListAdapter.java deleted file mode 100644 index 02f90bc2..00000000 --- a/app/src/main/java/net/lacolaco/smileessence/view/adapter/UnorderedCustomListAdapter.java +++ /dev/null @@ -1,88 +0,0 @@ -/* - * The MIT License (MIT) - * - * Copyright (c) 2012-2014 lacolaco.net - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in all - * copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - * SOFTWARE. - */ - -package net.lacolaco.smileessence.view.adapter; - -import android.app.Activity; -import net.lacolaco.smileessence.viewmodel.IViewModel; - -import java.util.ArrayList; -import java.util.Collections; -import java.util.List; -import java.util.ListIterator; - -public class UnorderedCustomListAdapter<T extends IViewModel> extends CustomListAdapter<T> { - - // ------------------------------ FIELDS ------------------------------ - - private final List<T> list = new ArrayList<>(); - - // --------------------------- CONSTRUCTORS --------------------------- - - public UnorderedCustomListAdapter(Activity activity) { - super(activity); - } - - // ------------------------ OVERRIDE METHODS ------------------------ - - @Override - protected synchronized List<T> getFrozenList() { - return Collections.unmodifiableList(new ArrayList<>(list)); - } - - // -------------------------- OTHER METHODS -------------------------- - - public synchronized void addItemToTop(T item) { - if (!list.contains(item)) { - list.add(0, item); - } - } - - public synchronized void addItemsToTop(List<T> items) { - ListIterator<T> iterator = items.listIterator(items.size()); - while (iterator.hasPrevious()) { - addItemToTop(iterator.previous()); - } - } - - public synchronized void addItemToBottom(T item) { - if (!list.contains(item)) { - list.add(item); - } - } - - public synchronized void addItemsToBottom(List<T> items) { - for (T item : items) { - addItemToBottom(item); - } - } - - public synchronized void clear() { - list.clear(); - } - - public synchronized boolean removeItem(T item) { - return list.remove(item); - } -} diff --git a/app/src/main/java/net/lacolaco/smileessence/view/adapter/UserListListAdapter.java b/app/src/main/java/net/lacolaco/smileessence/view/adapter/UserListListAdapter.java deleted file mode 100644 index 81e33d7e..00000000 --- a/app/src/main/java/net/lacolaco/smileessence/view/adapter/UserListListAdapter.java +++ /dev/null @@ -1,50 +0,0 @@ -/* - * The MIT License (MIT) - * - * Copyright (c) 2012-2014 lacolaco.net - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in all - * copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - * SOFTWARE. - */ - -package net.lacolaco.smileessence.view.adapter; - -import android.app.Activity; - -public class UserListListAdapter extends StatusListAdapter { - - // ------------------------------ FIELDS ------------------------------ - - private String listFullName; - - // --------------------------- CONSTRUCTORS --------------------------- - - public UserListListAdapter(Activity activity) { - super(activity); - } - - // --------------------- GETTER / SETTER METHODS --------------------- - - public String getListFullName() { - return listFullName; - } - - public void setListFullName(String listFullName) { - this.listFullName = listFullName; - } -} diff --git a/app/src/main/java/net/lacolaco/smileessence/view/dialog/AppInfoDialogFragment.java b/app/src/main/java/net/lacolaco/smileessence/view/dialog/AppInfoDialogFragment.java deleted file mode 100644 index 393bdd06..00000000 --- a/app/src/main/java/net/lacolaco/smileessence/view/dialog/AppInfoDialogFragment.java +++ /dev/null @@ -1,53 +0,0 @@ -/* - * The MIT License (MIT) - * - * Copyright (c) 2012-2014 lacolaco.net - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in all - * copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - * SOFTWARE. - */ - -package net.lacolaco.smileessence.view.dialog; - -import android.app.AlertDialog; -import android.app.Dialog; -import android.os.Bundle; -import android.view.LayoutInflater; -import android.view.View; -import android.widget.TextView; -import net.lacolaco.smileessence.BuildConfig; -import net.lacolaco.smileessence.R; - -public class AppInfoDialogFragment extends StackableDialogFragment { - - // ------------------------ OVERRIDE METHODS ------------------------ - - @Override - public Dialog onCreateDialog(Bundle savedInstanceState) { - LayoutInflater inflater = getActivity().getLayoutInflater(); - View contentView = inflater.inflate(R.layout.dialog_app_info, null); - TextView versionTextView = (TextView) contentView.findViewById(R.id.versionTextView); - versionTextView.setText(BuildConfig.VERSION_NAME + " (rev: " + BuildConfig.VERSION_CODE + "; upstream: " + getString(R.string.app_version_full) + ")"); - - return new AlertDialog.Builder(getActivity()) - .setTitle(R.string.dialog_title_about) - .setView(contentView) - .setPositiveButton(R.string.alert_dialog_ok, (dialog, which) -> dialog.dismiss()) - .create(); - } -} diff --git a/app/src/main/java/net/lacolaco/smileessence/view/dialog/EditTextDialogFragment.java b/app/src/main/java/net/lacolaco/smileessence/view/dialog/EditTextDialogFragment.java index 3ca6e175..8ce25145 100644 --- a/app/src/main/java/net/lacolaco/smileessence/view/dialog/EditTextDialogFragment.java +++ b/app/src/main/java/net/lacolaco/smileessence/view/dialog/EditTextDialogFragment.java @@ -26,12 +26,13 @@ package net.lacolaco.smileessence.view.dialog; import android.app.AlertDialog; import android.app.Dialog; +import android.app.DialogFragment; import android.os.Bundle; import android.view.View; import android.widget.EditText; import net.lacolaco.smileessence.R; -public abstract class EditTextDialogFragment extends StackableDialogFragment { +public abstract class EditTextDialogFragment extends DialogFragment { // ------------------------------ FIELDS ------------------------------ diff --git a/app/src/main/java/net/lacolaco/smileessence/view/dialog/MenuDialogFragment.java b/app/src/main/java/net/lacolaco/smileessence/view/dialog/MenuDialogFragment.java deleted file mode 100644 index 57491769..00000000 --- a/app/src/main/java/net/lacolaco/smileessence/view/dialog/MenuDialogFragment.java +++ /dev/null @@ -1,81 +0,0 @@ -/* - * The MIT License (MIT) - * - * Copyright (c) 2012-2014 lacolaco.net - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in all - * copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - * SOFTWARE. - */ - -package net.lacolaco.smileessence.view.dialog; - -import android.app.Activity; -import android.app.AlertDialog; -import android.app.Dialog; -import android.os.Bundle; -import android.view.View; -import android.widget.AdapterView; -import android.widget.ListView; -import net.lacolaco.smileessence.R; -import net.lacolaco.smileessence.command.Command; -import net.lacolaco.smileessence.command.IConfirmable; -import net.lacolaco.smileessence.view.adapter.UnorderedCustomListAdapter; - -import java.util.List; - -public abstract class MenuDialogFragment extends StackableDialogFragment implements AdapterView.OnItemClickListener { - @Override - public Dialog onCreateDialog(Bundle savedInstanceState) { - View body = setupView(); - - return new AlertDialog.Builder(getActivity()).setView(body).create(); - } - - protected abstract List<Command> getMenuCommands(); - - protected void executeCommand(Command command) { - dismiss(); - command.execute(); - } - - protected View setupView() { - final Activity activity = getActivity(); - View body = activity.getLayoutInflater().inflate(R.layout.dialog_menu_list, null); - ListView listView = (ListView) body.findViewById(R.id.listview_dialog_menu_list); - - final UnorderedCustomListAdapter<Command> adapter = new UnorderedCustomListAdapter<>(activity); - listView.setAdapter(adapter); - listView.setOnItemClickListener(this); - adapter.addItemsToBottom(getMenuCommands()); - adapter.updateForce(); - - return body; - } - - @Override - public void onItemClick(AdapterView<?> parent, View view, int position, long id) { - final Command command = (Command) parent.getItemAtPosition(position); - if (command != null) { - if (command instanceof IConfirmable) { - ConfirmDialogFragment.show(getActivity(), getString(R.string.dialog_confirm_commands), () -> executeCommand(command)); - } else { - executeCommand(command); - } - } - } -} diff --git a/app/src/main/java/net/lacolaco/smileessence/view/dialog/MessageDetailDialogFragment.java b/app/src/main/java/net/lacolaco/smileessence/view/dialog/MessageDetailDialogFragment.java index ab140c12..8383363c 100644 --- a/app/src/main/java/net/lacolaco/smileessence/view/dialog/MessageDetailDialogFragment.java +++ b/app/src/main/java/net/lacolaco/smileessence/view/dialog/MessageDetailDialogFragment.java @@ -24,46 +24,35 @@ package net.lacolaco.smileessence.view.dialog; -import android.app.Activity; import android.app.AlertDialog; import android.app.Dialog; import android.graphics.drawable.ColorDrawable; import android.os.Bundle; import android.view.View; +import android.view.ViewGroup; import android.widget.ImageButton; import android.widget.ListView; -import net.lacolaco.smileessence.Application; import net.lacolaco.smileessence.R; import net.lacolaco.smileessence.activity.MainActivity; import net.lacolaco.smileessence.command.Command; import net.lacolaco.smileessence.command.CommandAddHashtag; import net.lacolaco.smileessence.command.CommandOpenURL; import net.lacolaco.smileessence.command.CommandOpenUserDetail; -import net.lacolaco.smileessence.data.Account; import net.lacolaco.smileessence.entity.DirectMessage; -import net.lacolaco.smileessence.notification.Notificator; import net.lacolaco.smileessence.twitter.task.Messages; +import net.lacolaco.smileessence.util.SystemServiceHelper; import net.lacolaco.smileessence.view.DialogHelper; +import net.lacolaco.smileessence.view.Partials; +import net.lacolaco.smileessence.view.adapter.CustomListAdapter; import net.lacolaco.smileessence.view.adapter.MessageListAdapter; -import net.lacolaco.smileessence.view.adapter.UnorderedCustomListAdapter; -import net.lacolaco.smileessence.viewmodel.MessageViewModel; import java.util.ArrayList; import java.util.List; public class MessageDetailDialogFragment extends StackableDialogFragment implements View.OnClickListener { - - // ------------------------------ FIELDS ------------------------------ - private static final String KEY_MESSAGE_ID = "messageID"; private DirectMessage message; - // --------------------- GETTER / SETTER METHODS --------------------- - - public long getMessageID() { - return getArguments().getLong(KEY_MESSAGE_ID); - } - public void setMessageID(long messageID) { Bundle args = new Bundle(); args.putLong(KEY_MESSAGE_ID, messageID); @@ -96,18 +85,11 @@ public class MessageDetailDialogFragment extends StackableDialogFragment impleme } } - // ------------------------ OVERRIDE METHODS ------------------------ - - @Override - public void onCreate(Bundle savedInstanceState) { - super.onCreate(savedInstanceState); - message = DirectMessage.fetch(getMessageID()); - } - @Override public Dialog onCreateDialog(Bundle savedInstanceState) { + message = DirectMessage.fetch(getArguments().getLong(KEY_MESSAGE_ID)); if (message == null) { - Notificator.getInstance().alert(R.string.notice_error_get_messages); + getWorld().notifyError(R.string.notice_error_get_messages); return new DisposeDialog(getActivity()); } @@ -118,17 +100,18 @@ public class MessageDetailDialogFragment extends StackableDialogFragment impleme // TODO: 効率的な探索どうする DirectMessage replyTo = null; - for (DirectMessage mes : DirectMessage.cached()) { - if (message.getId() > mes.getId() && - message.getRecipient() == mes.getSender() && - message.getSender() == mes.getRecipient() && - (replyTo == null || replyTo.getId() < mes.getId())) { - replyTo = mes; - } - } + // FIXME + // for (DirectMessage mes : DirectMessage.cached()) { + // if (message.getId() > mes.getId() && + // message.getRecipient() == mes.getSender() && + // message.getSender() == mes.getRecipient() && + // (replyTo == null || replyTo.getId() < mes.getId())) { + // replyTo = mes; + // } + // } if (replyTo != null) { listView.setVisibility(View.VISIBLE); - adapter.addItem(new MessageViewModel(replyTo)); + adapter.add(replyTo); adapter.updateForce(); } else { listView.setVisibility(View.GONE); @@ -141,18 +124,16 @@ public class MessageDetailDialogFragment extends StackableDialogFragment impleme private void deleteMessage() { ConfirmDialogFragment.show(getActivity(), getString(R.string.dialog_confirm_commands), () -> { - new Messages.DestroyTask(Application.getInstance().getCurrentAccount(), message.getId()) - .onDone(x -> Notificator.getInstance().publish(R.string.notice_message_delete_succeeded)) - .onFail(x -> Notificator.getInstance().alert(R.string.notice_message_delete_failed)) + new Messages.DestroyTask(getWorld().getAccount(), message.getId()) + .onDone(x -> getWorld().notify(R.string.notice_message_delete_succeeded)) + .onFail(x -> getWorld().notifyError(R.string.notice_message_delete_failed)) .execute(); dismiss(); }); } private void openSendMessageDialog() { - SendMessageDialogFragment dialogFragment = new SendMessageDialogFragment(); - dialogFragment.setScreenName(message.getSender().getScreenName()); - DialogHelper.showDialog(getActivity(), dialogFragment); + DialogHelper.showDialog(getActivity(), SendMessageDialogFragment.newInstance(message.getSender())); } private View getTitleView() { @@ -160,8 +141,7 @@ public class MessageDetailDialogFragment extends StackableDialogFragment impleme View view = activity.getLayoutInflater().inflate(R.layout.dialog_status_detail, null); - MessageViewModel statusViewModel = new MessageViewModel(message); - View messageHeader = statusViewModel.getView(activity, activity.getLayoutInflater(), view.findViewById(R.id.layout_status_header)); + View messageHeader = Partials.getDirectMessageView(message, activity, view.findViewById(R.id.layout_status_header)); messageHeader.setClickable(false); view.setBackgroundColor(((ColorDrawable) messageHeader.getBackground()).getColor()); @@ -179,19 +159,16 @@ public class MessageDetailDialogFragment extends StackableDialogFragment impleme } private void updateViewButtons(View view) { - Account account = Application.getInstance().getCurrentAccount(); - //--- buttons ImageButton reply = (ImageButton) view.findViewById(R.id.button_status_detail_reply); reply.setOnClickListener(this); ImageButton delete = (ImageButton) view.findViewById(R.id.button_status_detail_delete); delete.setOnClickListener(this); - delete.setVisibility(account.canDelete(message) ? View.VISIBLE : View.GONE); + delete.setVisibility(View.VISIBLE); } private void updateViewMenu(View view) { - MainActivity activity = ((MainActivity) getActivity()); // -- menu dialog ImageButton menu = (ImageButton) view.findViewById(R.id.button_status_detail_menu); menu.setOnClickListener(this); @@ -203,8 +180,18 @@ public class MessageDetailDialogFragment extends StackableDialogFragment impleme if (commands.size() > 0) { divider.setVisibility(View.VISIBLE); listView.setVisibility(View.VISIBLE); - final UnorderedCustomListAdapter<Command> adapter = new UnorderedCustomListAdapter<>(activity); - adapter.addItemsToBottom(commands); + final CustomListAdapter<Command> adapter = new CustomListAdapter<Command>() { + + @Override + public View getView(int position, View convertView, ViewGroup parent) { + return null; + } + + @Override + protected List<Command> getList() { + return commands; + } + }; adapter.updateForce(); listView.setAdapter(adapter); listView.setOnItemClickListener((parent, view1, position, id) -> { @@ -218,7 +205,7 @@ public class MessageDetailDialogFragment extends StackableDialogFragment impleme } private List<Command> getCommands() { - Activity activity = getActivity(); + MainActivity activity = (MainActivity) getActivity(); List<Command> commands = new ArrayList<>(); // Mentions if (message.getSender() != message.getRecipient()) { @@ -241,8 +228,19 @@ public class MessageDetailDialogFragment extends StackableDialogFragment impleme } private void openMenu() { - MessageMenuDialogFragment fragment = new MessageMenuDialogFragment(); - fragment.setMessageID(getMessageID()); - DialogHelper.showDialog(getActivity(), fragment); + AlertDialog.Builder builder = new AlertDialog.Builder(getActivity()); + builder.setTitle("@" + message.getSender().getScreenName() + ": " + message.getText()) + .setItems(R.array.message_commands, (dialog, which) -> { + switch (which) { + case 0: + SystemServiceHelper.copyToClipboard(getActivity(), "message text", message.getText()); + getWorld().notify(R.string.notice_copy_clipboard); + break; + default: + throw new IllegalStateException(); + } + }); + AlertDialog dialog = builder.create(); + dialog.show(); } } diff --git a/app/src/main/java/net/lacolaco/smileessence/view/dialog/MessageMenuDialogFragment.java b/app/src/main/java/net/lacolaco/smileessence/view/dialog/MessageMenuDialogFragment.java deleted file mode 100644 index c3bcbe16..00000000 --- a/app/src/main/java/net/lacolaco/smileessence/view/dialog/MessageMenuDialogFragment.java +++ /dev/null @@ -1,66 +0,0 @@ -/* - * The MIT License (MIT) - * - * Copyright (c) 2012-2014 lacolaco.net - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in all - * copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - * SOFTWARE. - */ - -package net.lacolaco.smileessence.view.dialog; - -import android.app.Activity; -import android.os.Bundle; -import net.lacolaco.smileessence.command.Command; -import net.lacolaco.smileessence.entity.DirectMessage; - -import java.util.List; - -public class MessageMenuDialogFragment extends MenuDialogFragment { - - // ------------------------------ FIELDS ------------------------------ - - private static final String KEY_MESSAGE_ID = "messageID"; - private DirectMessage message; - - // --------------------- GETTER / SETTER METHODS --------------------- - - public long getMessageID() { - return getArguments().getLong(KEY_MESSAGE_ID); - } - - public void setMessageID(long messageID) { - Bundle args = new Bundle(); - args.putLong(KEY_MESSAGE_ID, messageID); - setArguments(args); - } - - // ------------------------ OVERRIDE METHODS ------------------------ - - @Override - public void onCreate(Bundle savedInstanceState) { - super.onCreate(savedInstanceState); - message = DirectMessage.fetch(getMessageID()); - } - - @Override - protected List<Command> getMenuCommands() { - Activity activity = getActivity(); - return Command.getMessageCommands(activity, message); - } -} diff --git a/app/src/main/java/net/lacolaco/smileessence/view/dialog/SelectSearchQueryDialogFragment.java b/app/src/main/java/net/lacolaco/smileessence/view/dialog/SelectSearchQueryDialogFragment.java deleted file mode 100644 index 9a897f8f..00000000 --- a/app/src/main/java/net/lacolaco/smileessence/view/dialog/SelectSearchQueryDialogFragment.java +++ /dev/null @@ -1,93 +0,0 @@ -/* - * The MIT License (MIT) - * - * Copyright (c) 2012-2014 lacolaco.net - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in all - * copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - * SOFTWARE. - */ - -package net.lacolaco.smileessence.view.dialog; - -import android.app.Activity; -import android.app.AlertDialog; -import android.app.Dialog; -import android.os.Bundle; -import android.view.View; -import android.widget.AdapterView; -import android.widget.ListView; -import net.lacolaco.smileessence.Application; -import net.lacolaco.smileessence.R; -import net.lacolaco.smileessence.command.Command; -import net.lacolaco.smileessence.command.CommandOpenSearch; -import net.lacolaco.smileessence.entity.SavedSearch; -import net.lacolaco.smileessence.notification.Notificator; -import net.lacolaco.smileessence.twitter.task.Searches; -import net.lacolaco.smileessence.view.adapter.UnorderedCustomListAdapter; - -import java.util.ArrayList; -import java.util.List; - -public class SelectSearchQueryDialogFragment extends MenuDialogFragment implements AdapterView.OnItemLongClickListener { - - // --------------------- Interface OnItemLongClickListener --------------------- - - @Override - public boolean onItemLongClick(AdapterView<?> parent, View view, int position, long id) { - final CommandOpenSearch command = (CommandOpenSearch) parent.getItemAtPosition(position); - @SuppressWarnings("unchecked") final UnorderedCustomListAdapter<Command> adapter = (UnorderedCustomListAdapter<Command>) parent.getAdapter(); - - ConfirmDialogFragment.show(getActivity(), getString(R.string.dialog_confirm_delete_query), () -> { - adapter.removeItem(command); - adapter.update(); - new Searches.DestroySavedSearchTask(Application.getInstance().getCurrentAccount(), command.getQuery().getId()) - .onDoneUI(x -> { - Notificator.getInstance().publish(R.string.notice_search_query_deleted); - Application.getInstance().getCurrentAccount().refreshSavedSearches(); - }) - .onFailUI(x -> Notificator.getInstance().publish("unable to delete search query")) - .execute(); - }, false); - - return true; - } - - // ------------------------ OVERRIDE METHODS ------------------------ - - @Override - protected List<Command> getMenuCommands() { - Activity activity = getActivity(); - List<Command> commands = new ArrayList<>(); - for (SavedSearch query : SavedSearch.cached()) { - commands.add(new CommandOpenSearch(activity, query)); - } - return commands; - } - - @Override - public Dialog onCreateDialog(Bundle savedInstanceState) { - View body = setupView(); - ListView listView = (ListView) body.findViewById(R.id.listview_dialog_menu_list); - listView.setOnItemLongClickListener(this); - - return new AlertDialog.Builder(getActivity()) - .setView(body) - .setTitle(R.string.dialog_title_select_search_query) - .create(); - } -} diff --git a/app/src/main/java/net/lacolaco/smileessence/view/dialog/SelectUserListDialogFragment.java b/app/src/main/java/net/lacolaco/smileessence/view/dialog/SelectUserListDialogFragment.java deleted file mode 100644 index 3d1c276a..00000000 --- a/app/src/main/java/net/lacolaco/smileessence/view/dialog/SelectUserListDialogFragment.java +++ /dev/null @@ -1,58 +0,0 @@ -/* - * The MIT License (MIT) - * - * Copyright (c) 2012-2014 lacolaco.net - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in all - * copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - * SOFTWARE. - */ - -package net.lacolaco.smileessence.view.dialog; - -import android.app.Activity; -import android.app.Dialog; -import android.os.Bundle; -import net.lacolaco.smileessence.Application; -import net.lacolaco.smileessence.R; -import net.lacolaco.smileessence.command.Command; -import net.lacolaco.smileessence.command.CommandOpenUserList; - -import java.util.ArrayList; -import java.util.List; - -public class SelectUserListDialogFragment extends MenuDialogFragment { - - // ------------------------ OVERRIDE METHODS ------------------------ - - @Override - protected List<Command> getMenuCommands() { - Activity activity = getActivity(); - List<Command> commands = new ArrayList<>(); - for (String fullName : Application.getInstance().getCurrentAccount().getListSubscriptions()) { - commands.add(new CommandOpenUserList(activity, fullName)); - } - return commands; - } - - @Override - public Dialog onCreateDialog(Bundle savedInstanceState) { - Dialog dialog = super.onCreateDialog(savedInstanceState); - dialog.setTitle(R.string.dialog_title_select_userlist); - return dialog; - } -} diff --git a/app/src/main/java/net/lacolaco/smileessence/view/dialog/SendMessageDialogFragment.java b/app/src/main/java/net/lacolaco/smileessence/view/dialog/SendMessageDialogFragment.java index 7f165fea..20917d8f 100644 --- a/app/src/main/java/net/lacolaco/smileessence/view/dialog/SendMessageDialogFragment.java +++ b/app/src/main/java/net/lacolaco/smileessence/view/dialog/SendMessageDialogFragment.java @@ -39,34 +39,24 @@ import android.widget.TextView; import com.twitter.Validator; import net.lacolaco.smileessence.Application; import net.lacolaco.smileessence.R; -import net.lacolaco.smileessence.data.PostState; -import net.lacolaco.smileessence.notification.Notificator; +import net.lacolaco.smileessence.entity.User; import net.lacolaco.smileessence.twitter.task.Messages; import net.lacolaco.smileessence.util.SystemServiceHelper; public class SendMessageDialogFragment extends StackableDialogFragment implements TextWatcher, View.OnClickListener { - - // ------------------------------ FIELDS ------------------------------ - - private static final String screenNameKey = "screenName"; - private String screenName; + private static final String KEY_RECIPIENT_ID = "KEY_RECIPIENT_ID"; + private User recipient; private EditText editText; private TextView textViewCount; private Button buttonSend; - // --------------------- GETTER / SETTER METHODS --------------------- - - public void setScreenName(String screenName) { + public static SendMessageDialogFragment newInstance(User recipient) { + SendMessageDialogFragment obj = new SendMessageDialogFragment(); Bundle args = new Bundle(); - args.putString(screenNameKey, screenName); - setArguments(args); + args.putLong(KEY_RECIPIENT_ID, recipient.getId()); + obj.setArguments(args); + return obj; } - - // ------------------------ INTERFACE METHODS ------------------------ - - - // --------------------- Interface OnClickListener --------------------- - @Override public void onClick(View v) { int id = v.getId(); @@ -81,8 +71,6 @@ public class SendMessageDialogFragment extends StackableDialogFragment implement } } - // --------------------- Interface TextWatcher --------------------- - @Override public void beforeTextChanged(CharSequence s, int start, int count, int after) { @@ -92,9 +80,6 @@ public class SendMessageDialogFragment extends StackableDialogFragment implement public void onTextChanged(CharSequence s, int start, int before, int count) { Validator validator = new Validator(); int remainingCount = 140 - validator.getTweetLength(s.toString()); - if (!TextUtils.isEmpty(PostState.getState().getMediaFilePath())) { - remainingCount -= validator.getShortUrlLength(); - } textViewCount.setText(String.valueOf(remainingCount)); if (remainingCount == 140 || remainingCount < 0) { textViewCount.setTextColor(ContextCompat.getColor(getActivity(), R.color.red)); @@ -108,20 +93,12 @@ public class SendMessageDialogFragment extends StackableDialogFragment implement } - // ------------------------ OVERRIDE METHODS ------------------------ - - @Override - public void onCreate(Bundle savedInstanceState) { - super.onCreate(savedInstanceState); - Bundle args = getArguments(); - screenName = args.getString(screenNameKey); - } - @Override public Dialog onCreateDialog(Bundle savedInstanceState) { + recipient = User.fetch(getArguments().getLong(KEY_RECIPIENT_ID)); View view = getActivity().getLayoutInflater().inflate(R.layout.dialog_send_message, null); TextView textViewName = (TextView) view.findViewById(R.id.textview_send_message_name); - textViewName.setText("To: @" + screenName); + textViewName.setText("To: @" + recipient.getScreenName()); textViewCount = (TextView) view.findViewById(R.id.textview_send_message_count); editText = (EditText) view.findViewById(R.id.edittext_send_message); editText.addTextChangedListener(this); @@ -142,12 +119,13 @@ public class SendMessageDialogFragment extends StackableDialogFragment implement private void sendMessage() { SystemServiceHelper.hideIM(getActivity(), editText); String text = editText.getText().toString(); - new Messages.CreateTask(Application.getInstance().getCurrentAccount(), screenName, text) + new Messages.CreateTask(getWorld().getAccount(), recipient.getId(), text) .onDoneUI(m -> { - Notificator.getInstance().publish(R.string.notice_message_send_succeeded); + getWorld().addDirectMessage(m); + getWorld().notify(R.string.notice_message_send_succeeded); dismiss(); }) - .onFail(e -> Notificator.getInstance().alert(R.string.notice_message_send_failed, e)) + .onFail(e -> getWorld().notifyError(R.string.notice_message_send_failed, e)) .execute(); } } diff --git a/app/src/main/java/net/lacolaco/smileessence/view/dialog/StackableDialogFragment.java b/app/src/main/java/net/lacolaco/smileessence/view/dialog/StackableDialogFragment.java index 427c4884..848c6465 100644 --- a/app/src/main/java/net/lacolaco/smileessence/view/dialog/StackableDialogFragment.java +++ b/app/src/main/java/net/lacolaco/smileessence/view/dialog/StackableDialogFragment.java @@ -1,9 +1,13 @@ package net.lacolaco.smileessence.view.dialog; import android.app.DialogFragment; -import net.lacolaco.smileessence.Application; +import net.lacolaco.smileessence.World; +import net.lacolaco.smileessence.activity.MainActivity; import net.lacolaco.smileessence.view.DialogHelper; +/** + * Only used by MainActivity. + */ public class StackableDialogFragment extends DialogFragment { @Override public void dismiss() { @@ -16,4 +20,9 @@ public class StackableDialogFragment extends DialogFragment { super.dismissAllowingStateLoss(); DialogHelper.unregisterDialog(getTag()); } + + protected World getWorld() { + final MainActivity activity = (MainActivity) getActivity(); + return activity.getWorld(); + } } diff --git a/app/src/main/java/net/lacolaco/smileessence/view/dialog/StatusDetailDialogFragment.java b/app/src/main/java/net/lacolaco/smileessence/view/dialog/StatusDetailDialogFragment.java index 7d2e5dbd..5b2ee58c 100644 --- a/app/src/main/java/net/lacolaco/smileessence/view/dialog/StatusDetailDialogFragment.java +++ b/app/src/main/java/net/lacolaco/smileessence/view/dialog/StatusDetailDialogFragment.java @@ -24,12 +24,12 @@ package net.lacolaco.smileessence.view.dialog; -import android.app.Activity; import android.app.AlertDialog; import android.app.Dialog; import android.graphics.drawable.ColorDrawable; import android.os.Bundle; import android.view.View; +import android.view.ViewGroup; import android.widget.ImageButton; import android.widget.ImageView; import android.widget.ListView; @@ -42,18 +42,19 @@ import net.lacolaco.smileessence.command.CommandAddHashtag; import net.lacolaco.smileessence.command.CommandOpenURL; import net.lacolaco.smileessence.command.CommandOpenUserDetail; import net.lacolaco.smileessence.data.Account; -import net.lacolaco.smileessence.data.PostState; import net.lacolaco.smileessence.entity.RBinding; import net.lacolaco.smileessence.entity.Tweet; -import net.lacolaco.smileessence.notification.Notificator; +import net.lacolaco.smileessence.preference.UserPreferenceHelper; import net.lacolaco.smileessence.twitter.task.TweetReactions; import net.lacolaco.smileessence.twitter.task.Tweets; +import net.lacolaco.smileessence.util.IntentUtils; +import net.lacolaco.smileessence.util.SystemServiceHelper; import net.lacolaco.smileessence.util.UIObserverBundle; import net.lacolaco.smileessence.view.DialogHelper; +import net.lacolaco.smileessence.view.Partials; import net.lacolaco.smileessence.view.ToggleableImageButton; -import net.lacolaco.smileessence.view.adapter.StatusListAdapter; -import net.lacolaco.smileessence.view.adapter.UnorderedCustomListAdapter; -import net.lacolaco.smileessence.viewmodel.StatusViewModel; +import net.lacolaco.smileessence.view.adapter.CustomListAdapter; +import net.lacolaco.smileessence.view.adapter.TimelineAdapter; import java.lang.ref.WeakReference; import java.util.ArrayList; @@ -61,50 +62,117 @@ import java.util.LinkedHashSet; import java.util.List; public class StatusDetailDialogFragment extends StackableDialogFragment implements View.OnClickListener { - - // ------------------------------ FIELDS ------------------------------ - - private static final String KEY_STATUS_ID = "statusID"; + private static final String KEY_STATUS_ID = "status_id"; private Tweet tweet; - // --------------------- GETTER / SETTER METHODS --------------------- - - public long getStatusID() { - return getArguments().getLong(KEY_STATUS_ID); - } - - public void setStatusID(long statusID) { + public static StatusDetailDialogFragment newInstance(Tweet tweet) { + StatusDetailDialogFragment obj = new StatusDetailDialogFragment(); Bundle args = new Bundle(); - args.putLong(KEY_STATUS_ID, statusID); - setArguments(args); + args.putLong(KEY_STATUS_ID, tweet.getId()); + obj.setArguments(args); + return obj; } - // ------------------------ INTERFACE METHODS ------------------------ - - - // --------------------- Interface OnClickListener --------------------- - @Override public void onClick(final View v) { switch (v.getId()) { case R.id.button_status_detail_reply: { - replyToStatus(); + Tweet originalTweet = tweet.getOriginalTweet(); + + StringBuilder builder = new StringBuilder(); + builder.append("@" + originalTweet.getUser().getScreenName() + " "); + + for (String screenName : originalTweet.getMentions()) { + if (!screenName.equals(getWorld().getAccount().getUser().getScreenName())) + builder.append("@" + screenName + " "); + } + String text = builder.toString(); + int selStart = originalTweet.getUser().getScreenName().length() + 2; // "@" and " " + + getWorld().getPostState().beginTransaction() + .clear() + .insertText(0, text) + .setInReplyTo(originalTweet) + .setSelection(selStart, text.length()) + .commitWithOpen((MainActivity) getActivity()); break; } case R.id.button_status_detail_retweet: { - toggleRetweet(); + Account account = getWorld().getAccount(); + confirm(() -> { + if (tweet.isRetweetedBy(account.getUserId())) { + new Tweets.DestroyTask(account, tweet.getRetweetIdBy(account.getUserId())) + .onDone(t -> getWorld().notify(R.string.notice_status_delete_succeeded)) + .onFail(e -> getWorld().notifyError(R.string.notice_status_delete_failed)) + .execute(); + dismiss(); + } else { + new TweetReactions.RetweetTask(account, tweet.getId()) + .onDone(x -> getWorld().notify(R.string.notice_retweet_succeeded)) + .onFail(x -> getWorld().notifyError(R.string.notice_retweet_failed)) + .execute(); + } + }); break; } case R.id.button_status_detail_favorite: { - toggleFavorite(); + Account account = getWorld().getAccount(); + if (tweet.isFavoritedBy(account.getUserId())) { + new TweetReactions.UnfavoriteTask(account, tweet.getId()) + .onDone(x -> getWorld().notify(R.string.notice_unfavorite_succeeded)) + .onFail(x -> getWorld().notifyError(R.string.notice_unfavorite_failed)) + .execute(); + } else { + new TweetReactions.FavoriteTask(account, tweet.getId()) + .onDone(x -> getWorld().notify(R.string.notice_favorite_succeeded)) + .onFail(x -> getWorld().notifyError(R.string.notice_favorite_failed)) + .execute(); + } break; } case R.id.button_status_detail_delete: { - deleteStatus(); + confirm(() -> { + new Tweets.DestroyTask(getWorld().getAccount(), tweet.getOriginalTweet().getId()) + .onDone(t -> getWorld().notify(R.string.notice_status_delete_succeeded)) + .onFail(e -> getWorld().notifyError(R.string.notice_status_delete_failed)) + .execute(); + dismiss(); + }); break; } case R.id.button_status_detail_menu: { - openMenu(); + AlertDialog.Builder builder = new AlertDialog.Builder(getActivity()); + builder.setTitle("@" + tweet.getUser().getScreenName() + ": " + tweet.getText()) + .setItems(R.array.status_commands, (dialog, which) -> { + switch (which) { + case 0: + String text = String.format("@%s ", tweet.getOriginalTweet().getUser().getScreenName()); + getWorld().getPostState().beginTransaction().insertText(0, text).moveCursor(text.length()).commit(); + getWorld().notify(R.string.notice_add_to_reply); + break; + case 1: + TalkChainDialogFragment dialogFragment = new TalkChainDialogFragment(); + dialogFragment.setStatusID(tweet.getOriginalTweet().getId()); + DialogHelper.showDialog(getActivity(), dialogFragment); + break; + case 2: + IntentUtils.openUri(getActivity(), tweet.getOriginalTweet().getTwitterUrl()); + break; + case 3: + SystemServiceHelper.copyToClipboard(getActivity(), "tweet text", tweet.getOriginalTweet().getText()); + getWorld().notify(R.string.notice_copy_clipboard); + break; + case 4: + String statusURL = tweet.getOriginalTweet().getTwitterUrl(); + SystemServiceHelper.copyToClipboard(getActivity(), "tweet url", statusURL); + getWorld().notify(R.string.notice_copy_clipboard); + break; + default: + throw new IllegalStateException(); + } + }); + AlertDialog dialog = builder.create(); + dialog.show(); break; } default: { @@ -113,62 +181,25 @@ public class StatusDetailDialogFragment extends StackableDialogFragment implemen } } - // ------------------------ OVERRIDE METHODS ------------------------ - - @Override - public void onCreate(Bundle savedInstanceState) { - super.onCreate(savedInstanceState); - tweet = Tweet.fetch(getStatusID()); - } - @Override public Dialog onCreateDialog(Bundle savedInstanceState) { + tweet = Tweet.fetch(getArguments().getLong(KEY_STATUS_ID)); if (tweet == null) { // trying to open deleted tweet? - Notificator.getInstance().publish(R.string.notice_error_show_status); + getWorld().notifyError(R.string.notice_error_show_status); return new DisposeDialog(getActivity()); } - Account account = Application.getInstance().getCurrentAccount(); - - View header = getTitleView(); - - ListView listView = (ListView) header.findViewById(R.id.listview_status_detail_reply_to); - final StatusListAdapter adapter = new StatusListAdapter(getActivity()); - listView.setAdapter(adapter); - - View replyDivider = header.findViewById(R.id.detail_dialog_divider_top); - - if (tweet.getInReplyToStatusId() != -1) { - replyDivider.setVisibility(View.VISIBLE); - listView.setVisibility(View.VISIBLE); - Tweet.fetchTask(tweet.getInReplyToStatusId(), account) - .onDoneUI(replyTo -> { - adapter.addItem(new StatusViewModel(replyTo)); - adapter.update(); - }) - .execute(); - } else { - replyDivider.setVisibility(View.GONE); - listView.setVisibility(View.GONE); - } - - return new AlertDialog.Builder(getActivity()).setView(header).create(); - } - - private View getTitleView() { - MainActivity activity = ((MainActivity) getActivity()); - - View view = activity.getLayoutInflater().inflate(R.layout.dialog_status_detail, null); + View view = getActivity().getLayoutInflater().inflate(R.layout.dialog_status_detail, null); UIObserverBundle bundle = new UIObserverBundle(); view.setTag(bundle); - View statusHeader = new StatusViewModel(tweet).getView(activity, activity.getLayoutInflater(), view.findViewById(R.id.layout_status_header)); + View statusHeader = Partials.getTweetView(tweet, getActivity(), view.findViewById(R.id.layout_status_header), true); statusHeader.setClickable(false); view.setBackgroundColor(((ColorDrawable) statusHeader.getBackground()).getColor()); updateViewReactions(view); updateViewButtons(view); - updateViewMenu(view); + setupViewMenu(view); final WeakReference<View> weakView = new WeakReference<>(view); bundle.attach(tweet.getOriginalTweet(), changes -> { @@ -181,11 +212,30 @@ public class StatusDetailDialogFragment extends StackableDialogFragment implemen } }); - return view; + ListView listView = (ListView) view.findViewById(R.id.listview_status_detail_reply_to); + final TimelineAdapter adapter = new TimelineAdapter(getActivity()); + listView.setAdapter(adapter); + + View replyDivider = view.findViewById(R.id.detail_dialog_divider_top); + + if (tweet.getInReplyToStatusId() != -1) { + replyDivider.setVisibility(View.VISIBLE); + listView.setVisibility(View.VISIBLE); + Tweet.fetchTask(tweet.getInReplyToStatusId(), getWorld().getAccount()) + .onDoneUI(replyTo -> { + adapter.add(replyTo); + adapter.update(); + }) + .execute(); + } else { + replyDivider.setVisibility(View.GONE); + listView.setVisibility(View.GONE); + } + + return new AlertDialog.Builder(getActivity()).setView(view).create(); } private void updateViewReactions(View view) { - //--- favs/RTs count ImageView favCountIcon = (ImageView) view.findViewById(R.id.image_status_detail_fav_count); TextView favCountText = (TextView) view.findViewById(R.id.textview_status_detail_fav_count); if (tweet.getFavoriteCount() > 0) { @@ -210,7 +260,7 @@ public class StatusDetailDialogFragment extends StackableDialogFragment implemen } private void updateViewButtons(View view) { - Account account = Application.getInstance().getCurrentAccount(); + Account account = getWorld().getAccount(); //--- buttons ImageButton reply = (ImageButton) view.findViewById(R.id.button_status_detail_reply); @@ -226,25 +276,37 @@ public class StatusDetailDialogFragment extends StackableDialogFragment implemen ImageButton delete = (ImageButton) view.findViewById(R.id.button_status_detail_delete); delete.setOnClickListener(this); - delete.setVisibility(account.canDelete(tweet) ? View.VISIBLE : View.GONE); - } + delete.setVisibility(tweet.getOriginalTweet().getUser() == account.getUser() ? View.VISIBLE : View.GONE); - private void updateViewMenu(View view) { - MainActivity activity = ((MainActivity) getActivity()); - // -- menu dialog ImageButton menu = (ImageButton) view.findViewById(R.id.button_status_detail_menu); menu.setOnClickListener(this); + } - // -- menu embedded in dialog + private void setupViewMenu(View view) { View divider = view.findViewById(R.id.detail_dialog_divider_bottom); ListView listView = (ListView) view.findViewById(R.id.listview_status_detail_menu); List<Command> commands = getCommands(); if (commands.size() > 0) { divider.setVisibility(View.VISIBLE); listView.setVisibility(View.VISIBLE); - final UnorderedCustomListAdapter<Command> adapter = new UnorderedCustomListAdapter<>(activity); - adapter.addItemsToBottom(commands); - adapter.updateForce(); + final CustomListAdapter<Command> adapter = new CustomListAdapter<Command>() { + @Override + public View getView(int position, View convertView, ViewGroup parent) { + if (convertView == null) { + convertView = getActivity().getLayoutInflater().inflate(R.layout.menu_item_simple_text, null); + } + TextView textView = (TextView) convertView.findViewById(R.id.list_item_textview); + textView.setTextSize(UserPreferenceHelper.getInstance().getTextSize()); + textView.setText(getItem(position).getText()); + return convertView; + } + + @Override + protected List<Command> getList() { + return commands; + } + }; + adapter.update(); listView.setAdapter(adapter); listView.setOnItemClickListener((parent, view1, position, id) -> { Command command = (Command) parent.getItemAtPosition(position); @@ -260,20 +322,8 @@ public class StatusDetailDialogFragment extends StackableDialogFragment implemen ConfirmDialogFragment.show(getActivity(), getString(R.string.dialog_confirm_commands), onYes); } - private void deleteStatus() { - confirm(() -> { - Account account = Application.getInstance().getCurrentAccount(); - - new Tweets.DestroyTask(account, tweet.getOriginalTweet().getId()) - .onDone(t -> Notificator.getInstance().publish(R.string.notice_status_delete_succeeded)) - .onFail(e -> Notificator.getInstance().alert(R.string.notice_status_delete_failed)) - .execute(); - dismiss(); - }); - } - private List<Command> getCommands() { - Activity activity = getActivity(); + MainActivity activity = (MainActivity) getActivity(); ArrayList<Command> commands = new ArrayList<>(); // Retweeter if (tweet.getRetweetedTweet() != null && tweet.getUser() != tweet.getRetweetedTweet().getUser()) @@ -295,64 +345,4 @@ public class StatusDetailDialogFragment extends StackableDialogFragment implemen } return commands; } - - private void openMenu() { - StatusMenuDialogFragment fragment = new StatusMenuDialogFragment(); - fragment.setStatusID(getStatusID()); - DialogHelper.showDialog(getActivity(), fragment); - } - - private void replyToStatus() { - Account account = Application.getInstance().getCurrentAccount(); - Tweet originalTweet = tweet.getOriginalTweet(); - - StringBuilder builder = new StringBuilder(); - builder.append("@" + originalTweet.getUser().getScreenName() + " "); - - for (String screenName : originalTweet.getMentions()) { - if (!screenName.equals(account.getUser().getScreenName())) - builder.append("@" + screenName + " "); - } - String text = builder.toString(); - int selStart = originalTweet.getUser().getScreenName().length() + 2; // "@" and " " - - PostState.newState().beginTransaction() - .insertText(0, text) - .setInReplyTo(originalTweet) - .setSelection(selStart, text.length()) - .commitWithOpen((MainActivity) getActivity()); - } - - private void toggleFavorite() { - Account account = Application.getInstance().getCurrentAccount(); - if (tweet.isFavoritedBy(account.getUserId())) { - new TweetReactions.UnfavoriteTask(account, tweet.getId()) - .onDone(x -> Notificator.getInstance().publish(R.string.notice_unfavorite_succeeded)) - .onFail(x -> Notificator.getInstance().alert(R.string.notice_unfavorite_failed)) - .execute(); - } else { - new TweetReactions.FavoriteTask(account, tweet.getId()) - .onDone(x -> Notificator.getInstance().publish(R.string.notice_favorite_succeeded)) - .onFail(x -> Notificator.getInstance().alert(R.string.notice_favorite_failed)) - .execute(); - } - } - - private void toggleRetweet() { - Account account = Application.getInstance().getCurrentAccount(); - confirm(() -> { - if (tweet.isRetweetedBy(account.getUserId())) { - new Tweets.DestroyTask(account, tweet.getRetweetIdBy(account.getUserId())) - .onDone(t -> Notificator.getInstance().publish(R.string.notice_status_delete_succeeded)) - .onFail(e -> Notificator.getInstance().alert(R.string.notice_status_delete_failed)) - .execute(); - dismiss(); - } else { - new TweetReactions.RetweetTask(account, tweet.getId()) - .onDone(x -> Notificator.getInstance().publish(R.string.notice_retweet_succeeded)) - .onFail(x -> Notificator.getInstance().alert(R.string.notice_retweet_failed)) - .execute(); - } - }); - } } diff --git a/app/src/main/java/net/lacolaco/smileessence/view/dialog/StatusMenuDialogFragment.java b/app/src/main/java/net/lacolaco/smileessence/view/dialog/StatusMenuDialogFragment.java deleted file mode 100644 index 58284536..00000000 --- a/app/src/main/java/net/lacolaco/smileessence/view/dialog/StatusMenuDialogFragment.java +++ /dev/null @@ -1,66 +0,0 @@ -/* - * The MIT License (MIT) - * - * Copyright (c) 2012-2014 lacolaco.net - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in all - * copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - * SOFTWARE. - */ - -package net.lacolaco.smileessence.view.dialog; - -import android.app.Activity; -import android.os.Bundle; -import net.lacolaco.smileessence.command.Command; -import net.lacolaco.smileessence.entity.Tweet; - -import java.util.List; - -public class StatusMenuDialogFragment extends MenuDialogFragment { - - // ------------------------------ FIELDS ------------------------------ - - private static final String KEY_STATUS_ID = "statusID"; - private Tweet tweet; - - // --------------------- GETTER / SETTER METHODS --------------------- - - public long getStatusID() { - return getArguments().getLong(KEY_STATUS_ID); - } - - public void setStatusID(long statusID) { - Bundle args = new Bundle(); - args.putLong(KEY_STATUS_ID, statusID); - setArguments(args); - } - - // ------------------------ OVERRIDE METHODS ------------------------ - - @Override - public void onCreate(Bundle savedInstanceState) { - super.onCreate(savedInstanceState); - tweet = Tweet.fetch(getStatusID()); - } - - @Override - protected List<Command> getMenuCommands() { - Activity activity = getActivity(); - return Command.getStatusCommands(activity, tweet); - } -} diff --git a/app/src/main/java/net/lacolaco/smileessence/view/dialog/TalkChainDialogFragment.java b/app/src/main/java/net/lacolaco/smileessence/view/dialog/TalkChainDialogFragment.java index cc7b2b01..95bbac5c 100644 --- a/app/src/main/java/net/lacolaco/smileessence/view/dialog/TalkChainDialogFragment.java +++ b/app/src/main/java/net/lacolaco/smileessence/view/dialog/TalkChainDialogFragment.java @@ -28,22 +28,22 @@ import android.app.AlertDialog; import android.app.Dialog; import android.os.Bundle; import android.view.View; +import android.view.ViewGroup; import android.widget.ListView; import net.lacolaco.smileessence.Application; import net.lacolaco.smileessence.R; import net.lacolaco.smileessence.activity.MainActivity; import net.lacolaco.smileessence.data.Account; +import net.lacolaco.smileessence.entity.Tweet; import net.lacolaco.smileessence.twitter.task.Tweets; -import net.lacolaco.smileessence.view.adapter.UnorderedCustomListAdapter; -import net.lacolaco.smileessence.viewmodel.StatusViewModel; +import net.lacolaco.smileessence.view.Partials; +import net.lacolaco.smileessence.view.adapter.CustomListAdapter; -public class TalkChainDialogFragment extends StackableDialogFragment { - - // ------------------------------ FIELDS ------------------------------ - - private static final String KEY_STATUS_ID = "statusID"; +import java.util.ArrayList; +import java.util.List; - // --------------------- GETTER / SETTER METHODS --------------------- +public class TalkChainDialogFragment extends StackableDialogFragment { + private static final String KEY_STATUS_ID = "KEY_STATUS_ID"; private long getStatusID() { return getArguments().getLong(KEY_STATUS_ID); @@ -55,24 +55,32 @@ public class TalkChainDialogFragment extends StackableDialogFragment { setArguments(bundle); } - // ------------------------ OVERRIDE METHODS ------------------------ - @Override public Dialog onCreateDialog(Bundle savedInstanceState) { - MainActivity activity = (MainActivity) getActivity(); - Account account = Application.getInstance().getCurrentAccount(); + Account account = getWorld().getAccount(); View view = getActivity().getLayoutInflater().inflate(R.layout.dialog_talk_list, null); ListView listView = (ListView) view.findViewById(R.id.listview_dialog_talk_list); - final UnorderedCustomListAdapter<StatusViewModel> adapter = new UnorderedCustomListAdapter<>(getActivity()); + final List<Tweet> list = new ArrayList<>(); + final CustomListAdapter<Tweet> adapter = new CustomListAdapter<Tweet>() { + @Override + public View getView(int position, View convertView, ViewGroup parent) { + return Partials.getTweetView(getItem(position), getActivity(), convertView, true); + } + + @Override + protected List<Tweet> getList() { + return list; + } + }; listView.setAdapter(adapter); new Tweets.GetTalkTask(account, getStatusID()).onProgressUI(tweet -> { - adapter.addItemToBottom(new StatusViewModel(tweet)); + list.add(tweet); adapter.updateForce(); }).execute(); - return new AlertDialog.Builder(activity) + return new AlertDialog.Builder(getActivity()) .setTitle(R.string.dialog_title_talk_chain) .setView(view) .setCancelable(true) diff --git a/app/src/main/java/net/lacolaco/smileessence/view/dialog/UserDetailDialogFragment.java b/app/src/main/java/net/lacolaco/smileessence/view/dialog/UserDetailDialogFragment.java index f7f69947..9e036d32 100644 --- a/app/src/main/java/net/lacolaco/smileessence/view/dialog/UserDetailDialogFragment.java +++ b/app/src/main/java/net/lacolaco/smileessence/view/dialog/UserDetailDialogFragment.java @@ -31,20 +31,20 @@ import android.text.Html; import android.text.TextUtils; import android.text.method.LinkMovementMethod; import android.view.View; -import android.widget.*; +import android.widget.AbsListView; +import android.widget.ListView; +import android.widget.TabHost; +import android.widget.TextView; import com.android.volley.toolbox.NetworkImageView; import com.handmark.pulltorefresh.library.PullToRefreshBase; import com.handmark.pulltorefresh.library.PullToRefreshListView; import net.lacolaco.smileessence.Application; import net.lacolaco.smileessence.R; import net.lacolaco.smileessence.activity.MainActivity; -import net.lacolaco.smileessence.command.Command; import net.lacolaco.smileessence.data.Account; import net.lacolaco.smileessence.data.ImageCache; import net.lacolaco.smileessence.entity.RBinding; -import net.lacolaco.smileessence.entity.Tweet; import net.lacolaco.smileessence.entity.User; -import net.lacolaco.smileessence.notification.Notificator; import net.lacolaco.smileessence.twitter.task.Timelines; import net.lacolaco.smileessence.twitter.task.Users; import net.lacolaco.smileessence.util.IntentUtils; @@ -52,9 +52,7 @@ import net.lacolaco.smileessence.util.UIHandler; import net.lacolaco.smileessence.util.UIObserverBundle; import net.lacolaco.smileessence.view.DialogHelper; import net.lacolaco.smileessence.view.ThreeStateButton; -import net.lacolaco.smileessence.view.adapter.OrderedCustomListAdapter; -import net.lacolaco.smileessence.view.adapter.StatusListAdapter; -import net.lacolaco.smileessence.viewmodel.StatusViewModel; +import net.lacolaco.smileessence.view.adapter.TimelineAdapter; public class UserDetailDialogFragment extends StackableDialogFragment implements View.OnClickListener, PullToRefreshBase.OnRefreshListener2<ListView> { @@ -62,7 +60,7 @@ public class UserDetailDialogFragment extends StackableDialogFragment implements // ------------------------------ FIELDS ------------------------------ private static final String KEY_USER_ID = "userID"; - private StatusListAdapter adapter; + private TimelineAdapter adapter; private TextView textViewScreenName; private TextView textViewName; private TextView textViewURL; @@ -138,15 +136,13 @@ public class UserDetailDialogFragment extends StackableDialogFragment implements @Override public void onPullDownToRefresh(final PullToRefreshBase<ListView> refreshView) { - Account currentAccount = Application.getInstance().getCurrentAccount(); + Account currentAccount = getWorld().getAccount(); new Timelines.UserTimelineTask(currentAccount, getUserID()) .setCount(200) .setSinceId(adapter.getTopID()) - .onFail(x -> Notificator.getInstance().alert(R.string.notice_error_get_user_timeline)) + .onFail(x -> getWorld().notifyError(R.string.notice_error_get_user_timeline)) .onDoneUI(tweets -> { - for (int i = tweets.size() - 1; i >= 0; i--) { - adapter.addItem(new StatusViewModel(tweets.get(i))); - } + adapter.addAll(tweets); updateListView(refreshView.getRefreshableView(), adapter, true); refreshView.onRefreshComplete(); }) @@ -155,15 +151,13 @@ public class UserDetailDialogFragment extends StackableDialogFragment implements @Override public void onPullUpToRefresh(final PullToRefreshBase<ListView> refreshView) { - Account currentAccount = Application.getInstance().getCurrentAccount(); + Account currentAccount = getWorld().getAccount(); new Timelines.UserTimelineTask(currentAccount, getUserID()) .setCount(200) .setMaxId(adapter.getLastID() - 1) - .onFail(x -> Notificator.getInstance().alert(R.string.notice_error_get_user_timeline)) + .onFail(x -> getWorld().notifyError(R.string.notice_error_get_user_timeline)) .onDoneUI(tweets -> { - for (Tweet tweet : tweets) { - adapter.addItem(new StatusViewModel(tweet)); - } + adapter.addAll(tweets); updateListView(refreshView.getRefreshableView(), adapter, false); refreshView.onRefreshComplete(); }) @@ -189,7 +183,7 @@ public class UserDetailDialogFragment extends StackableDialogFragment implements public Dialog onCreateDialog(Bundle savedInstanceState) { MainActivity activity = (MainActivity) getActivity(); if (user == null) { - Notificator.getInstance().publish(R.string.notice_error_show_user); + getWorld().notify(R.string.notice_error_show_user); return new DisposeDialog(activity); } @@ -237,16 +231,14 @@ public class UserDetailDialogFragment extends StackableDialogFragment implements .create(); } - private void executeUserTimelineTask(final StatusListAdapter adapter) { - Account account = Application.getInstance().getCurrentAccount(); + private void executeUserTimelineTask(final TimelineAdapter adapter) { + Account account = getWorld().getAccount(); tabHost.getTabWidget().getChildTabViewAt(1).setVisibility(View.GONE); new Timelines.UserTimelineTask(account, user.getId()) .setCount(200) - .onFail(x -> Notificator.getInstance().alert(R.string.notice_error_get_user_timeline)) + .onFail(x -> getWorld().notifyError(R.string.notice_error_get_user_timeline)) .onDoneUI(tweets -> { - for (Tweet tweet : tweets) { - adapter.addItem(new StatusViewModel(tweet)); - } + adapter.addAll(tweets); adapter.updateForce(); tabHost.getTabWidget().getChildTabViewAt(1).setVisibility(View.VISIBLE); }) @@ -300,7 +292,7 @@ public class UserDetailDialogFragment extends StackableDialogFragment implements updateUserDataDetail(); MainActivity activity = (MainActivity) getActivity(); - adapter = new StatusListAdapter(activity); + adapter = new TimelineAdapter(activity); listViewTimeline.setAdapter(adapter); executeUserTimelineTask(adapter); updateRelationship(); @@ -316,19 +308,54 @@ public class UserDetailDialogFragment extends StackableDialogFragment implements } private void openUserMenu() { - UserMenuDialogFragment menuFragment = new UserMenuDialogFragment() { - @Override - protected void executeCommand(Command command) { - super.executeCommand(command); - new UIHandler().postDelayed(() -> { - if (UserDetailDialogFragment.this.isAdded()) { - updateRelationship(); + AlertDialog.Builder builder = new AlertDialog.Builder(getActivity()); + builder.setTitle("@" + user.getScreenName()) + .setItems(R.array.user_commands, (dialog, which) -> { + // XXX + new UIHandler().postDelayed(() -> { + if (UserDetailDialogFragment.this.isAdded()) { + updateRelationship(); + } + }, 1000); + switch (which) { + case 0: + String text = String.format("@%s ", user.getScreenName()); + getWorld().getPostState().beginTransaction().insertText(0, text).moveCursor(text.length()).commit(); + getWorld().notify(R.string.notice_add_to_reply); + break; + case 1: + DialogHelper.showDialog(getActivity(), SendMessageDialogFragment.newInstance(user)); + break; + case 2: + ConfirmDialogFragment.show(getActivity(), getString(R.string.dialog_confirm_commands), () -> + new Users.BlockTask(getWorld().getAccount(), user.getId()) + .onDone(user -> getWorld().notify(R.string.notice_block_succeeded)) + .onFail(ex -> getWorld().notifyError(R.string.notice_block_failed)) + .execute()); + break; + case 3: + ConfirmDialogFragment.show(getActivity(), getString(R.string.dialog_confirm_commands), () -> + new Users.UnblockTask(getWorld().getAccount(), user.getId()) + .onDone(user -> getWorld().notify(R.string.notice_unblock_succeeded)) + .onFail(x -> getWorld().notifyError(R.string.notice_unblock_failed)) + .execute()); + break; + case 4: + ConfirmDialogFragment.show(getActivity(), getString(R.string.dialog_confirm_commands), () -> + new Users.ReportForSpamTask(getWorld().getAccount(), user.getId()) + .onDone(user -> getWorld().notify(R.string.notice_r4s_succeeded)) + .onFail(ex -> getWorld().notifyError(R.string.notice_r4s_failed)) + .execute()); + break; + case 5: + IntentUtils.openUri(getActivity(), user.getAclogTimelineURL()); + break; + default: + throw new IllegalStateException(); } - }, 1000); - } - }; - menuFragment.setUserID(user.getId()); - DialogHelper.showDialog(getActivity(), menuFragment); + }); + AlertDialog dialog = builder.create(); + dialog.show(); } private void setFollowButtonState(boolean isFollowing) { @@ -339,30 +366,30 @@ public class UserDetailDialogFragment extends StackableDialogFragment implements } private void toggleFollowing() { - Account account = Application.getInstance().getCurrentAccount(); + Account account = getWorld().getAccount(); Boolean isFollowing = buttonFollow.getState() == ThreeStateButton.STATE_ON; buttonFollow.setState(ThreeStateButton.STATE_LOCKED); if (isFollowing) { new Users.UnfollowTask(account, user.getId()) .onDoneUI(result -> { - Notificator.getInstance().publish(R.string.notice_unfollow_succeeded); + getWorld().notify(R.string.notice_unfollow_succeeded); updateRelationship(); }) .onFail(x -> - Notificator.getInstance().alert(R.string.notice_unfollow_failed)) + getWorld().notifyError(R.string.notice_unfollow_failed)) .execute(); } else { new Users.FollowTask(account, user.getId()) .onDoneUI(result -> { - Notificator.getInstance().publish(R.string.notice_follow_succeeded); + getWorld().notify(R.string.notice_follow_succeeded); updateRelationship(); }) - .onFail(x -> Notificator.getInstance().alert(R.string.notice_follow_failed)) + .onFail(x -> getWorld().notifyError(R.string.notice_follow_failed)) .execute(); } } - private void updateListView(AbsListView absListView, OrderedCustomListAdapter<?> adapter, boolean addedToTop) { + private void updateListView(AbsListView absListView, TimelineAdapter adapter, boolean addedToTop) { int before = adapter.getCount(); adapter.notifyDataSetChanged(); // synchronized call (not adapter#updateForce()) int after = adapter.getCount(); @@ -379,7 +406,7 @@ public class UserDetailDialogFragment extends StackableDialogFragment implements } private void updateRelationship() { - Account account = Application.getInstance().getCurrentAccount(); + Account account = getWorld().getAccount(); if (user == account.getUser()) { textViewFollowed.setText(R.string.user_detail_followed_is_me); buttonFollow.setVisibility(View.GONE); diff --git a/app/src/main/java/net/lacolaco/smileessence/view/dialog/UserMenuDialogFragment.java b/app/src/main/java/net/lacolaco/smileessence/view/dialog/UserMenuDialogFragment.java deleted file mode 100644 index 13d212ee..00000000 --- a/app/src/main/java/net/lacolaco/smileessence/view/dialog/UserMenuDialogFragment.java +++ /dev/null @@ -1,66 +0,0 @@ -/* - * The MIT License (MIT) - * - * Copyright (c) 2012-2014 lacolaco.net - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in all - * copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - * SOFTWARE. - */ - -package net.lacolaco.smileessence.view.dialog; - -import android.app.Activity; -import android.os.Bundle; -import net.lacolaco.smileessence.command.Command; -import net.lacolaco.smileessence.entity.User; - -import java.util.List; - -public class UserMenuDialogFragment extends MenuDialogFragment { - - // ------------------------------ FIELDS ------------------------------ - - private static final String KEY_USER_ID = "userID"; - private User user; - - // --------------------- GETTER / SETTER METHODS --------------------- - - public long getUserID() { - return getArguments().getLong(KEY_USER_ID); - } - - public void setUserID(long userID) { - Bundle args = new Bundle(); - args.putLong(KEY_USER_ID, userID); - setArguments(args); - } - - // ------------------------ OVERRIDE METHODS ------------------------ - - @Override - public void onCreate(Bundle savedInstanceState) { - super.onCreate(savedInstanceState); - user = User.fetch(getUserID()); - } - - @Override - protected List<Command> getMenuCommands() { - Activity activity = getActivity(); - return Command.getUserCommands(activity, user); - } -} diff --git a/app/src/main/java/net/lacolaco/smileessence/view/page/CustomListFragment.java b/app/src/main/java/net/lacolaco/smileessence/view/page/CustomListFragment.java index 12064b3d..0dd24e67 100644 --- a/app/src/main/java/net/lacolaco/smileessence/view/page/CustomListFragment.java +++ b/app/src/main/java/net/lacolaco/smileessence/view/page/CustomListFragment.java @@ -33,7 +33,8 @@ import android.widget.ListView; import com.handmark.pulltorefresh.library.PullToRefreshBase; import com.handmark.pulltorefresh.library.PullToRefreshListView; import net.lacolaco.smileessence.R; -import net.lacolaco.smileessence.notification.Notificator; +import net.lacolaco.smileessence.World; +import net.lacolaco.smileessence.activity.MainActivity; import net.lacolaco.smileessence.view.adapter.CustomListAdapter; public abstract class CustomListFragment<T extends CustomListAdapter> extends PageFragment<T> implements AbsListView.OnScrollListener, @@ -100,7 +101,6 @@ public abstract class CustomListFragment<T extends CustomListAdapter> extends Pa int after = adapter.getCount(); int increments = after - before; if (increments > 0) { - Notificator.getInstance().publish(R.string.notice_timeline_new, increments); if (addedToTop) { absListView.setSelection(increments + 1); absListView.smoothScrollToPositionFromTop(increments, 0); diff --git a/app/src/main/java/net/lacolaco/smileessence/view/page/HistoryFragment.java b/app/src/main/java/net/lacolaco/smileessence/view/page/HistoryFragment.java index b139575e..5f04114e 100644 --- a/app/src/main/java/net/lacolaco/smileessence/view/page/HistoryFragment.java +++ b/app/src/main/java/net/lacolaco/smileessence/view/page/HistoryFragment.java @@ -26,40 +26,18 @@ package net.lacolaco.smileessence.view.page; import android.os.Bundle; import com.handmark.pulltorefresh.library.PullToRefreshBase; -import net.lacolaco.smileessence.twitter.StatusFilter; +import net.lacolaco.smileessence.World; import net.lacolaco.smileessence.view.adapter.EventListAdapter; -import net.lacolaco.smileessence.viewmodel.EventViewModel; -/** - * Fragment for notice history - */ public class HistoryFragment extends CustomListFragment<EventListAdapter> { - - // --------------------- GETTER / SETTER METHODS --------------------- - - @Override - protected PullToRefreshBase.Mode getRefreshMode() { - return PullToRefreshBase.Mode.DISABLED; - } - - // ------------------------ INTERFACE METHODS ------------------------ - @Override public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); - EventListAdapter adapter = new EventListAdapter(getActivity()); - setAdapter(adapter); - - StatusFilter.getInstance().register(this, EventViewModel.class, (EventViewModel vm) -> { - adapter.addItemToTop(vm); - adapter.update(); - }, null); - } - @Override - public void onDestroy() { - super.onDestroy(); - StatusFilter.getInstance().unregister(this); + World world = getWorld(); + final EventListAdapter adapter = new EventListAdapter(world, getActivity()); + setAdapter(adapter); + world.addEventNotifier(this, () -> adapter.update()); // XXX } @Override diff --git a/app/src/main/java/net/lacolaco/smileessence/view/page/HomeFragment.java b/app/src/main/java/net/lacolaco/smileessence/view/page/HomeFragment.java index 719a5c53..e00f69c6 100644 --- a/app/src/main/java/net/lacolaco/smileessence/view/page/HomeFragment.java +++ b/app/src/main/java/net/lacolaco/smileessence/view/page/HomeFragment.java @@ -32,69 +32,48 @@ import net.lacolaco.smileessence.R; import net.lacolaco.smileessence.activity.MainActivity; import net.lacolaco.smileessence.entity.Tweet; import net.lacolaco.smileessence.logging.Logger; -import net.lacolaco.smileessence.notification.Notificator; -import net.lacolaco.smileessence.twitter.StatusFilter; import net.lacolaco.smileessence.twitter.task.TimelineTask; import net.lacolaco.smileessence.twitter.task.Timelines; import net.lacolaco.smileessence.util.UIHandler; -import net.lacolaco.smileessence.view.adapter.StatusListAdapter; -import net.lacolaco.smileessence.viewmodel.StatusViewModel; - -public class HomeFragment extends CustomListFragment<StatusListAdapter> { - - // --------------------- GETTER / SETTER METHODS --------------------- +import net.lacolaco.smileessence.view.adapter.TimelineAdapter; +public class HomeFragment extends CustomListFragment<TimelineAdapter> { @Override protected PullToRefreshBase.Mode getRefreshMode() { return PullToRefreshBase.Mode.BOTH; } - // ------------------------ INTERFACE METHODS ------------------------ - - @Override // onCreate って Fragment のインスタンスが作られるときは必ず呼ばれるって認識でいいんだよね? + @Override public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); - StatusListAdapter adapter = new StatusListAdapter(getActivity()); + TimelineAdapter adapter = new TimelineAdapter(getActivity()); setAdapter(adapter); - StatusFilter.getInstance().register(this, Tweet.class, (Tweet tweet) -> { - adapter.addItem(new StatusViewModel(tweet)); + getWorld().addTimeline(this, tweet -> { + adapter.add(tweet); adapter.update(); - }, id -> { - adapter.removeItemById(id); - adapter.updateForce(); }); - if (Application.getInstance().getCurrentAccount() != null) { - Logger.debug(String.format("Current account %s is set; refreshing", Application.getInstance().getCurrentAccount().getUser().getScreenName())); - refresh(); - } - } - - @Override - public void onDestroy() { - super.onDestroy(); - StatusFilter.getInstance().unregister(this); + refresh(); } @Override public void refresh() { - runRefreshTask(new Timelines.HomeTimelineTask(Application.getInstance().getCurrentAccount()), () -> getAdapter().updateForce()); + runRefreshTask(new Timelines.HomeTimelineTask(getWorld().getAccount()), () -> getAdapter().updateForce()); } // --------------------- Interface OnRefreshListener2 --------------------- @Override public void onPullDownToRefresh(final PullToRefreshBase<ListView> refreshView) { - final MainActivity activity = (MainActivity) getActivity(); - if (activity.isStreaming()) { + if (getWorld().isStreaming()) { new UIHandler().post(() -> { updateListViewWithNotice(refreshView.getRefreshableView(), true); refreshView.onRefreshComplete(); }); } else { runRefreshTask( - new Timelines.HomeTimelineTask(Application.getInstance().getCurrentAccount()) + new Timelines.HomeTimelineTask(getWorld().getAccount()) .setSinceId(getAdapter().getTopID()), () -> { updateListViewWithNotice(refreshView.getRefreshableView(), true); @@ -106,7 +85,7 @@ public class HomeFragment extends CustomListFragment<StatusListAdapter> { @Override public void onPullUpToRefresh(final PullToRefreshBase<ListView> refreshView) { runRefreshTask( - new Timelines.HomeTimelineTask(Application.getInstance().getCurrentAccount()) + new Timelines.HomeTimelineTask(getWorld().getAccount()) .setMaxId(getAdapter().getLastID() - 1), () -> { updateListViewWithNotice(refreshView.getRefreshableView(), false); @@ -117,12 +96,8 @@ public class HomeFragment extends CustomListFragment<StatusListAdapter> { private void runRefreshTask(TimelineTask<Tweet> task, Runnable onFinish) { task .setCount(200) - .onFail(e -> Notificator.getInstance().alert(R.string.notice_error_get_home)) - .onDoneUI(tweets -> { - for (Tweet tweet : tweets) { - StatusFilter.getInstance().filter(tweet); - } - }) + .onFail(e -> getWorld().notifyError(R.string.notice_error_get_home)) + .onDoneUI(tweets -> getWorld().addTweetAll(tweets)) .onFinishUI(onFinish) .execute(); } diff --git a/app/src/main/java/net/lacolaco/smileessence/view/page/MentionsFragment.java b/app/src/main/java/net/lacolaco/smileessence/view/page/MentionsFragment.java index cfa75d7d..21ae1169 100644 --- a/app/src/main/java/net/lacolaco/smileessence/view/page/MentionsFragment.java +++ b/app/src/main/java/net/lacolaco/smileessence/view/page/MentionsFragment.java @@ -31,14 +31,12 @@ import net.lacolaco.smileessence.Application; import net.lacolaco.smileessence.R; import net.lacolaco.smileessence.data.ExtractionWord; import net.lacolaco.smileessence.entity.Tweet; -import net.lacolaco.smileessence.notification.Notificator; -import net.lacolaco.smileessence.twitter.StatusFilter; +import net.lacolaco.smileessence.entity.User; import net.lacolaco.smileessence.twitter.task.TimelineTask; import net.lacolaco.smileessence.twitter.task.Timelines; -import net.lacolaco.smileessence.view.adapter.StatusListAdapter; -import net.lacolaco.smileessence.viewmodel.StatusViewModel; +import net.lacolaco.smileessence.view.adapter.TimelineAdapter; -public class MentionsFragment extends CustomListFragment<StatusListAdapter> { +public class MentionsFragment extends CustomListFragment<TimelineAdapter> { // --------------------- GETTER / SETTER METHODS --------------------- @@ -51,42 +49,32 @@ public class MentionsFragment extends CustomListFragment<StatusListAdapter> { @Override public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); - StatusListAdapter adapter = new StatusListAdapter(getActivity()); + + final TimelineAdapter adapter = new TimelineAdapter(getActivity()); setAdapter(adapter); - StatusFilter.getInstance().register(this, Tweet.class, (Tweet tweet) -> { - StatusViewModel vm = new StatusViewModel(tweet); - if (tweet.getMentions().contains(Application.getInstance().getCurrentAccount().getUser().getScreenName())) { - adapter.addItem(vm); + // Prevent calling getWorld() on null + final User self = getWorld().getAccount().getUser(); + getWorld().addTimeline(this, tweet -> { + if (tweet.getMentions().contains(self.getScreenName())) { + adapter.add(tweet); adapter.update(); } else { for (ExtractionWord word : ExtractionWord.cached()) { if (word.getPattern().matcher(tweet.getOriginalTweet().getText()).find()) { - adapter.addItem(vm); + adapter.add(tweet); adapter.update(); - return; } } } - }, id -> { - adapter.removeItemById(id); - adapter.updateForce(); }); - if (Application.getInstance().getCurrentAccount() != null) { - refresh(); - } - } - - @Override - public void onDestroy() { - super.onDestroy(); - StatusFilter.getInstance().unregister(this); + refresh(); } @Override public void refresh() { - runRefreshTask(new Timelines.MentionsTimelineTask(Application.getInstance().getCurrentAccount()), () -> getAdapter().updateForce()); + runRefreshTask(new Timelines.MentionsTimelineTask(getWorld().getAccount()), () -> getAdapter().updateForce()); } // --------------------- Interface OnRefreshListener2 --------------------- @@ -94,7 +82,7 @@ public class MentionsFragment extends CustomListFragment<StatusListAdapter> { @Override public void onPullDownToRefresh(final PullToRefreshBase<ListView> refreshView) { runRefreshTask( - new Timelines.MentionsTimelineTask(Application.getInstance().getCurrentAccount()) + new Timelines.MentionsTimelineTask(getWorld().getAccount()) .setSinceId(getAdapter().getTopID()), () -> { updateListViewWithNotice(refreshView.getRefreshableView(), true); @@ -105,7 +93,7 @@ public class MentionsFragment extends CustomListFragment<StatusListAdapter> { @Override public void onPullUpToRefresh(final PullToRefreshBase<ListView> refreshView) { runRefreshTask( - new Timelines.MentionsTimelineTask(Application.getInstance().getCurrentAccount()) + new Timelines.MentionsTimelineTask(getWorld().getAccount()) .setMaxId(getAdapter().getLastID() - 1), () -> { updateListViewWithNotice(refreshView.getRefreshableView(), false); @@ -116,12 +104,8 @@ public class MentionsFragment extends CustomListFragment<StatusListAdapter> { private void runRefreshTask(TimelineTask<Tweet> task, Runnable onFinish) { task .setCount(200) - .onFail(x -> Notificator.getInstance().alert(R.string.notice_error_get_mentions)) - .onDoneUI(tweets -> { - for (Tweet tweet : tweets) { - StatusFilter.getInstance().filter(tweet); - } - }) + .onFail(x -> getWorld().notifyError(R.string.notice_error_get_mentions)) + .onDoneUI(tweets -> getWorld().addTweetAll(tweets)) .onFinishUI(onFinish) .execute(); } diff --git a/app/src/main/java/net/lacolaco/smileessence/view/page/MessagesFragment.java b/app/src/main/java/net/lacolaco/smileessence/view/page/MessagesFragment.java index e07cf272..291f4cfc 100644 --- a/app/src/main/java/net/lacolaco/smileessence/view/page/MessagesFragment.java +++ b/app/src/main/java/net/lacolaco/smileessence/view/page/MessagesFragment.java @@ -30,64 +30,40 @@ import com.handmark.pulltorefresh.library.PullToRefreshBase; import net.lacolaco.smileessence.Application; import net.lacolaco.smileessence.R; import net.lacolaco.smileessence.entity.DirectMessage; -import net.lacolaco.smileessence.notification.Notificator; -import net.lacolaco.smileessence.twitter.StatusFilter; import net.lacolaco.smileessence.twitter.task.Messages; import net.lacolaco.smileessence.twitter.task.TimelineTask; import net.lacolaco.smileessence.view.adapter.MessageListAdapter; -import net.lacolaco.smileessence.viewmodel.MessageViewModel; -/** - * Fragment of messages list - */ public class MessagesFragment extends CustomListFragment<MessageListAdapter> { - - // --------------------- GETTER / SETTER METHODS --------------------- - @Override protected PullToRefreshBase.Mode getRefreshMode() { return PullToRefreshBase.Mode.BOTH; } - // ------------------------ INTERFACE METHODS ------------------------ - @Override public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); MessageListAdapter adapter = new MessageListAdapter(getActivity()); setAdapter(adapter); - StatusFilter.getInstance().register(this, DirectMessage.class, (DirectMessage message) -> { - adapter.addItem(new MessageViewModel(message)); + getWorld().addDirectMessageTimeline(this, message -> { + adapter.add(message); adapter.update(); - }, id -> { - adapter.removeItemById(id); - adapter.updateForce(); }); - if (Application.getInstance().getCurrentAccount() != null) { - refresh(); - } - } - - @Override - public void onDestroy() { - super.onDestroy(); - StatusFilter.getInstance().unregister(this); + refresh(); } @Override public void refresh() { - runRefreshTask(new Messages.GetAllReceived(Application.getInstance().getCurrentAccount()), () -> getAdapter().updateForce()); - runRefreshTask(new Messages.GetAllSent(Application.getInstance().getCurrentAccount()), () -> getAdapter().updateForce()); + runRefreshTask(new Messages.GetAllReceived(getWorld().getAccount()), () -> getAdapter().updateForce()); + runRefreshTask(new Messages.GetAllSent(getWorld().getAccount()), () -> getAdapter().updateForce()); } - // --------------------- Interface OnRefreshListener2 --------------------- - @Override public void onPullDownToRefresh(final PullToRefreshBase<ListView> refreshView) { runRefreshTask( - new Messages.GetAllReceived(Application.getInstance().getCurrentAccount()) + new Messages.GetAllReceived(getWorld().getAccount()) .setSinceId(getAdapter().getTopID()), () -> { updateListViewWithNotice(refreshView.getRefreshableView(), true); @@ -98,7 +74,7 @@ public class MessagesFragment extends CustomListFragment<MessageListAdapter> { @Override public void onPullUpToRefresh(final PullToRefreshBase<ListView> refreshView) { runRefreshTask( - new Messages.GetAllReceived(Application.getInstance().getCurrentAccount()) + new Messages.GetAllReceived(getWorld().getAccount()) .setMaxId(getAdapter().getLastID() - 1), () -> { updateListViewWithNotice(refreshView.getRefreshableView(), false); @@ -109,10 +85,10 @@ public class MessagesFragment extends CustomListFragment<MessageListAdapter> { private void runRefreshTask(TimelineTask<DirectMessage> task, Runnable onFinish) { task .setCount(200) - .onFail(x -> Notificator.getInstance().alert(R.string.notice_error_get_messages)) + .onFail(x -> getWorld().notifyError(R.string.notice_error_get_messages)) .onDoneUI(messages -> { for (DirectMessage message : messages) { - StatusFilter.getInstance().filter(message); + getWorld().addDirectMessage(message); } }) .onFinishUI(onFinish) diff --git a/app/src/main/java/net/lacolaco/smileessence/view/page/PageFragment.java b/app/src/main/java/net/lacolaco/smileessence/view/page/PageFragment.java index d9393ccd..c1299298 100644 --- a/app/src/main/java/net/lacolaco/smileessence/view/page/PageFragment.java +++ b/app/src/main/java/net/lacolaco/smileessence/view/page/PageFragment.java @@ -1,20 +1,32 @@ package net.lacolaco.smileessence.view.page; import android.app.Fragment; +import android.os.Bundle; import android.widget.Adapter; import net.lacolaco.smileessence.Application; +import net.lacolaco.smileessence.World; +import net.lacolaco.smileessence.activity.MainActivity; public abstract class PageFragment<T extends Adapter> extends Fragment { + public static final String KEY_USER_ID = "KEY_USER_ID"; private T adapter; + private World world; - protected T getAdapter() { + protected final T getAdapter() { if (adapter == null) throw new IllegalStateException("adapter is not initialized"); return adapter; } - protected void setAdapter(T _adapter) { + protected final void setAdapter(T _adapter) { adapter = _adapter; } public abstract void refresh(); + + protected final World getWorld() { + if (world == null) { + world = Application.getWorld(getArguments().getLong(KEY_USER_ID)); + } + return world; + } } diff --git a/app/src/main/java/net/lacolaco/smileessence/view/page/PostFragment.java b/app/src/main/java/net/lacolaco/smileessence/view/page/PostFragment.java index 94fd5ba9..f0c54f6f 100644 --- a/app/src/main/java/net/lacolaco/smileessence/view/page/PostFragment.java +++ b/app/src/main/java/net/lacolaco/smileessence/view/page/PostFragment.java @@ -37,20 +37,19 @@ import android.text.method.ArrowKeyMovementMethod; import android.view.*; import android.widget.*; import com.twitter.Validator; -import net.lacolaco.smileessence.Application; import net.lacolaco.smileessence.R; +import net.lacolaco.smileessence.World; import net.lacolaco.smileessence.activity.MainActivity; import net.lacolaco.smileessence.data.PostState; import net.lacolaco.smileessence.entity.Tweet; import net.lacolaco.smileessence.logging.Logger; -import net.lacolaco.smileessence.notification.Notificator; import net.lacolaco.smileessence.preference.UserPreferenceHelper; import net.lacolaco.smileessence.twitter.task.Tweets; import net.lacolaco.smileessence.util.BitmapThumbnailTask; import net.lacolaco.smileessence.util.IntentUtils; import net.lacolaco.smileessence.util.SystemServiceHelper; import net.lacolaco.smileessence.util.UIHandler; -import net.lacolaco.smileessence.viewmodel.StatusViewModel; +import net.lacolaco.smileessence.view.Partials; import java.io.File; @@ -135,7 +134,7 @@ public class PostFragment extends PageFragment implements TextWatcher, View.OnFo Tweet tweet = postState.getInReplyTo(); View header = viewGroupReply.findViewById(R.id.layout_post_reply_status); - header = new StatusViewModel(tweet).getView(activity, activity.getLayoutInflater(), header); + header = Partials.getTweetView(tweet, activity, header, true); header.setBackgroundColor(ContextCompat.getColor(getActivity(), R.color.transparent)); header.setClickable(false); } else { @@ -168,7 +167,7 @@ public class PostFragment extends PageFragment implements TextWatcher, View.OnFo private void updateTextCount(CharSequence s) { Validator validator = new Validator(); int remainingCount = 140 - validator.getTweetLength(s.toString()); - if (!TextUtils.isEmpty(PostState.getState().getMediaFilePath())) { + if (!TextUtils.isEmpty(getWorld().getPostState().getMediaFilePath())) { remainingCount -= validator.getShortUrlLength(); } textViewCount.setText(String.valueOf(remainingCount)); @@ -202,7 +201,7 @@ public class PostFragment extends PageFragment implements TextWatcher, View.OnFo public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) { Logger.debug("onCreateView"); - PostState.getState().setListener(this); + getWorld().getPostState().setListener(this); View v = inflater.inflate(R.layout.fragment_post, null); buttonTweet = getTweetButton(v); buttonTweet.setOnClickListener(this); @@ -242,33 +241,33 @@ public class PostFragment extends PageFragment implements TextWatcher, View.OnFo Logger.debug("onDestroyView"); super.onDestroyView(); setStateFromView(); - PostState.getState().removeListener(); + getWorld().getPostState().removeListener(); } @Override public void onViewStateRestored(Bundle savedInstanceState) { Logger.debug("onViewStateRestored"); super.onViewStateRestored(savedInstanceState); - PostState state = PostState.getState(); + PostState state = getWorld().getPostState(); onPostStateChange(state); } private void deletePost() { editText.setText(""); - PostState.getState().beginTransaction().setText("").setCursor(0).commit(); + getWorld().getPostState().beginTransaction().setText("").setCursor(0).commit(); deleteReply(); } private void deleteReply() { viewGroupReply.setVisibility(View.GONE); - PostState.getState().beginTransaction().setInReplyTo(null).commit(); + getWorld().getPostState().beginTransaction().setInReplyTo(null).commit(); } private void displayImage() { Intent intent = new Intent(); intent.setAction(Intent.ACTION_VIEW); intent.addCategory(Intent.CATEGORY_DEFAULT); - intent.setDataAndType(Uri.fromFile(new File(PostState.getState().getMediaFilePath())), "image/*"); + intent.setDataAndType(Uri.fromFile(new File(getWorld().getPostState().getMediaFilePath())), "image/*"); IntentUtils.startActivityIfFound(getActivity(), intent); } @@ -296,7 +295,7 @@ public class PostFragment extends PageFragment implements TextWatcher, View.OnFo SystemServiceHelper.hideIM(getActivity(), editText); viewGroupMedia.setVisibility(View.GONE); ((ImageView) viewGroupMedia.findViewById(R.id.image_post_media)).setImageBitmap(null); - PostState.getState().beginTransaction().setMediaFilePath("").commit(); + getWorld().getPostState().beginTransaction().setMediaFilePath("").commit(); } private void setImage() { @@ -309,7 +308,7 @@ public class PostFragment extends PageFragment implements TextWatcher, View.OnFo } private void setStateFromView() { - PostState state = PostState.getState(); + PostState state = getWorld().getPostState(); state.removeListener(); state.beginTransaction() .setText(editText.getText().toString()) @@ -321,15 +320,15 @@ public class PostFragment extends PageFragment implements TextWatcher, View.OnFo private void submitPost() { SystemServiceHelper.hideIM(getActivity(), editText); setStateFromView(); - PostState state = PostState.getState(); + PostState state = getWorld().getPostState(); MainActivity mainActivity = (MainActivity) getActivity(); boolean resizeFlag = UserPreferenceHelper.getInstance().get(R.string.key_setting_resize_post_image, false); - new Tweets.CreateTask(Application.getInstance().getCurrentAccount(), state.toStatusUpdate(), state.getMediaFilePath(), resizeFlag) + new Tweets.CreateTask(getWorld().getAccount(), state.toStatusUpdate(), state.getMediaFilePath(), resizeFlag) .onDoneUI(t -> { - Notificator.getInstance().publish(R.string.notice_tweet_succeeded); - PostState.newState().beginTransaction().commit(); + getWorld().notify(R.string.notice_tweet_succeeded); + getWorld().getPostState().beginTransaction().clear().commit(); }) - .onFail(e -> Notificator.getInstance().alert(R.string.notice_tweet_failed, e)) + .onFail(e -> getWorld().notifyError(R.string.notice_tweet_failed, e)) .execute(); mainActivity.openHomePage(); } diff --git a/app/src/main/java/net/lacolaco/smileessence/view/page/SearchFragment.java b/app/src/main/java/net/lacolaco/smileessence/view/page/SearchFragment.java index 99173bf6..84d10c21 100644 --- a/app/src/main/java/net/lacolaco/smileessence/view/page/SearchFragment.java +++ b/app/src/main/java/net/lacolaco/smileessence/view/page/SearchFragment.java @@ -24,6 +24,7 @@ package net.lacolaco.smileessence.view.page; +import android.app.AlertDialog; import android.os.Bundle; import android.support.annotation.NonNull; import android.text.Spannable; @@ -40,30 +41,28 @@ import android.widget.ListView; import android.widget.TextView; import com.handmark.pulltorefresh.library.PullToRefreshBase; import com.handmark.pulltorefresh.library.PullToRefreshListView; -import net.lacolaco.smileessence.Application; import net.lacolaco.smileessence.R; -import net.lacolaco.smileessence.command.Command; -import net.lacolaco.smileessence.command.CommandOpenSearch; +import net.lacolaco.smileessence.activity.MainActivity; import net.lacolaco.smileessence.entity.SavedSearch; -import net.lacolaco.smileessence.notification.Notificator; import net.lacolaco.smileessence.preference.InternalPreferenceHelper; import net.lacolaco.smileessence.twitter.task.Searches; import net.lacolaco.smileessence.util.ListUtils; import net.lacolaco.smileessence.util.SystemServiceHelper; import net.lacolaco.smileessence.util.UIHandler; -import net.lacolaco.smileessence.view.DialogHelper; -import net.lacolaco.smileessence.view.adapter.SearchListAdapter; -import net.lacolaco.smileessence.view.dialog.SelectSearchQueryDialogFragment; -import net.lacolaco.smileessence.viewmodel.StatusViewModel; +import net.lacolaco.smileessence.view.adapter.TimelineAdapter; +import net.lacolaco.smileessence.view.dialog.ConfirmDialogFragment; import twitter4j.Query; +import java.util.ArrayList; import java.util.List; -public class SearchFragment extends CustomListFragment<SearchListAdapter> implements View.OnClickListener, View.OnFocusChangeListener, - SearchListAdapter.OnQueryChangeListener { +public class SearchFragment extends CustomListFragment<TimelineAdapter> implements View.OnClickListener, View.OnLongClickListener, + View.OnFocusChangeListener { // ------------------------------ FIELDS ------------------------------ + private String queryString; + private TimelineAdapter adapter; private EditText editText; // --------------------- GETTER / SETTER METHODS --------------------- @@ -79,19 +78,19 @@ public class SearchFragment extends CustomListFragment<SearchListAdapter> implem public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setHasOptionsMenu(true); - SearchListAdapter adapter = new SearchListAdapter(getActivity()); + + queryString = InternalPreferenceHelper.getInstance().get(R.string.key_last_used_search_query, ""); + android.app.Activity activity = getActivity(); + adapter = new TimelineAdapter(activity); setAdapter(adapter); - if (Application.getInstance().getCurrentAccount() != null) { - refresh(); - } + refresh(); } @Override public void refresh() { //TODO - String lastUsedSearchQuery = InternalPreferenceHelper.getInstance().get(R.string.key_last_used_search_query, ""); - if (!TextUtils.isEmpty(lastUsedSearchQuery)) { - startSearch(lastUsedSearchQuery); + if (!TextUtils.isEmpty(queryString)) { + startSearch(queryString); } } @@ -114,21 +113,35 @@ public class SearchFragment extends CustomListFragment<SearchListAdapter> implem } } - // --------------------- Interface OnFocusChangeListener --------------------- - @Override - public void onFocusChange(View v, boolean hasFocus) { - if (!hasFocus) { - SystemServiceHelper.hideIM(getActivity(), editText); + public boolean onLongClick(View v) { + switch (v.getId()) { + case R.id.button_search_save: { + String text = editText.getText().toString(); + for (SavedSearch ss : getWorld().getSavedSearches()) { + if (ss.getQuery().equals(text)) { + ConfirmDialogFragment.show(getActivity(), getString(R.string.dialog_confirm_delete_query), () -> new Searches.DestroySavedSearchTask(getWorld().getAccount(), ss.getId()) + .onDoneUI(x -> { + getWorld().notify(R.string.notice_search_query_deleted); + getWorld().refreshSavedSearches(); + }) + .onFailUI(x -> getWorld().notify("unable to delete search query")) + .execute(), false); + break; + } + } + return true; + } } + return false; } - // --------------------- Interface OnQueryChangeListener --------------------- + // --------------------- Interface OnFocusChangeListener --------------------- @Override - public void onQueryChange(String newQuery) { - if (editText != null) { - editText.setText(newQuery); + public void onFocusChange(View v, boolean hasFocus) { + if (!hasFocus) { + SystemServiceHelper.hideIM(getActivity(), editText); } } @@ -136,8 +149,6 @@ public class SearchFragment extends CustomListFragment<SearchListAdapter> implem @Override public void onPullDownToRefresh(final PullToRefreshBase<ListView> refreshView) { - final SearchListAdapter adapter = getAdapter(); - String queryString = adapter.getQuery(); if (TextUtils.isEmpty(queryString)) { new UIHandler().post(() -> { notifyTextEmpty(); @@ -160,8 +171,6 @@ public class SearchFragment extends CustomListFragment<SearchListAdapter> implem @Override public void onPullUpToRefresh(final PullToRefreshBase<ListView> refreshView) { - final SearchListAdapter adapter = getAdapter(); - String queryString = adapter.getQuery(); if (TextUtils.isEmpty(queryString)) { new UIHandler().post(() -> { notifyTextEmpty(); @@ -193,7 +202,6 @@ public class SearchFragment extends CustomListFragment<SearchListAdapter> implem public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) { View page = inflater.inflate(R.layout.fragment_search, container, false); PullToRefreshListView listView = getListView(page); - SearchListAdapter adapter = getAdapter(); listView.setAdapter(adapter); listView.setOnScrollListener(this); listView.setOnRefreshListener(this); @@ -206,7 +214,7 @@ public class SearchFragment extends CustomListFragment<SearchListAdapter> implem buttonSave.setOnClickListener(this); editText = getEditText(page); editText.setOnFocusChangeListener(this); - editText.setText(adapter.getQuery()); + editText.setText(queryString); editText.setOnEditorActionListener((textView, i, keyEvent) -> { if (i == EditorInfo.IME_ACTION_SEARCH || keyEvent != null && @@ -229,7 +237,6 @@ public class SearchFragment extends CustomListFragment<SearchListAdapter> implem return widget.getSelectionStart() == 0 || super.left(widget, buffer); } }); - adapter.setOnQueryChangeListener(this); return page; } @@ -250,32 +257,29 @@ public class SearchFragment extends CustomListFragment<SearchListAdapter> implem } private void notifyTextEmpty() { - Notificator.getInstance().alert(R.string.notice_search_text_empty); + getWorld().notifyError(R.string.notice_search_text_empty); } private void openSearchQueryDialog() { - DialogHelper.showDialog(getActivity(), new SelectSearchQueryDialogFragment() { - @Override - protected void executeCommand(Command command) { - super.executeCommand(command); - SavedSearch ss = ((CommandOpenSearch) command).getQuery(); - editText.setText(ss.getQuery()); - SystemServiceHelper.hideIM(SearchFragment.this.getActivity(), editText); - } + List<SavedSearch> sss = new ArrayList<>(getWorld().getSavedSearches()); + AlertDialog.Builder builder = new AlertDialog.Builder(getActivity()); + builder.setItems(ListUtils.map(sss, SavedSearch::getQuery).toArray(new String[]{}), (dialog, which) -> { + SavedSearch ss = sss.get(which); + ((MainActivity) getActivity()).openSearchPage(ss.getQuery()); }); + AlertDialog dialog = builder.create(); + dialog.show(); } private void saveQuery() { String text = editText.getText().toString(); if (TextUtils.isEmpty(text)) { - Notificator.getInstance().alert(R.string.notice_query_is_empty); + getWorld().notifyError(R.string.notice_query_is_empty); } else { - new Searches.CreateSavedSearchTask(Application.getInstance().getCurrentAccount(), text).onDoneUI(cb -> { - Notificator.getInstance().publish(R.string.notice_query_saved); - Application.getInstance().getCurrentAccount().refreshSavedSearches(); - }).onFailUI(ex -> { - Notificator.getInstance().publish("Query is not saved"); - }).execute(); + new Searches.CreateSavedSearchTask(getWorld().getAccount(), text).onDoneUI(cb -> { + getWorld().notify(R.string.notice_query_saved); + getWorld().refreshSavedSearches(); + }).onFailUI(ex -> getWorld().notifyError("Query is not saved")).execute(); } } @@ -283,7 +287,7 @@ public class SearchFragment extends CustomListFragment<SearchListAdapter> implem if (editText != null) { String text = editText.getText().toString(); if (TextUtils.isEmpty(text)) { - Notificator.getInstance().alert(R.string.notice_query_is_empty); + getWorld().notifyError(R.string.notice_query_is_empty); } else { startSearch(text); SystemServiceHelper.hideIM(getActivity(), editText); @@ -293,10 +297,12 @@ public class SearchFragment extends CustomListFragment<SearchListAdapter> implem public void startSearch(final String queryString) { InternalPreferenceHelper.getInstance().set(R.string.key_last_used_search_query, queryString); + if (editText != null) + editText.setText(queryString); + this.queryString = queryString; + adapter.clear(); + adapter.updateForce(); if (!TextUtils.isEmpty(queryString)) { - final SearchListAdapter adapter = getAdapter(); - adapter.initSearch(queryString); - adapter.updateForce(); final Query query = new Query(); query.setQuery(queryString); query.setCount(200); @@ -306,13 +312,9 @@ public class SearchFragment extends CustomListFragment<SearchListAdapter> implem } private void runRefreshTask(Query query, Runnable onFinish) { - final SearchListAdapter adapter = getAdapter(); - new Searches.SearchTask(Application.getInstance().getCurrentAccount(), query) - .onFail(x -> Notificator.getInstance().alert(R.string.notice_error_search)) - .onDoneUI(tweets -> { - List<StatusViewModel> e = ListUtils.map(ListUtils.filter(tweets, t -> !t.isRetweet()), StatusViewModel::new); - adapter.addItems(e); - }) + new Searches.SearchTask(getWorld().getAccount(), query) + .onFail(x -> getWorld().notifyError(R.string.notice_error_search)) + .onDoneUI(tweets -> adapter.addAll(ListUtils.filter(tweets, t -> !t.isRetweet()))) .onFinishUI(onFinish) .execute(); } diff --git a/app/src/main/java/net/lacolaco/smileessence/view/page/UserListFragment.java b/app/src/main/java/net/lacolaco/smileessence/view/page/UserListFragment.java index 2ec98dc2..3d19c5d6 100644 --- a/app/src/main/java/net/lacolaco/smileessence/view/page/UserListFragment.java +++ b/app/src/main/java/net/lacolaco/smileessence/view/page/UserListFragment.java @@ -24,7 +24,7 @@ package net.lacolaco.smileessence.view.page; -import android.content.DialogInterface; +import android.app.AlertDialog; import android.os.Bundle; import android.text.TextUtils; import android.view.LayoutInflater; @@ -37,42 +37,30 @@ import com.handmark.pulltorefresh.library.PullToRefreshBase; import com.handmark.pulltorefresh.library.PullToRefreshListView; import net.lacolaco.smileessence.Application; import net.lacolaco.smileessence.R; +import net.lacolaco.smileessence.activity.MainActivity; import net.lacolaco.smileessence.entity.Tweet; -import net.lacolaco.smileessence.notification.Notificator; import net.lacolaco.smileessence.preference.InternalPreferenceHelper; -import net.lacolaco.smileessence.twitter.StatusFilter; import net.lacolaco.smileessence.twitter.task.TimelineTask; import net.lacolaco.smileessence.twitter.task.Timelines; import net.lacolaco.smileessence.util.UIHandler; -import net.lacolaco.smileessence.view.DialogHelper; -import net.lacolaco.smileessence.view.adapter.UserListListAdapter; -import net.lacolaco.smileessence.view.dialog.SelectUserListDialogFragment; -import net.lacolaco.smileessence.viewmodel.StatusViewModel; - -public class UserListFragment extends CustomListFragment<UserListListAdapter> implements View.OnClickListener { - - // ------------------------------ FIELDS ------------------------------ +import net.lacolaco.smileessence.view.adapter.TimelineAdapter; +public class UserListFragment extends CustomListFragment<TimelineAdapter> implements View.OnClickListener { private TextView textListName; - - // --------------------- GETTER / SETTER METHODS --------------------- + private String listFullName; @Override protected PullToRefreshBase.Mode getRefreshMode() { return PullToRefreshBase.Mode.BOTH; } - // ------------------------ INTERFACE METHODS ------------------------ - @Override public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); - UserListListAdapter adapter = new UserListListAdapter(getActivity()); + TimelineAdapter adapter = new TimelineAdapter(getActivity()); setAdapter(adapter); - if (Application.getInstance().getCurrentAccount() != null) { - refresh(); - } + refresh(); } @Override @@ -83,8 +71,6 @@ public class UserListFragment extends CustomListFragment<UserListListAdapter> im } } - // --------------------- Interface OnClickListener --------------------- - @Override public void onClick(View v) { int id = v.getId(); @@ -96,13 +82,9 @@ public class UserListFragment extends CustomListFragment<UserListListAdapter> im } } - // --------------------- Interface OnRefreshListener2 --------------------- - @Override public void onPullDownToRefresh(final PullToRefreshBase<ListView> refreshView) { - final UserListListAdapter adapter = getAdapter(); - String listFullName = adapter.getListFullName(); - if (TextUtils.isEmpty(listFullName)) { + if (listFullName == null) { new UIHandler().post(() -> { notifyTextEmpty(); refreshView.onRefreshComplete(); @@ -110,8 +92,8 @@ public class UserListFragment extends CustomListFragment<UserListListAdapter> im return; } runRefreshTask( - new Timelines.UserListStatusesTask(Application.getInstance().getCurrentAccount(), listFullName) - .setSinceId(adapter.getTopID()), + new Timelines.UserListStatusesTask(getWorld().getAccount(), listFullName) + .setSinceId(getAdapter().getTopID()), () -> { updateListViewWithNotice(refreshView.getRefreshableView(), true); refreshView.onRefreshComplete(); @@ -120,9 +102,7 @@ public class UserListFragment extends CustomListFragment<UserListListAdapter> im @Override public void onPullUpToRefresh(final PullToRefreshBase<ListView> refreshView) { - final UserListListAdapter adapter = getAdapter(); - String listFullName = adapter.getListFullName(); - if (TextUtils.isEmpty(listFullName)) { + if (listFullName == null) { new UIHandler().post(() -> { notifyTextEmpty(); refreshView.onRefreshComplete(); @@ -130,8 +110,8 @@ public class UserListFragment extends CustomListFragment<UserListListAdapter> im return; } runRefreshTask( - new Timelines.UserListStatusesTask(Application.getInstance().getCurrentAccount(), listFullName) - .setMaxId(adapter.getLastID() - 1), + new Timelines.UserListStatusesTask(getWorld().getAccount(), listFullName) + .setMaxId(getAdapter().getLastID() - 1), () -> { updateListViewWithNotice(refreshView.getRefreshableView(), false); refreshView.onRefreshComplete(); @@ -149,7 +129,7 @@ public class UserListFragment extends CustomListFragment<UserListListAdapter> im public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) { View page = inflater.inflate(R.layout.fragment_userlist, container, false); PullToRefreshListView listView = getListView(page); - UserListListAdapter adapter = getAdapter(); + TimelineAdapter adapter = getAdapter(); listView.setAdapter(adapter); listView.setOnScrollListener(this); listView.setOnRefreshListener(this); @@ -157,7 +137,7 @@ public class UserListFragment extends CustomListFragment<UserListListAdapter> im ImageButton buttonUserLists = getUserListsButton(page); buttonUserLists.setOnClickListener(this); textListName = getTextListName(page); - textListName.setText(adapter.getListFullName()); + textListName.setText(listFullName != null ? listFullName : "<none>"); return page; } @@ -170,40 +150,41 @@ public class UserListFragment extends CustomListFragment<UserListListAdapter> im } private void notifyTextEmpty() { - Notificator.getInstance().alert(R.string.notice_userlist_not_selected); + getWorld().notifyError(R.string.notice_userlist_not_selected); } private void openUserListsDialog() { - DialogHelper.showDialog(getActivity(), new SelectUserListDialogFragment() { - @Override - public void onDismiss(DialogInterface dialog) { - super.onDismiss(dialog); - textListName.setText(getAdapter().getListFullName()); - } - }); + final String[] ary = getWorld().getListSubscriptions().toArray(new String[]{}); + AlertDialog.Builder builder = new AlertDialog.Builder(getActivity()); + builder.setTitle(R.string.dialog_title_select_userlist) + .setItems(ary, (dialog, which) -> { + MainActivity activity = (MainActivity) getActivity(); + activity.openUserListPage(ary[which]); + textListName.setText(ary[which]); + }); + AlertDialog dialog = builder.create(); + dialog.show(); } public void startUserList(String listFullName) { InternalPreferenceHelper.getInstance().set(R.string.key_last_used_user_list, listFullName); - final UserListListAdapter adapter = getAdapter(); - adapter.setListFullName(listFullName); + final TimelineAdapter adapter = getAdapter(); + this.listFullName = listFullName; adapter.clear(); adapter.updateForce(); runRefreshTask( - new Timelines.UserListStatusesTask(Application.getInstance().getCurrentAccount(), listFullName), + new Timelines.UserListStatusesTask(getWorld().getAccount(), listFullName), adapter::updateForce); } private void runRefreshTask(TimelineTask<Tweet> task, Runnable onFinish) { - final UserListListAdapter adapter = getAdapter(); + final TimelineAdapter adapter = getAdapter(); task .setCount(200) - .onFail(x -> Notificator.getInstance().alert(R.string.notice_error_get_list)) + .onFail(x -> getWorld().notifyError(R.string.notice_error_get_list)) .onDoneUI(tweets -> { - for (Tweet tweet : tweets) { - StatusFilter.getInstance().filter(tweet); - adapter.addItem(new StatusViewModel(tweet)); - } + getWorld().addTweetAll(tweets); + adapter.addAll(tweets); }) .onFinishUI(onFinish) .execute(); diff --git a/app/src/main/java/net/lacolaco/smileessence/viewmodel/EventViewModel.java b/app/src/main/java/net/lacolaco/smileessence/viewmodel/EventViewModel.java deleted file mode 100644 index ae53d0fb..00000000 --- a/app/src/main/java/net/lacolaco/smileessence/viewmodel/EventViewModel.java +++ /dev/null @@ -1,179 +0,0 @@ -/* - * The MIT License (MIT) - * - * Copyright (c) 2012-2014 lacolaco.net - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in all - * copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - * SOFTWARE. - */ - -package net.lacolaco.smileessence.viewmodel; - -import android.app.Activity; -import android.view.LayoutInflater; -import android.view.View; -import android.widget.ImageView; -import android.widget.TextView; -import com.android.volley.toolbox.NetworkImageView; -import net.lacolaco.smileessence.Application; -import net.lacolaco.smileessence.R; -import net.lacolaco.smileessence.data.ImageCache; -import net.lacolaco.smileessence.entity.RBinding; -import net.lacolaco.smileessence.entity.Tweet; -import net.lacolaco.smileessence.entity.User; -import net.lacolaco.smileessence.preference.UserPreferenceHelper; -import net.lacolaco.smileessence.util.StringUtils; -import net.lacolaco.smileessence.util.UIObserverBundle; -import net.lacolaco.smileessence.view.DialogHelper; -import net.lacolaco.smileessence.view.dialog.UserDetailDialogFragment; -import net.lacolaco.smileessence.view.listener.ListItemClickListener; - -import java.lang.ref.WeakReference; -import java.util.Date; - -public class EventViewModel implements IViewModel { - - // ------------------------------ FIELDS ------------------------------ - - private EnumEvent event; - private User source; - private Tweet targetObject; - private Date createdAt; - - // --------------------------- CONSTRUCTORS --------------------------- - - public EventViewModel(EnumEvent event, User source) { - this(event, source, null); - } - - public EventViewModel(EnumEvent event, User source, Tweet tweet) { - this.event = event; - this.source = source; - this.createdAt = new Date(); - - if (tweet != null) { - if (event == EnumEvent.RETWEETED) { - this.targetObject = tweet.getRetweetedTweet(); - } else { - this.targetObject = tweet; - } - } - } - - // --------------------- GETTER / SETTER METHODS --------------------- - - public Date getCreatedAt() { - return createdAt; - } - - public boolean isStatusEvent() { - return targetObject != null; - } - - // ------------------------ INTERFACE METHODS ------------------------ - - - // --------------------- Interface IViewModel --------------------- - - private void updateViewUser(View convertedView) { - NetworkImageView icon = (NetworkImageView) convertedView.findViewById(R.id.imageview_status_icon); - String iconUrl = source.getProfileImageUrlOriginal(); - ImageCache.getInstance().setImageToView(iconUrl, icon); - - TextView header = (TextView) convertedView.findViewById(R.id.textview_status_header); - header.setText(getFormattedString()); - } - - @Override - public View getView(final Activity activity, LayoutInflater inflater, View convertedView) { - if (convertedView == null) { - convertedView = inflater.inflate(R.layout.list_item_status, null); - } - UIObserverBundle bundle = (UIObserverBundle) convertedView.getTag(); - if (bundle != null) { - bundle.detachAll(); - } else { - bundle = new UIObserverBundle(); - convertedView.setTag(bundle); - } - - int textSize = UserPreferenceHelper.getInstance().getTextSize(); - - TextView header = (TextView) convertedView.findViewById(R.id.textview_status_header); - header.setTextSize(textSize); - - updateViewUser(convertedView); - - TextView content = (TextView) convertedView.findViewById(R.id.textview_status_text); - content.setTextSize(textSize); - content.setText(isStatusEvent() ? targetObject.getText() : ""); - TextView footer = (TextView) convertedView.findViewById(R.id.textview_status_footer); - footer.setTextSize(textSize - 2); - footer.setText(StringUtils.dateToString(getCreatedAt())); - ImageView favorited = (ImageView) convertedView.findViewById(R.id.imageview_status_favorited); - favorited.setVisibility(View.GONE); - convertedView.setOnClickListener(new ListItemClickListener(activity, () -> { - UserDetailDialogFragment fragment = new UserDetailDialogFragment(); - fragment.setUserID(source.getId()); - DialogHelper.showDialog(activity, fragment); - })); - - final WeakReference<View> weakView = new WeakReference<>(convertedView); - bundle.attach(source, changes -> { - View strongView = weakView.get(); - if (strongView != null && changes.contains(RBinding.BASIC)) - updateViewUser(strongView); - }); - - return convertedView; - } - - // -------------------------- OTHER METHODS -------------------------- - - public String getFormattedString() { - return Application.getInstance().getString(event.getTextFormatResourceID(), source.getScreenName()); - } - - public enum EnumEvent { - - FAVORITED(R.string.format_event_favorited), - UNFAVORITED(R.string.format_event_unfavorited), - RETWEETED(R.string.format_event_retweeted), - MENTIONED(R.string.format_event_mentioned), - FOLLOWED(R.string.format_event_followed), - BLOCKED(R.string.format_event_blocked), - UNBLOCKED(R.string.format_event_unblocked), - RECEIVE_MESSAGE(R.string.format_event_message); - - // ------------------------------ FIELDS ------------------------------ - - private int textFormatResourceID; - - // --------------------------- CONSTRUCTORS --------------------------- - - EnumEvent(int textFormatResourceID) { - this.textFormatResourceID = textFormatResourceID; - } - - // --------------------- GETTER / SETTER METHODS --------------------- - - public int getTextFormatResourceID() { - return textFormatResourceID; - } - } -} diff --git a/app/src/main/java/net/lacolaco/smileessence/viewmodel/IViewModel.java b/app/src/main/java/net/lacolaco/smileessence/viewmodel/IViewModel.java deleted file mode 100644 index 6de694d0..00000000 --- a/app/src/main/java/net/lacolaco/smileessence/viewmodel/IViewModel.java +++ /dev/null @@ -1,36 +0,0 @@ -/* - * The MIT License (MIT) - * - * Copyright (c) 2012-2014 lacolaco.net - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in all - * copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - * SOFTWARE. - */ - -package net.lacolaco.smileessence.viewmodel; - -import android.app.Activity; -import android.view.LayoutInflater; -import android.view.View; - -public interface IViewModel { - - // -------------------------- OTHER METHODS -------------------------- - - View getView(Activity activity, LayoutInflater inflater, View convertedView); -} diff --git a/app/src/main/java/net/lacolaco/smileessence/viewmodel/MessageViewModel.java b/app/src/main/java/net/lacolaco/smileessence/viewmodel/MessageViewModel.java deleted file mode 100644 index ae8f667b..00000000 --- a/app/src/main/java/net/lacolaco/smileessence/viewmodel/MessageViewModel.java +++ /dev/null @@ -1,155 +0,0 @@ -/* - * The MIT License (MIT) - * - * Copyright (c) 2012-2014 lacolaco.net - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in all - * copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - * SOFTWARE. - */ - -package net.lacolaco.smileessence.viewmodel; - -import android.app.Activity; -import android.view.LayoutInflater; -import android.view.View; -import android.widget.ImageView; -import android.widget.TextView; -import com.android.volley.toolbox.NetworkImageView; -import net.lacolaco.smileessence.Application; -import net.lacolaco.smileessence.R; -import net.lacolaco.smileessence.activity.MainActivity; -import net.lacolaco.smileessence.data.Account; -import net.lacolaco.smileessence.data.ImageCache; -import net.lacolaco.smileessence.entity.DirectMessage; -import net.lacolaco.smileessence.entity.IdObject; -import net.lacolaco.smileessence.entity.RBinding; -import net.lacolaco.smileessence.preference.UserPreferenceHelper; -import net.lacolaco.smileessence.util.StringUtils; -import net.lacolaco.smileessence.util.UIObserverBundle; -import net.lacolaco.smileessence.view.ColoredRelativeLayout; -import net.lacolaco.smileessence.view.DialogHelper; -import net.lacolaco.smileessence.view.dialog.MessageDetailDialogFragment; -import net.lacolaco.smileessence.view.dialog.UserDetailDialogFragment; -import net.lacolaco.smileessence.view.listener.ListItemClickListener; - -import java.lang.ref.WeakReference; - -public class MessageViewModel implements IViewModel, IdObject { - - // ------------------------------ FIELDS ------------------------------ - - private final DirectMessage directMessage; - - // --------------------------- CONSTRUCTORS --------------------------- - - public MessageViewModel(DirectMessage mes) { - directMessage = mes; - } - - // --------------------- GETTER / SETTER METHODS --------------------- - - - public DirectMessage getDirectMessage() { - return directMessage; - } - - @Override - public long getId() { - return directMessage.getId(); - } - - private String getFooterText(Account account) { - StringBuilder builder = new StringBuilder(); - builder.append(StringUtils.dateToString(directMessage.getCreatedAt())); - if (directMessage.getSender().getId() == account.getUserId()) { - builder.append(" to @").append(directMessage.getRecipient().getScreenName()); - } - return builder.toString(); - } - - // ------------------------ INTERFACE METHODS ------------------------ - - // --------------------- Interface IViewModel --------------------- - - @Override - public View getView(final Activity activity, LayoutInflater inflater, View convertedView) { - if (convertedView == null) { - convertedView = inflater.inflate(R.layout.list_item_status, null); - } - UIObserverBundle bundle = (UIObserverBundle) convertedView.getTag(); - if (bundle != null) { - bundle.detachAll(); - } else { - bundle = new UIObserverBundle(); - convertedView.setTag(bundle); - } - - convertedView.setOnClickListener(new ListItemClickListener(activity, () -> { - MessageDetailDialogFragment dialogFragment = new MessageDetailDialogFragment(); - dialogFragment.setMessageID(directMessage.getId()); - DialogHelper.showDialog(activity, dialogFragment); - })); - - ImageView favorited = (ImageView) convertedView.findViewById(R.id.imageview_status_favorited); - favorited.setVisibility(View.GONE); - - updateViewSender(activity, convertedView); - updateViewBody(activity, convertedView); - - final WeakReference<View> weakView = new WeakReference<>(convertedView); - final WeakReference<MainActivity> weakActivity = new WeakReference<>((MainActivity) activity); - bundle.attach(directMessage.getSender(), changes -> { - View strongView = weakView.get(); - MainActivity strongActivity = weakActivity.get(); - if (strongView != null && strongActivity != null && changes.contains(RBinding.BASIC)) - updateViewSender(strongActivity, strongView); - }); - - return convertedView; - } - - private void updateViewSender(Activity activity, View convertedView) { - int textSize = UserPreferenceHelper.getInstance().getTextSize(); - - NetworkImageView icon = (NetworkImageView) convertedView.findViewById(R.id.imageview_status_icon); - String iconUrl = directMessage.getSender().getProfileImageUrlOriginal(); - ImageCache.getInstance().setImageToView(iconUrl, icon); - icon.setOnClickListener(v -> { - UserDetailDialogFragment dialogFragment = new UserDetailDialogFragment(); - dialogFragment.setUserID(directMessage.getSender().getId()); - DialogHelper.showDialog(activity, dialogFragment); - }); - - TextView header = (TextView) convertedView.findViewById(R.id.textview_status_header); - header.setTextSize(textSize); - header.setText(directMessage.getSender().getFormattedName()); - - ((ColoredRelativeLayout) convertedView).setAccentVisibility(directMessage.getSender() == Application.getInstance().getCurrentAccount().getUser()); - } - - private void updateViewBody(Activity activity, View convertedView) { - int textSize = UserPreferenceHelper.getInstance().getTextSize(); - - TextView content = (TextView) convertedView.findViewById(R.id.textview_status_text); - content.setTextSize(textSize); - content.setText(directMessage.getText()); - TextView footer = (TextView) convertedView.findViewById(R.id.textview_status_footer); - footer.setTextSize(textSize - 2); - footer.setText(getFooterText(Application.getInstance().getCurrentAccount())); - } -} diff --git a/app/src/main/java/net/lacolaco/smileessence/viewmodel/StatusViewModel.java b/app/src/main/java/net/lacolaco/smileessence/viewmodel/StatusViewModel.java deleted file mode 100644 index cd0f8c07..00000000 --- a/app/src/main/java/net/lacolaco/smileessence/viewmodel/StatusViewModel.java +++ /dev/null @@ -1,217 +0,0 @@ -/* - * The MIT License (MIT) - * - * Copyright (c) 2012-2014 lacolaco.net - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in all - * copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - * SOFTWARE. - */ - -package net.lacolaco.smileessence.viewmodel; - -import android.app.Activity; -import android.text.Html; -import android.view.LayoutInflater; -import android.view.View; -import android.widget.ImageView; -import android.widget.ListView; -import android.widget.TextView; -import com.android.volley.toolbox.NetworkImageView; -import net.lacolaco.smileessence.Application; -import net.lacolaco.smileessence.R; -import net.lacolaco.smileessence.data.Account; -import net.lacolaco.smileessence.data.ImageCache; -import net.lacolaco.smileessence.entity.IdObject; -import net.lacolaco.smileessence.entity.RBinding; -import net.lacolaco.smileessence.entity.Tweet; -import net.lacolaco.smileessence.preference.UserPreferenceHelper; -import net.lacolaco.smileessence.util.StringUtils; -import net.lacolaco.smileessence.util.UIObserverBundle; -import net.lacolaco.smileessence.view.ColoredRelativeLayout; -import net.lacolaco.smileessence.view.DialogHelper; -import net.lacolaco.smileessence.view.adapter.StatusListAdapter; -import net.lacolaco.smileessence.view.dialog.StatusDetailDialogFragment; -import net.lacolaco.smileessence.view.dialog.UserDetailDialogFragment; -import net.lacolaco.smileessence.view.listener.ListItemClickListener; - -import java.lang.ref.WeakReference; - -public class StatusViewModel implements IViewModel, IdObject { - private final Tweet tweet; - private StatusListAdapter embeddedTweetsAdapter = null; // load when first rendering - private final boolean expandEmbeddedTweets; - - // --------------------------- CONSTRUCTORS --------------------------- - - public StatusViewModel(Tweet tw) { - this(tw, true); - } - - public StatusViewModel(Tweet tw, boolean expand) { - tweet = tw; - expandEmbeddedTweets = expand; - } - - // --------------------- GETTER / SETTER METHODS --------------------- - - public Tweet getTweet() { - return tweet; - } - - @Override - public long getId() { - return tweet.getId(); - } - - private String getFooterText() { - StringBuilder builder = new StringBuilder(); - if (tweet.isRetweet()) { - builder - .append("(RT: ") - .append(tweet.getUser().getScreenName()) - .append(") "); - } - builder.append(StringUtils.dateToString(tweet.getOriginalTweet().getCreatedAt())); - builder.append(" via "); - builder.append(Html.fromHtml(tweet.getOriginalTweet().getSource())); - return builder.toString(); - } - - // ------------------------ INTERFACE METHODS ------------------------ - - - // --------------------- Interface IViewModel --------------------- - - @Override - public View getView(final Activity activity, final LayoutInflater inflater, View convertedView) { - if (convertedView == null) { - convertedView = inflater.inflate(R.layout.list_item_status, null); - } - UIObserverBundle bundle = (UIObserverBundle) convertedView.getTag(); - if (bundle != null) { - bundle.detachAll(); - } else { - bundle = new UIObserverBundle(); - convertedView.setTag(bundle); - } - - convertedView.setOnClickListener(new ListItemClickListener(activity, () -> onClick(activity))); - - updateViewUser(activity, convertedView); - updateViewBody(activity, convertedView); - updateViewFavorited(convertedView); - updateViewEmbeddeds(activity, convertedView); - - final WeakReference<View> weakView = new WeakReference<>(convertedView); - final WeakReference<Activity> weakActivity = new WeakReference<>(activity); - bundle.attach(tweet.getOriginalTweet(), changes -> { - View strongView = weakView.get(); - if (strongView != null && changes.contains(RBinding.FAVORITERS)) - updateViewFavorited(strongView); - }); - bundle.attach(tweet.getUser(), changes -> { - View strongView = weakView.get(); - Activity strongActivity = weakActivity.get(); - if (strongView != null && strongActivity != null && changes.contains(RBinding.BASIC)) - updateViewUser(strongActivity, strongView); - }); - - return convertedView; - } - - private void updateViewUser(Activity activity, View convertedView) { - int textSize = UserPreferenceHelper.getInstance().getTextSize(); - - NetworkImageView icon = (NetworkImageView) convertedView.findViewById(R.id.imageview_status_icon); - String iconUrl = tweet.getOriginalTweet().getUser().getProfileImageUrlOriginal(); - ImageCache.getInstance().setImageToView(iconUrl, icon); - icon.setOnClickListener(v -> onIconClick(activity)); - - TextView header = (TextView) convertedView.findViewById(R.id.textview_status_header); - header.setTextSize(textSize); - header.setText(tweet.getOriginalTweet().getUser().getFormattedName()); - - ((ColoredRelativeLayout) convertedView).setAccentVisibility(tweet.getUser() == Application.getInstance().getCurrentAccount().getUser()); - } - - private void updateViewBody(Activity activity, View convertedView) { - int textSize = UserPreferenceHelper.getInstance().getTextSize(); - - TextView content = (TextView) convertedView.findViewById(R.id.textview_status_text); - content.setTextSize(textSize); - String rawText = tweet.getOriginalTweet().getText(); - content.setText(rawText); - TextView footer = (TextView) convertedView.findViewById(R.id.textview_status_footer); - footer.setTextSize(textSize - 2); - footer.setText(getFooterText()); - - ColoredRelativeLayout typedView = (ColoredRelativeLayout) convertedView; - if (tweet.isRetweet()) { - typedView.setHighlight(2); - } else if (tweet.getOriginalTweet().getMentions().contains(Application.getInstance().getCurrentAccount().getUser().getScreenName())) { - typedView.setHighlight(1); - } else { - typedView.setHighlight(0); - } - } - - private void updateViewFavorited(View convertedView) { - ImageView favorited = (ImageView) convertedView.findViewById(R.id.imageview_status_favorited); - favorited.setVisibility(tweet.isFavoritedBy(Application.getInstance().getCurrentAccount().getUserId()) ? View.VISIBLE : View.GONE); - } - - private void prepareEmbeddedTweetsAdapter(Activity activity) { - if (embeddedTweetsAdapter != null) { - return; - } - embeddedTweetsAdapter = new StatusListAdapter(activity); - - Account account = Application.getInstance().getCurrentAccount(); - for (long id : tweet.getEmbeddedStatusIDs()) { - Tweet.fetchTask(id, account).onDone(t -> { - StatusViewModel viewModel = new StatusViewModel(t, false); - embeddedTweetsAdapter.addItem(viewModel); - embeddedTweetsAdapter.update(); - }).execute(); - } - } - - private void updateViewEmbeddeds(Activity activity, View convertedView) { - final ListView embeddedStatus = (ListView) convertedView.findViewById(R.id.listview_status_embedded_status); - if (expandEmbeddedTweets) { - prepareEmbeddedTweetsAdapter(activity); - embeddedStatus.setAdapter(embeddedTweetsAdapter); - embeddedStatus.setVisibility(View.VISIBLE); - } else { - embeddedStatus.setAdapter(null); // view may be reused, set null explicitly - embeddedStatus.setVisibility(View.GONE); - } - } - - private void onClick(Activity activity) { - StatusDetailDialogFragment fragment = new StatusDetailDialogFragment(); - fragment.setStatusID(tweet.getId()); - DialogHelper.showDialog(activity, fragment); - } - - private void onIconClick(Activity activity) { - UserDetailDialogFragment dialogFragment = new UserDetailDialogFragment(); - dialogFragment.setUserID(tweet.getOriginalTweet().getUser().getId()); - DialogHelper.showDialog(activity, dialogFragment); - } -} diff --git a/app/src/main/res/layout/list_item_account.xml b/app/src/main/res/layout/list_item_account.xml index ee9631fd..ee3ed0bd 100644 --- a/app/src/main/res/layout/list_item_account.xml +++ b/app/src/main/res/layout/list_item_account.xml @@ -18,12 +18,4 @@ android:layout_margin="8dp" android:layout_weight="1" android:textSize="20sp" /> - <RadioButton - android:id="@+id/account_radio_button" - android:layout_width="wrap_content" - android:layout_height="wrap_content" - android:layout_margin="8dp" - android:clickable="false" - android:focusable="false" - android:focusableInTouchMode="false" /> </LinearLayout>
\ No newline at end of file diff --git a/app/src/main/res/menu/main.xml b/app/src/main/res/menu/main.xml index 159c0bd4..37458740 100644 --- a/app/src/main/res/menu/main.xml +++ b/app/src/main/res/menu/main.xml @@ -6,10 +6,6 @@ android:icon="@drawable/icon_edit" android:showAsAction="ifRoom"/> <item - android:id="@+id/actionbar_accounts" - android:title="@string/actionbar_accounts" - android:showAsAction="never"/> - <item android:id="@+id/actionbar_setting" android:title="@string/actionbar_setting" android:icon="@drawable/icon_settings" diff --git a/app/src/main/res/values/app_info.xml b/app/src/main/res/values/app_info.xml index a5db054e..7af80355 100644 --- a/app/src/main/res/values/app_info.xml +++ b/app/src/main/res/values/app_info.xml @@ -24,13 +24,12 @@ <resources xmlns:tools="http://schemas.android.com/tools" tools:ignore="MissingTranslation"> - <string name="app_name">xSmileEssence</string> + <string name="app_name">SE3</string> <string name="app_version_full">1.0.11 \"Dolphin\"</string> <string name="app_url">http://smileessence.lacolaco.net</string> <string name="app_author">Developed by laco0416</string> <string name="app_thanks_to">Thanks to</string> <string name="thanks_to">miz_hi, yaplus, firstspring1845, ahiru3net, unyuho123, karno, ret156, vividtomato_, hoyo203, brsywe, NTTrf, mikamikafever</string> - <string name="library_name_guava">Guava</string> <string name="library_name_twitter_text">twitter-text</string> <string name="library_name_twitter4j">twitter4j</string> <string name="library_name_crouton">Crouton</string> diff --git a/app/src/main/res/values/arrays.xml b/app/src/main/res/values/arrays.xml index 145ff9eb..7d440d91 100644 --- a/app/src/main/res/values/arrays.xml +++ b/app/src/main/res/values/arrays.xml @@ -32,4 +32,22 @@ <item>0</item> <item>1</item> </string-array> + <string-array name="message_commands"> + <item>@string/command_status_copy_text_to_clipboard</item> + </string-array> + <string-array name="user_commands"> + <item>@string/command_user_add_to_reply</item> + <item>@string/command_user_send_message</item> + <item>@string/command_user_block</item> + <item>@string/command_user_unblock</item> + <item>@string/command_user_r4s</item> + <item>@string/command_user_open_aclog</item> + </string-array> + <string-array name="status_commands"> + <item>@string/command_status_add_to_reply</item> + <item>@string/command_status_open_talk_view</item> + <item>@string/command_status_open_in_browser</item> + <item>@string/command_status_copy_text_to_clipboard</item> + <item>@string/command_status_copy_url_to_clipboard</item> + </string-array> </resources>
\ No newline at end of file diff --git a/app/src/main/res/values/keys.xml b/app/src/main/res/values/keys.xml index 47f88924..7388279c 100644 --- a/app/src/main/res/values/keys.xml +++ b/app/src/main/res/values/keys.xml @@ -24,15 +24,12 @@ <resources xmlns:tools="http://schemas.android.com/tools" tools:ignore="MissingTranslation"> - <string name="key_test_preference">testPreference</string> <string name="key_setting_text_size">textSize</string> - <string name="key_setting_accounts">manageAccounts</string> <string name="key_setting_show_confirm_dialog">confirm</string> <string name="key_setting_theme">theme</string> <string name="key_setting_application_information">appInfo</string> <string name="key_setting_licenses">licenseNotice</string> <string name="key_setting_resize_post_image">resizePostImage</string> <string name="key_last_used_search_query">lastUsedSearchQuery</string> - <string name="key_last_used_account_id">lastUsedAccountId</string> <string name="key_last_used_user_list">lastUsedUserList</string> </resources>
\ No newline at end of file diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml index 7ff3fde0..e69f3753 100644 --- a/app/src/main/res/values/strings.xml +++ b/app/src/main/res/values/strings.xml @@ -46,14 +46,6 @@ <string name="actionbar_settings">Settings</string> <string name="actionbar_edit_extraction">Edit extraction</string> <string name="actionbar_post">Post</string> - <string name="format_event_favorited">Favorited by %s</string> - <string name="format_event_unfavorited">Unfavorited by %s</string> - <string name="format_event_retweeted">Retweeted by %s</string> - <string name="format_event_mentioned">Mentioned by %s</string> - <string name="format_event_followed">Followed by %s</string> - <string name="format_event_blocked">Blocked by %s</string> - <string name="format_event_unblocked">Unblocked by %s</string> - <string name="format_event_message">Received %s\'s message</string> <string name="text_message_to_author">" #SmileEssence @uac [%s]"</string> <string name="setting_category_display_title">Display Setting</string> <string name="setting_category_display_summary">Enable at next launch.</string> @@ -73,10 +65,7 @@ <string name="setting_category_accounts_title">Accounts</string> <string name="setting_application_information_title">Application information</string> <string name="setting_licenses_title">Licenses</string> - <string name="error_setting_text_size_range">Must be between 8\-24</string> <string name="error_setting_text_size_not_number">Given value is not number</string> - <string name="error_setting_timelines_range">Must be between 1\-200</string> - <string name="error_setting_timelines_not_number">Given value is not number</string> <string name="error_intent_status_cannot_load">Failed to get tweet</string> <string name="alert_dialog_ok">OK</string> <string name="alert_dialog_cancel">Cancel</string> @@ -169,13 +158,11 @@ <string name="command_status_open_in_browser">Open in browser</string> <string name="command_status_open_talk_view">Show this talk</string> <string name="command_status_add_to_reply">Add to reply</string> - <string name="command_search_on_twitter">Search on Twitter</string> <string name="notice_error_get_user_timeline">Failed to get user timeline</string> <string name="notice_error_get_list">Failed to get list timeline</string> <string name="notices_of_files">Notices of files:</string> <string name="activity_manage_accounts">Accounts</string> <string name="actionbar_accounts">Accounts</string> <string name="notice_cant_remove_last_account">You can\'t remove last account</string> - <string name="notice_no_account_selected">No account selected. Do you want to quit?</string> <string name="notice_error_storage_permission">Write access to external storage is required.</string> </resources> diff --git a/app/src/main/res/xml/setting.xml b/app/src/main/res/xml/setting.xml index ff564f85..1e1daf02 100644 --- a/app/src/main/res/xml/setting.xml +++ b/app/src/main/res/xml/setting.xml @@ -25,13 +25,6 @@ --> <PreferenceScreen xmlns:android="http://schemas.android.com/apk/res/android"> - - <PreferenceCategory android:title="@string/setting_category_accounts_title"> - <Preference - android:key="@string/key_setting_accounts" - android:title="@string/setting_accounts_title" /> - </PreferenceCategory> - <PreferenceCategory android:summary="@string/setting_category_display_summary" android:title="@string/setting_category_display_title"> diff --git a/app/src/release2/res/values/app_info.xml b/app/src/release2/res/values/app_info.xml index 1c37d279..39aa8171 100644 --- a/app/src/release2/res/values/app_info.xml +++ b/app/src/release2/res/values/app_info.xml @@ -1,4 +1,4 @@ <resources xmlns:tools="http://schemas.android.com/tools" tools:ignore="MissingTranslation"> - <string name="app_name">ySmileEssence</string> + <string name="app_name">SE3-R2</string> </resources>
\ No newline at end of file |