Reorganizes the whole codebase.
This commit is contained in:
parent
bdca1d1c94
commit
aa2394748c
|
@ -21,12 +21,17 @@ import android.content.Intent;
|
|||
import android.content.SharedPreferences;
|
||||
import android.preference.PreferenceManager;
|
||||
import android.text.Spanned;
|
||||
import android.util.ArraySet;
|
||||
|
||||
import com.google.gson.Gson;
|
||||
import com.google.gson.GsonBuilder;
|
||||
|
||||
import com.keylesspalace.tusky.entity.Notification;
|
||||
import com.keylesspalace.tusky.json.SpannedTypeAdapter;
|
||||
import com.keylesspalace.tusky.json.StringWithEmoji;
|
||||
import com.keylesspalace.tusky.json.StringWithEmojiTypeAdapter;
|
||||
import com.keylesspalace.tusky.network.MastodonAPI;
|
||||
import com.keylesspalace.tusky.util.NotificationMaker;
|
||||
import com.keylesspalace.tusky.util.OkHttpUtils;
|
||||
|
||||
import java.util.HashSet;
|
||||
import java.util.List;
|
||||
|
|
|
@ -79,11 +79,11 @@
|
|||
android:name="com.theartofdev.edmodo.cropper.CropImageActivity"
|
||||
android:theme="@style/Base.Theme.AppCompat" />
|
||||
|
||||
<receiver android:name=".NotificationClearBroadcastReceiver" />
|
||||
<receiver android:name=".util.NotificationClearBroadcastReceiver" />
|
||||
|
||||
<service
|
||||
tools:targetApi="24"
|
||||
android:name="com.keylesspalace.tusky.TuskyTileService"
|
||||
android:name="com.keylesspalace.tusky.service.TuskyTileService"
|
||||
android:icon="@drawable/ic_send_24dp"
|
||||
android:label="Compose Toot"
|
||||
android:permission="android.permission.BIND_QUICK_SETTINGS_TILE">
|
||||
|
|
|
@ -23,6 +23,7 @@ import android.content.SharedPreferences;
|
|||
import android.graphics.drawable.Drawable;
|
||||
import android.net.Uri;
|
||||
import android.os.Bundle;
|
||||
import android.preference.PreferenceManager;
|
||||
import android.support.annotation.AttrRes;
|
||||
import android.support.annotation.Nullable;
|
||||
import android.support.design.widget.AppBarLayout;
|
||||
|
@ -43,6 +44,14 @@ import android.widget.TextView;
|
|||
|
||||
import com.keylesspalace.tusky.entity.Account;
|
||||
import com.keylesspalace.tusky.entity.Relationship;
|
||||
import com.keylesspalace.tusky.fragment.SFragment;
|
||||
import com.keylesspalace.tusky.interfaces.LinkListener;
|
||||
import com.keylesspalace.tusky.interfaces.StatusRemoveListener;
|
||||
import com.keylesspalace.tusky.pager.AccountPagerAdapter;
|
||||
import com.keylesspalace.tusky.util.LinkHelper;
|
||||
import com.keylesspalace.tusky.util.Assert;
|
||||
import com.keylesspalace.tusky.util.Log;
|
||||
import com.keylesspalace.tusky.util.ThemeUtils;
|
||||
import com.pkmmte.view.CircularImageView;
|
||||
import com.squareup.picasso.Picasso;
|
||||
|
||||
|
@ -237,7 +246,9 @@ public class AccountActivity extends BaseActivity implements SFragment.OnUserRem
|
|||
|
||||
displayName.setText(account.getDisplayName());
|
||||
|
||||
LinkHelper.setClickableText(note, account.note, null, new LinkListener() {
|
||||
boolean useCustomTabs = PreferenceManager.getDefaultSharedPreferences(this)
|
||||
.getBoolean("customTabs", true);
|
||||
LinkHelper.setClickableText(note, account.note, null, useCustomTabs, new LinkListener() {
|
||||
@Override
|
||||
public void onViewTag(String tag) {
|
||||
Intent intent = new Intent(AccountActivity.this, ViewTagActivity.class);
|
||||
|
|
|
@ -24,6 +24,8 @@ import android.support.v7.app.ActionBar;
|
|||
import android.support.v7.widget.Toolbar;
|
||||
import android.view.MenuItem;
|
||||
|
||||
import com.keylesspalace.tusky.fragment.AccountListFragment;
|
||||
|
||||
public class AccountListActivity extends BaseActivity {
|
||||
enum Type {
|
||||
BLOCKS,
|
||||
|
|
|
@ -34,6 +34,13 @@ import android.view.Menu;
|
|||
|
||||
import com.google.gson.Gson;
|
||||
import com.google.gson.GsonBuilder;
|
||||
import com.keylesspalace.tusky.json.SpannedTypeAdapter;
|
||||
import com.keylesspalace.tusky.json.StringWithEmoji;
|
||||
import com.keylesspalace.tusky.json.StringWithEmojiTypeAdapter;
|
||||
import com.keylesspalace.tusky.network.MastodonAPI;
|
||||
import com.keylesspalace.tusky.network.TuskyAPI;
|
||||
import com.keylesspalace.tusky.util.Log;
|
||||
import com.keylesspalace.tusky.util.OkHttpUtils;
|
||||
|
||||
import java.io.IOException;
|
||||
|
||||
|
@ -51,7 +58,7 @@ import retrofit2.converter.gson.GsonConverterFactory;
|
|||
public class BaseActivity extends AppCompatActivity {
|
||||
private static final String TAG = "BaseActivity"; // logging tag
|
||||
|
||||
protected MastodonAPI mastodonAPI;
|
||||
public MastodonAPI mastodonAPI;
|
||||
protected TuskyAPI tuskyAPI;
|
||||
protected Dispatcher mastodonApiDispatcher;
|
||||
protected PendingIntent serviceAlarmIntent;
|
||||
|
|
|
@ -71,6 +71,14 @@ import android.widget.TextView;
|
|||
|
||||
import com.keylesspalace.tusky.entity.Media;
|
||||
import com.keylesspalace.tusky.entity.Status;
|
||||
import com.keylesspalace.tusky.fragment.ComposeOptionsFragment;
|
||||
import com.keylesspalace.tusky.util.DownsizeImageTask;
|
||||
import com.keylesspalace.tusky.util.EditTextTyped;
|
||||
import com.keylesspalace.tusky.util.CountUpDownLatch;
|
||||
import com.keylesspalace.tusky.util.IOUtils;
|
||||
import com.keylesspalace.tusky.util.Log;
|
||||
import com.keylesspalace.tusky.util.SpanUtils;
|
||||
import com.keylesspalace.tusky.util.ThemeUtils;
|
||||
|
||||
import java.io.ByteArrayOutputStream;
|
||||
import java.io.File;
|
||||
|
@ -119,7 +127,8 @@ public class ComposeActivity extends BaseActivity implements ComposeOptionsFrag
|
|||
private Uri photoUploadUri;
|
||||
// this only exists when a status is trying to be sent, but uploads are still occurring
|
||||
private ProgressDialog finishingUploadDialog;
|
||||
@BindView(R.id.compose_edit_field) EditTextTyped textEditor;
|
||||
@BindView(R.id.compose_edit_field)
|
||||
EditTextTyped textEditor;
|
||||
@BindView(R.id.compose_media_preview_bar) LinearLayout mediaPreviewBar;
|
||||
@BindView(R.id.compose_content_warning_bar) View contentWarningBar;
|
||||
@BindView(R.id.field_content_warning) EditText contentWarningEditor;
|
||||
|
|
|
@ -36,7 +36,6 @@ import android.util.Base64;
|
|||
import android.view.Menu;
|
||||
import android.view.MenuItem;
|
||||
import android.view.View;
|
||||
import android.widget.Button;
|
||||
import android.widget.EditText;
|
||||
import android.widget.ImageButton;
|
||||
import android.widget.ImageView;
|
||||
|
@ -44,6 +43,8 @@ import android.widget.ProgressBar;
|
|||
|
||||
import com.keylesspalace.tusky.entity.Account;
|
||||
import com.keylesspalace.tusky.entity.Profile;
|
||||
import com.keylesspalace.tusky.util.IOUtils;
|
||||
import com.keylesspalace.tusky.util.Log;
|
||||
import com.pkmmte.view.CircularImageView;
|
||||
import com.squareup.picasso.Picasso;
|
||||
import com.theartofdev.edmodo.cropper.CropImage;
|
||||
|
|
|
@ -23,6 +23,10 @@ import android.support.v7.app.ActionBar;
|
|||
import android.support.v7.widget.Toolbar;
|
||||
import android.view.MenuItem;
|
||||
|
||||
import com.keylesspalace.tusky.fragment.SFragment;
|
||||
import com.keylesspalace.tusky.fragment.TimelineFragment;
|
||||
import com.keylesspalace.tusky.interfaces.StatusRemoveListener;
|
||||
|
||||
public class FavouritesActivity extends BaseActivity implements SFragment.OnUserRemovedListener {
|
||||
private StatusRemoveListener statusRemoveListener;
|
||||
|
||||
|
|
|
@ -36,6 +36,10 @@ import android.widget.TextView;
|
|||
|
||||
import com.keylesspalace.tusky.entity.AccessToken;
|
||||
import com.keylesspalace.tusky.entity.AppCredentials;
|
||||
import com.keylesspalace.tusky.network.MastodonAPI;
|
||||
import com.keylesspalace.tusky.util.CustomTabsHelper;
|
||||
import com.keylesspalace.tusky.util.Log;
|
||||
import com.keylesspalace.tusky.util.OkHttpUtils;
|
||||
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
|
|
|
@ -42,6 +42,11 @@ import com.arlib.floatingsearchview.FloatingSearchView;
|
|||
import com.arlib.floatingsearchview.suggestions.SearchSuggestionsAdapter;
|
||||
import com.arlib.floatingsearchview.suggestions.model.SearchSuggestion;
|
||||
import com.keylesspalace.tusky.entity.Account;
|
||||
import com.keylesspalace.tusky.fragment.SFragment;
|
||||
import com.keylesspalace.tusky.interfaces.StatusRemoveListener;
|
||||
import com.keylesspalace.tusky.pager.TimelinePagerAdapter;
|
||||
import com.keylesspalace.tusky.util.Log;
|
||||
import com.keylesspalace.tusky.util.ThemeUtils;
|
||||
import com.mikepenz.google_material_typeface_library.GoogleMaterial;
|
||||
import com.mikepenz.materialdrawer.AccountHeader;
|
||||
import com.mikepenz.materialdrawer.AccountHeaderBuilder;
|
||||
|
@ -82,7 +87,7 @@ public class MainActivity extends BaseActivity implements SFragment.OnUserRemove
|
|||
@BindView(R.id.tab_layout) TabLayout tabLayout;
|
||||
@BindView(R.id.pager) ViewPager viewPager;
|
||||
|
||||
FloatingActionButton composeButton;
|
||||
public FloatingActionButton composeButton;
|
||||
|
||||
@Override
|
||||
protected void onCreate(Bundle savedInstanceState) {
|
||||
|
|
|
@ -21,6 +21,8 @@ import android.os.Bundle;
|
|||
import android.preference.PreferenceManager;
|
||||
import android.support.annotation.Nullable;
|
||||
|
||||
import com.keylesspalace.tusky.fragment.PreferencesFragment;
|
||||
|
||||
public class PreferencesActivity extends BaseActivity
|
||||
implements SharedPreferences.OnSharedPreferenceChangeListener {
|
||||
private boolean themeSwitched;
|
||||
|
|
|
@ -30,7 +30,11 @@ import android.view.MenuItem;
|
|||
import android.view.View;
|
||||
import android.widget.EditText;
|
||||
|
||||
import com.keylesspalace.tusky.adapter.ReportAdapter;
|
||||
import com.keylesspalace.tusky.entity.Status;
|
||||
import com.keylesspalace.tusky.util.HtmlUtils;
|
||||
import com.keylesspalace.tusky.util.Log;
|
||||
import com.keylesspalace.tusky.util.ThemeUtils;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
|
|
|
@ -23,6 +23,10 @@ import android.support.v7.app.ActionBar;
|
|||
import android.support.v7.widget.Toolbar;
|
||||
import android.view.MenuItem;
|
||||
|
||||
import com.keylesspalace.tusky.fragment.SFragment;
|
||||
import com.keylesspalace.tusky.fragment.TimelineFragment;
|
||||
import com.keylesspalace.tusky.interfaces.StatusRemoveListener;
|
||||
|
||||
import butterknife.BindView;
|
||||
import butterknife.ButterKnife;
|
||||
|
||||
|
|
|
@ -25,6 +25,10 @@ import android.support.v7.widget.Toolbar;
|
|||
import android.view.Menu;
|
||||
import android.view.MenuItem;
|
||||
|
||||
import com.keylesspalace.tusky.fragment.SFragment;
|
||||
import com.keylesspalace.tusky.fragment.ViewThreadFragment;
|
||||
import com.keylesspalace.tusky.interfaces.StatusRemoveListener;
|
||||
|
||||
public class ViewThreadActivity extends BaseActivity implements SFragment.OnUserRemovedListener {
|
||||
Fragment viewThreadFragment;
|
||||
|
||||
|
|
|
@ -13,17 +13,18 @@
|
|||
* You should have received a copy of the GNU General Public License along with Tusky; if not,
|
||||
* see <http://www.gnu.org/licenses>. */
|
||||
|
||||
package com.keylesspalace.tusky;
|
||||
package com.keylesspalace.tusky.adapter;
|
||||
|
||||
import android.support.annotation.Nullable;
|
||||
import android.support.v7.widget.RecyclerView;
|
||||
|
||||
import com.keylesspalace.tusky.entity.Account;
|
||||
import com.keylesspalace.tusky.interfaces.AccountActionListener;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
abstract class AccountAdapter extends RecyclerView.Adapter {
|
||||
public abstract class AccountAdapter extends RecyclerView.Adapter {
|
||||
List<Account> accountList;
|
||||
AccountActionListener accountActionListener;
|
||||
|
||||
|
@ -38,7 +39,7 @@ abstract class AccountAdapter extends RecyclerView.Adapter {
|
|||
return accountList.size() + 1;
|
||||
}
|
||||
|
||||
void update(List<Account> newAccounts) {
|
||||
public void update(List<Account> newAccounts) {
|
||||
if (newAccounts == null || newAccounts.isEmpty()) {
|
||||
return;
|
||||
}
|
||||
|
@ -59,14 +60,14 @@ abstract class AccountAdapter extends RecyclerView.Adapter {
|
|||
notifyDataSetChanged();
|
||||
}
|
||||
|
||||
void addItems(List<Account> newAccounts) {
|
||||
public void addItems(List<Account> newAccounts) {
|
||||
int end = accountList.size();
|
||||
accountList.addAll(newAccounts);
|
||||
notifyItemRangeInserted(end, newAccounts.size());
|
||||
}
|
||||
|
||||
@Nullable
|
||||
Account removeItem(int position) {
|
||||
public Account removeItem(int position) {
|
||||
if (position < 0 || position >= accountList.size()) {
|
||||
return null;
|
||||
}
|
||||
|
@ -75,7 +76,7 @@ abstract class AccountAdapter extends RecyclerView.Adapter {
|
|||
return account;
|
||||
}
|
||||
|
||||
void addItem(Account account, int position) {
|
||||
public void addItem(Account account, int position) {
|
||||
if (position < 0 || position > accountList.size()) {
|
||||
return;
|
||||
}
|
|
@ -13,7 +13,7 @@
|
|||
* You should have received a copy of the GNU General Public License along with Tusky; if not,
|
||||
* see <http://www.gnu.org/licenses>. */
|
||||
|
||||
package com.keylesspalace.tusky;
|
||||
package com.keylesspalace.tusky.adapter;
|
||||
|
||||
import android.support.v7.widget.RecyclerView;
|
||||
import android.view.LayoutInflater;
|
||||
|
@ -22,18 +22,20 @@ import android.view.ViewGroup;
|
|||
import android.widget.ImageButton;
|
||||
import android.widget.TextView;
|
||||
|
||||
import com.keylesspalace.tusky.R;
|
||||
import com.keylesspalace.tusky.entity.Account;
|
||||
import com.keylesspalace.tusky.interfaces.AccountActionListener;
|
||||
import com.pkmmte.view.CircularImageView;
|
||||
import com.squareup.picasso.Picasso;
|
||||
|
||||
import butterknife.BindView;
|
||||
import butterknife.ButterKnife;
|
||||
|
||||
class BlocksAdapter extends AccountAdapter {
|
||||
public class BlocksAdapter extends AccountAdapter {
|
||||
private static final int VIEW_TYPE_BLOCKED_USER = 0;
|
||||
private static final int VIEW_TYPE_FOOTER = 1;
|
||||
|
||||
BlocksAdapter(AccountActionListener accountActionListener) {
|
||||
public BlocksAdapter(AccountActionListener accountActionListener) {
|
||||
super(accountActionListener);
|
||||
}
|
||||
|
|
@ -13,7 +13,7 @@
|
|||
* You should have received a copy of the GNU General Public License along with Tusky; if not,
|
||||
* see <http://www.gnu.org/licenses>. */
|
||||
|
||||
package com.keylesspalace.tusky;
|
||||
package com.keylesspalace.tusky.adapter;
|
||||
|
||||
import android.content.Context;
|
||||
import android.support.v7.widget.RecyclerView;
|
||||
|
@ -22,16 +22,18 @@ import android.view.View;
|
|||
import android.view.ViewGroup;
|
||||
import android.widget.TextView;
|
||||
|
||||
import com.keylesspalace.tusky.R;
|
||||
import com.keylesspalace.tusky.entity.Account;
|
||||
import com.keylesspalace.tusky.interfaces.AccountActionListener;
|
||||
import com.pkmmte.view.CircularImageView;
|
||||
import com.squareup.picasso.Picasso;
|
||||
|
||||
/** Both for follows and following lists. */
|
||||
class FollowAdapter extends AccountAdapter {
|
||||
public class FollowAdapter extends AccountAdapter {
|
||||
private static final int VIEW_TYPE_ACCOUNT = 0;
|
||||
private static final int VIEW_TYPE_FOOTER = 1;
|
||||
|
||||
FollowAdapter(AccountActionListener accountActionListener) {
|
||||
public FollowAdapter(AccountActionListener accountActionListener) {
|
||||
super(accountActionListener);
|
||||
}
|
||||
|
|
@ -13,7 +13,7 @@
|
|||
* You should have received a copy of the GNU General Public License along with Tusky; if not,
|
||||
* see <http://www.gnu.org/licenses>. */
|
||||
|
||||
package com.keylesspalace.tusky;
|
||||
package com.keylesspalace.tusky.adapter;
|
||||
|
||||
import android.support.v7.widget.RecyclerView;
|
||||
import android.view.LayoutInflater;
|
||||
|
@ -22,6 +22,8 @@ import android.view.ViewGroup;
|
|||
import android.widget.ImageButton;
|
||||
import android.widget.TextView;
|
||||
|
||||
import com.keylesspalace.tusky.interfaces.AccountActionListener;
|
||||
import com.keylesspalace.tusky.R;
|
||||
import com.keylesspalace.tusky.entity.Account;
|
||||
import com.pkmmte.view.CircularImageView;
|
||||
import com.squareup.picasso.Picasso;
|
||||
|
@ -29,11 +31,11 @@ import com.squareup.picasso.Picasso;
|
|||
import butterknife.BindView;
|
||||
import butterknife.ButterKnife;
|
||||
|
||||
class FollowRequestsAdapter extends AccountAdapter {
|
||||
public class FollowRequestsAdapter extends AccountAdapter {
|
||||
private static final int VIEW_TYPE_FOLLOW_REQUEST = 0;
|
||||
private static final int VIEW_TYPE_FOOTER = 1;
|
||||
|
||||
FollowRequestsAdapter(AccountActionListener accountActionListener) {
|
||||
public FollowRequestsAdapter(AccountActionListener accountActionListener) {
|
||||
super(accountActionListener);
|
||||
}
|
||||
|
|
@ -13,12 +13,14 @@
|
|||
* You should have received a copy of the GNU General Public License along with Tusky; if not,
|
||||
* see <http://www.gnu.org/licenses>. */
|
||||
|
||||
package com.keylesspalace.tusky;
|
||||
package com.keylesspalace.tusky.adapter;
|
||||
|
||||
import android.support.v7.widget.RecyclerView;
|
||||
import android.view.View;
|
||||
import android.widget.ProgressBar;
|
||||
|
||||
import com.keylesspalace.tusky.R;
|
||||
|
||||
class FooterViewHolder extends RecyclerView.ViewHolder {
|
||||
FooterViewHolder(View itemView) {
|
||||
super(itemView);
|
|
@ -1,4 +1,4 @@
|
|||
package com.keylesspalace.tusky;
|
||||
package com.keylesspalace.tusky.adapter;
|
||||
|
||||
import android.support.v7.widget.RecyclerView;
|
||||
import android.view.LayoutInflater;
|
||||
|
@ -7,21 +7,20 @@ import android.view.ViewGroup;
|
|||
import android.widget.ImageButton;
|
||||
import android.widget.TextView;
|
||||
|
||||
import com.keylesspalace.tusky.R;
|
||||
import com.keylesspalace.tusky.entity.Account;
|
||||
import com.keylesspalace.tusky.interfaces.AccountActionListener;
|
||||
import com.pkmmte.view.CircularImageView;
|
||||
import com.squareup.picasso.Picasso;
|
||||
|
||||
import java.util.HashSet;
|
||||
import java.util.Set;
|
||||
|
||||
import butterknife.BindView;
|
||||
import butterknife.ButterKnife;
|
||||
|
||||
class MutesAdapter extends AccountAdapter {
|
||||
public class MutesAdapter extends AccountAdapter {
|
||||
private static final int VIEW_TYPE_MUTED_USER = 0;
|
||||
private static final int VIEW_TYPE_FOOTER = 1;
|
||||
|
||||
MutesAdapter(AccountActionListener accountActionListener) {
|
||||
public MutesAdapter(AccountActionListener accountActionListener) {
|
||||
super(accountActionListener);
|
||||
}
|
||||
|
|
@ -13,7 +13,7 @@
|
|||
* You should have received a copy of the GNU General Public License along with Tusky; if not,
|
||||
* see <http://www.gnu.org/licenses>. */
|
||||
|
||||
package com.keylesspalace.tusky;
|
||||
package com.keylesspalace.tusky.adapter;
|
||||
|
||||
import android.content.Context;
|
||||
import android.graphics.Typeface;
|
||||
|
@ -29,21 +29,24 @@ import android.view.ViewGroup;
|
|||
import android.widget.ImageView;
|
||||
import android.widget.TextView;
|
||||
|
||||
import com.keylesspalace.tusky.R;
|
||||
import com.keylesspalace.tusky.entity.Notification;
|
||||
import com.keylesspalace.tusky.entity.Status;
|
||||
import com.keylesspalace.tusky.interfaces.AdapterItemRemover;
|
||||
import com.keylesspalace.tusky.interfaces.StatusActionListener;
|
||||
import com.squareup.picasso.Picasso;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Iterator;
|
||||
import java.util.List;
|
||||
|
||||
class NotificationsAdapter extends RecyclerView.Adapter implements AdapterItemRemover {
|
||||
public class NotificationsAdapter extends RecyclerView.Adapter implements AdapterItemRemover {
|
||||
private static final int VIEW_TYPE_MENTION = 0;
|
||||
private static final int VIEW_TYPE_FOOTER = 1;
|
||||
private static final int VIEW_TYPE_STATUS_NOTIFICATION = 2;
|
||||
private static final int VIEW_TYPE_FOLLOW = 3;
|
||||
|
||||
enum FooterState {
|
||||
public enum FooterState {
|
||||
EMPTY,
|
||||
END,
|
||||
LOADING
|
||||
|
@ -54,7 +57,7 @@ class NotificationsAdapter extends RecyclerView.Adapter implements AdapterItemRe
|
|||
private NotificationActionListener notificationActionListener;
|
||||
private FooterState footerState = FooterState.END;
|
||||
|
||||
NotificationsAdapter(StatusActionListener statusListener,
|
||||
public NotificationsAdapter(StatusActionListener statusListener,
|
||||
NotificationActionListener notificationActionListener) {
|
||||
super();
|
||||
notifications = new ArrayList<>();
|
||||
|
@ -63,7 +66,7 @@ class NotificationsAdapter extends RecyclerView.Adapter implements AdapterItemRe
|
|||
}
|
||||
|
||||
|
||||
void setFooterState(FooterState newFooterState) {
|
||||
public void setFooterState(FooterState newFooterState) {
|
||||
FooterState oldValue = footerState;
|
||||
footerState = newFooterState;
|
||||
if (footerState != oldValue) {
|
||||
|
@ -179,7 +182,7 @@ class NotificationsAdapter extends RecyclerView.Adapter implements AdapterItemRe
|
|||
return null;
|
||||
}
|
||||
|
||||
void update(List<Notification> newNotifications) {
|
||||
public void update(List<Notification> newNotifications) {
|
||||
if (newNotifications == null || newNotifications.isEmpty()) {
|
||||
return;
|
||||
}
|
||||
|
@ -200,7 +203,7 @@ class NotificationsAdapter extends RecyclerView.Adapter implements AdapterItemRe
|
|||
notifyDataSetChanged();
|
||||
}
|
||||
|
||||
void addItems(List<Notification> new_notifications) {
|
||||
public void addItems(List<Notification> new_notifications) {
|
||||
int end = notifications.size();
|
||||
notifications.addAll(new_notifications);
|
||||
notifyItemRangeInserted(end, new_notifications.size());
|
||||
|
@ -223,7 +226,7 @@ class NotificationsAdapter extends RecyclerView.Adapter implements AdapterItemRe
|
|||
}
|
||||
}
|
||||
|
||||
interface NotificationActionListener {
|
||||
public interface NotificationActionListener {
|
||||
void onViewAccount(String id);
|
||||
}
|
||||
|
|
@ -13,7 +13,7 @@
|
|||
* You should have received a copy of the GNU General Public License along with Tusky; if not,
|
||||
* see <http://www.gnu.org/licenses>. */
|
||||
|
||||
package com.keylesspalace.tusky;
|
||||
package com.keylesspalace.tusky.adapter;
|
||||
|
||||
import android.support.v7.widget.RecyclerView;
|
||||
import android.text.Spanned;
|
||||
|
@ -24,16 +24,18 @@ import android.widget.CheckBox;
|
|||
import android.widget.CompoundButton;
|
||||
import android.widget.TextView;
|
||||
|
||||
import com.keylesspalace.tusky.R;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
class ReportAdapter extends RecyclerView.Adapter {
|
||||
static class ReportStatus {
|
||||
public class ReportAdapter extends RecyclerView.Adapter {
|
||||
public static class ReportStatus {
|
||||
String id;
|
||||
Spanned content;
|
||||
boolean checked;
|
||||
|
||||
ReportStatus(String id, Spanned content, boolean checked) {
|
||||
public ReportStatus(String id, Spanned content, boolean checked) {
|
||||
this.id = id;
|
||||
this.content = content;
|
||||
this.checked = checked;
|
||||
|
@ -58,7 +60,7 @@ class ReportAdapter extends RecyclerView.Adapter {
|
|||
|
||||
private List<ReportStatus> statusList;
|
||||
|
||||
ReportAdapter() {
|
||||
public ReportAdapter() {
|
||||
super();
|
||||
statusList = new ArrayList<>();
|
||||
}
|
||||
|
@ -82,13 +84,13 @@ class ReportAdapter extends RecyclerView.Adapter {
|
|||
return statusList.size();
|
||||
}
|
||||
|
||||
void addItem(ReportStatus status) {
|
||||
public void addItem(ReportStatus status) {
|
||||
int end = statusList.size();
|
||||
statusList.add(status);
|
||||
notifyItemInserted(end);
|
||||
}
|
||||
|
||||
void addItems(List<ReportStatus> newStatuses) {
|
||||
public void addItems(List<ReportStatus> newStatuses) {
|
||||
int end = statusList.size();
|
||||
int added = 0;
|
||||
for (ReportStatus status : newStatuses) {
|
||||
|
@ -102,7 +104,7 @@ class ReportAdapter extends RecyclerView.Adapter {
|
|||
}
|
||||
}
|
||||
|
||||
String[] getCheckedStatusIds() {
|
||||
public String[] getCheckedStatusIds() {
|
||||
List<String> idList = new ArrayList<>();
|
||||
for (ReportStatus status : statusList) {
|
||||
if (status.checked) {
|
|
@ -13,9 +13,10 @@
|
|||
* You should have received a copy of the GNU General Public License along with Tusky; if not,
|
||||
* see <http://www.gnu.org/licenses>. */
|
||||
|
||||
package com.keylesspalace.tusky;
|
||||
package com.keylesspalace.tusky.adapter;
|
||||
|
||||
import android.content.Context;
|
||||
import android.preference.PreferenceManager;
|
||||
import android.support.annotation.Nullable;
|
||||
import android.support.v7.widget.RecyclerView;
|
||||
import android.text.Spanned;
|
||||
|
@ -26,7 +27,13 @@ import android.widget.ImageView;
|
|||
import android.widget.TextView;
|
||||
import android.widget.ToggleButton;
|
||||
|
||||
import com.keylesspalace.tusky.R;
|
||||
import com.keylesspalace.tusky.util.RoundedTransformation;
|
||||
import com.keylesspalace.tusky.interfaces.StatusActionListener;
|
||||
import com.keylesspalace.tusky.entity.Status;
|
||||
import com.keylesspalace.tusky.util.DateUtils;
|
||||
import com.keylesspalace.tusky.util.LinkHelper;
|
||||
import com.keylesspalace.tusky.util.ThemeUtils;
|
||||
import com.squareup.picasso.Picasso;
|
||||
import com.varunest.sparkbutton.SparkButton;
|
||||
import com.varunest.sparkbutton.SparkEventListener;
|
||||
|
@ -100,7 +107,10 @@ class StatusViewHolder extends RecyclerView.ViewHolder {
|
|||
StatusActionListener listener) {
|
||||
/* Redirect URLSpan's in the status content to the listener for viewing tag pages and
|
||||
* account pages. */
|
||||
LinkHelper.setClickableText(this.content, content, mentions, listener);
|
||||
Context context = this.content.getContext();
|
||||
boolean useCustomTabs = PreferenceManager.getDefaultSharedPreferences(context)
|
||||
.getBoolean("useCustomTabs", true);
|
||||
LinkHelper.setClickableText(this.content, content, mentions, useCustomTabs, listener);
|
||||
}
|
||||
|
||||
private void setAvatar(String url) {
|
|
@ -13,24 +13,27 @@
|
|||
* You should have received a copy of the GNU General Public License along with Tusky; if not,
|
||||
* see <http://www.gnu.org/licenses>. */
|
||||
|
||||
package com.keylesspalace.tusky;
|
||||
package com.keylesspalace.tusky.adapter;
|
||||
|
||||
import android.support.v7.widget.RecyclerView;
|
||||
import android.view.LayoutInflater;
|
||||
import android.view.View;
|
||||
import android.view.ViewGroup;
|
||||
|
||||
import com.keylesspalace.tusky.R;
|
||||
import com.keylesspalace.tusky.interfaces.AdapterItemRemover;
|
||||
import com.keylesspalace.tusky.interfaces.StatusActionListener;
|
||||
import com.keylesspalace.tusky.entity.Status;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
class ThreadAdapter extends RecyclerView.Adapter implements AdapterItemRemover {
|
||||
public class ThreadAdapter extends RecyclerView.Adapter implements AdapterItemRemover {
|
||||
private List<Status> statuses;
|
||||
private StatusActionListener statusActionListener;
|
||||
private int statusIndex;
|
||||
|
||||
ThreadAdapter(StatusActionListener listener) {
|
||||
public ThreadAdapter(StatusActionListener listener) {
|
||||
this.statusActionListener = listener;
|
||||
this.statuses = new ArrayList<>();
|
||||
this.statusIndex = 0;
|
||||
|
@ -55,7 +58,7 @@ class ThreadAdapter extends RecyclerView.Adapter implements AdapterItemRemover {
|
|||
return statuses.size();
|
||||
}
|
||||
|
||||
Status getItem(int position) {
|
||||
public Status getItem(int position) {
|
||||
return statuses.get(position);
|
||||
}
|
||||
|
||||
|
@ -76,7 +79,7 @@ class ThreadAdapter extends RecyclerView.Adapter implements AdapterItemRemover {
|
|||
}
|
||||
}
|
||||
|
||||
int setStatus(Status status) {
|
||||
public int setStatus(Status status) {
|
||||
if (statuses.size() > 0 && statuses.get(statusIndex).equals(status)) {
|
||||
// Do not add this status on refresh, it's already in there.
|
||||
statuses.set(statusIndex, status);
|
||||
|
@ -88,7 +91,7 @@ class ThreadAdapter extends RecyclerView.Adapter implements AdapterItemRemover {
|
|||
return i;
|
||||
}
|
||||
|
||||
void setContext(List<Status> ancestors, List<Status> descendants) {
|
||||
public void setContext(List<Status> ancestors, List<Status> descendants) {
|
||||
Status mainStatus = null;
|
||||
|
||||
// In case of refresh, remove old ancestors and descendants first. We'll remove all blindly,
|
|
@ -13,7 +13,7 @@
|
|||
* You should have received a copy of the GNU General Public License along with Tusky; if not,
|
||||
* see <http://www.gnu.org/licenses>. */
|
||||
|
||||
package com.keylesspalace.tusky;
|
||||
package com.keylesspalace.tusky.adapter;
|
||||
|
||||
import android.support.annotation.Nullable;
|
||||
import android.support.v7.widget.RecyclerView;
|
||||
|
@ -21,16 +21,19 @@ import android.view.LayoutInflater;
|
|||
import android.view.View;
|
||||
import android.view.ViewGroup;
|
||||
|
||||
import com.keylesspalace.tusky.R;
|
||||
import com.keylesspalace.tusky.interfaces.AdapterItemRemover;
|
||||
import com.keylesspalace.tusky.interfaces.StatusActionListener;
|
||||
import com.keylesspalace.tusky.entity.Status;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
class TimelineAdapter extends RecyclerView.Adapter implements AdapterItemRemover {
|
||||
public class TimelineAdapter extends RecyclerView.Adapter implements AdapterItemRemover {
|
||||
private static final int VIEW_TYPE_STATUS = 0;
|
||||
private static final int VIEW_TYPE_FOOTER = 1;
|
||||
|
||||
enum FooterState {
|
||||
public enum FooterState {
|
||||
EMPTY,
|
||||
END,
|
||||
LOADING
|
||||
|
@ -40,7 +43,7 @@ class TimelineAdapter extends RecyclerView.Adapter implements AdapterItemRemover
|
|||
private StatusActionListener statusListener;
|
||||
private FooterState footerState = FooterState.END;
|
||||
|
||||
TimelineAdapter(StatusActionListener statusListener) {
|
||||
public TimelineAdapter(StatusActionListener statusListener) {
|
||||
super();
|
||||
statuses = new ArrayList<>();
|
||||
this.statusListener = statusListener;
|
||||
|
@ -79,7 +82,7 @@ class TimelineAdapter extends RecyclerView.Adapter implements AdapterItemRemover
|
|||
}
|
||||
}
|
||||
|
||||
void setFooterState(FooterState newFooterState) {
|
||||
public void setFooterState(FooterState newFooterState) {
|
||||
FooterState oldValue = footerState;
|
||||
footerState = newFooterState;
|
||||
if (footerState != oldValue) {
|
||||
|
@ -110,7 +113,7 @@ class TimelineAdapter extends RecyclerView.Adapter implements AdapterItemRemover
|
|||
}
|
||||
}
|
||||
|
||||
void update(List<Status> newStatuses) {
|
||||
public void update(List<Status> newStatuses) {
|
||||
if (newStatuses == null || newStatuses.isEmpty()) {
|
||||
return;
|
||||
}
|
||||
|
@ -131,7 +134,7 @@ class TimelineAdapter extends RecyclerView.Adapter implements AdapterItemRemover
|
|||
notifyDataSetChanged();
|
||||
}
|
||||
|
||||
void addItems(List<Status> newStatuses) {
|
||||
public void addItems(List<Status> newStatuses) {
|
||||
int end = statuses.size();
|
||||
statuses.addAll(newStatuses);
|
||||
notifyItemRangeInserted(end, newStatuses.size());
|
||||
|
@ -142,7 +145,7 @@ class TimelineAdapter extends RecyclerView.Adapter implements AdapterItemRemover
|
|||
notifyItemRemoved(position);
|
||||
}
|
||||
|
||||
void removeAllByAccountId(String accountId) {
|
||||
public void removeAllByAccountId(String accountId) {
|
||||
for (int i = 0; i < statuses.size();) {
|
||||
Status status = statuses.get(i);
|
||||
if (accountId.equals(status.account.id)) {
|
||||
|
@ -155,7 +158,7 @@ class TimelineAdapter extends RecyclerView.Adapter implements AdapterItemRemover
|
|||
}
|
||||
|
||||
@Nullable
|
||||
Status getItem(int position) {
|
||||
public Status getItem(int position) {
|
||||
if (position >= 0 && position < statuses.size()) {
|
||||
return statuses.get(position);
|
||||
}
|
|
@ -20,8 +20,8 @@ import android.text.Spanned;
|
|||
|
||||
import com.arlib.floatingsearchview.suggestions.model.SearchSuggestion;
|
||||
import com.google.gson.annotations.SerializedName;
|
||||
import com.keylesspalace.tusky.HtmlUtils;
|
||||
import com.keylesspalace.tusky.StringWithEmoji;
|
||||
import com.keylesspalace.tusky.util.HtmlUtils;
|
||||
import com.keylesspalace.tusky.json.StringWithEmoji;
|
||||
|
||||
public class Account implements SearchSuggestion {
|
||||
public String id;
|
||||
|
|
|
@ -13,7 +13,7 @@
|
|||
* You should have received a copy of the GNU General Public License along with Tusky; if not,
|
||||
* see <http://www.gnu.org/licenses>. */
|
||||
|
||||
package com.keylesspalace.tusky;
|
||||
package com.keylesspalace.tusky.fragment;
|
||||
|
||||
import android.content.Context;
|
||||
import android.content.Intent;
|
||||
|
@ -29,8 +29,22 @@ import android.view.LayoutInflater;
|
|||
import android.view.View;
|
||||
import android.view.ViewGroup;
|
||||
|
||||
|
||||
import com.keylesspalace.tusky.AccountActivity;
|
||||
import com.keylesspalace.tusky.adapter.AccountAdapter;
|
||||
import com.keylesspalace.tusky.adapter.BlocksAdapter;
|
||||
import com.keylesspalace.tusky.adapter.FollowAdapter;
|
||||
import com.keylesspalace.tusky.adapter.FollowRequestsAdapter;
|
||||
import com.keylesspalace.tusky.adapter.MutesAdapter;
|
||||
import com.keylesspalace.tusky.BaseActivity;
|
||||
import com.keylesspalace.tusky.entity.Account;
|
||||
import com.keylesspalace.tusky.entity.Relationship;
|
||||
import com.keylesspalace.tusky.interfaces.AccountActionListener;
|
||||
import com.keylesspalace.tusky.network.MastodonAPI;
|
||||
import com.keylesspalace.tusky.R;
|
||||
import com.keylesspalace.tusky.util.EndlessOnScrollListener;
|
||||
import com.keylesspalace.tusky.util.Log;
|
||||
import com.keylesspalace.tusky.util.ThemeUtils;
|
||||
|
||||
import java.util.List;
|
||||
|
|
@ -13,7 +13,7 @@
|
|||
* You should have received a copy of the GNU General Public License along with Tusky; if not,
|
||||
* see <http://www.gnu.org/licenses>. */
|
||||
|
||||
package com.keylesspalace.tusky;
|
||||
package com.keylesspalace.tusky.fragment;
|
||||
|
||||
import android.content.Context;
|
||||
import android.content.SharedPreferences;
|
||||
|
@ -21,6 +21,8 @@ import android.os.Bundle;
|
|||
import android.support.annotation.Nullable;
|
||||
import android.support.v4.app.Fragment;
|
||||
|
||||
import com.keylesspalace.tusky.R;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
|
@ -13,7 +13,7 @@
|
|||
* You should have received a copy of the GNU General Public License along with Tusky; if not,
|
||||
* see <http://www.gnu.org/licenses>. */
|
||||
|
||||
package com.keylesspalace.tusky;
|
||||
package com.keylesspalace.tusky.fragment;
|
||||
|
||||
import android.content.Context;
|
||||
import android.content.res.ColorStateList;
|
||||
|
@ -33,8 +33,11 @@ import android.widget.CompoundButton;
|
|||
import android.widget.RadioButton;
|
||||
import android.widget.RadioGroup;
|
||||
|
||||
import com.keylesspalace.tusky.R;
|
||||
import com.keylesspalace.tusky.util.ThemeUtils;
|
||||
|
||||
public class ComposeOptionsFragment extends BottomSheetDialogFragment {
|
||||
interface Listener {
|
||||
public interface Listener {
|
||||
void onVisibilityChanged(String visibility);
|
||||
void onContentWarningChanged(boolean hideText);
|
||||
}
|
|
@ -13,7 +13,7 @@
|
|||
* You should have received a copy of the GNU General Public License along with Tusky; if not,
|
||||
* see <http://www.gnu.org/licenses>. */
|
||||
|
||||
package com.keylesspalace.tusky;
|
||||
package com.keylesspalace.tusky.fragment;
|
||||
|
||||
import android.content.Context;
|
||||
import android.content.SharedPreferences;
|
||||
|
@ -31,8 +31,17 @@ import android.view.LayoutInflater;
|
|||
import android.view.View;
|
||||
import android.view.ViewGroup;
|
||||
|
||||
|
||||
import com.keylesspalace.tusky.MainActivity;
|
||||
import com.keylesspalace.tusky.adapter.NotificationsAdapter;
|
||||
import com.keylesspalace.tusky.R;
|
||||
import com.keylesspalace.tusky.entity.Notification;
|
||||
import com.keylesspalace.tusky.entity.Status;
|
||||
import com.keylesspalace.tusky.interfaces.StatusActionListener;
|
||||
import com.keylesspalace.tusky.interfaces.StatusRemoveListener;
|
||||
import com.keylesspalace.tusky.util.EndlessOnScrollListener;
|
||||
import com.keylesspalace.tusky.util.Log;
|
||||
import com.keylesspalace.tusky.util.ThemeUtils;
|
||||
|
||||
import java.util.List;
|
||||
|
|
@ -13,11 +13,13 @@
|
|||
* You should have received a copy of the GNU General Public License along with Tusky; if not,
|
||||
* see <http://www.gnu.org/licenses>. */
|
||||
|
||||
package com.keylesspalace.tusky;
|
||||
package com.keylesspalace.tusky.fragment;
|
||||
|
||||
import android.os.Bundle;
|
||||
import android.preference.PreferenceFragment;
|
||||
|
||||
import com.keylesspalace.tusky.R;
|
||||
|
||||
public class PreferencesFragment extends PreferenceFragment {
|
||||
@Override
|
||||
public void onCreate(Bundle savedInstanceState) {
|
|
@ -13,7 +13,7 @@
|
|||
* You should have received a copy of the GNU General Public License along with Tusky; if not,
|
||||
* see <http://www.gnu.org/licenses>. */
|
||||
|
||||
package com.keylesspalace.tusky;
|
||||
package com.keylesspalace.tusky.fragment;
|
||||
|
||||
import android.content.Intent;
|
||||
import android.content.SharedPreferences;
|
||||
|
@ -27,8 +27,19 @@ import android.text.Spanned;
|
|||
import android.view.MenuItem;
|
||||
import android.view.View;
|
||||
|
||||
import com.keylesspalace.tusky.AccountActivity;
|
||||
import com.keylesspalace.tusky.BaseActivity;
|
||||
import com.keylesspalace.tusky.ComposeActivity;
|
||||
import com.keylesspalace.tusky.R;
|
||||
import com.keylesspalace.tusky.ReportActivity;
|
||||
import com.keylesspalace.tusky.ViewTagActivity;
|
||||
import com.keylesspalace.tusky.ViewThreadActivity;
|
||||
import com.keylesspalace.tusky.ViewVideoActivity;
|
||||
import com.keylesspalace.tusky.entity.Relationship;
|
||||
import com.keylesspalace.tusky.entity.Status;
|
||||
import com.keylesspalace.tusky.interfaces.AdapterItemRemover;
|
||||
import com.keylesspalace.tusky.network.MastodonAPI;
|
||||
import com.keylesspalace.tusky.util.HtmlUtils;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
@ -45,7 +56,7 @@ import retrofit2.Response;
|
|||
* overlap functionality. So, I'm momentarily leaving it and hopefully working on those will clear
|
||||
* up what needs to be where. */
|
||||
public abstract class SFragment extends BaseFragment {
|
||||
interface OnUserRemovedListener {
|
||||
public interface OnUserRemovedListener {
|
||||
void onUserRemoved(String accountId);
|
||||
}
|
||||
|
|
@ -13,7 +13,7 @@
|
|||
* You should have received a copy of the GNU General Public License along with Tusky; if not,
|
||||
* see <http://www.gnu.org/licenses>. */
|
||||
|
||||
package com.keylesspalace.tusky;
|
||||
package com.keylesspalace.tusky.fragment;
|
||||
|
||||
import android.content.Context;
|
||||
import android.content.SharedPreferences;
|
||||
|
@ -31,7 +31,15 @@ import android.view.LayoutInflater;
|
|||
import android.view.View;
|
||||
import android.view.ViewGroup;
|
||||
|
||||
import com.keylesspalace.tusky.MainActivity;
|
||||
import com.keylesspalace.tusky.R;
|
||||
import com.keylesspalace.tusky.adapter.TimelineAdapter;
|
||||
import com.keylesspalace.tusky.entity.Status;
|
||||
import com.keylesspalace.tusky.interfaces.StatusActionListener;
|
||||
import com.keylesspalace.tusky.interfaces.StatusRemoveListener;
|
||||
import com.keylesspalace.tusky.util.EndlessOnScrollListener;
|
||||
import com.keylesspalace.tusky.util.Log;
|
||||
import com.keylesspalace.tusky.util.ThemeUtils;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
|
@ -47,7 +55,7 @@ public class TimelineFragment extends SFragment implements
|
|||
|
||||
private Call<List<Status>> listCall;
|
||||
|
||||
enum Kind {
|
||||
public enum Kind {
|
||||
HOME,
|
||||
PUBLIC_LOCAL,
|
||||
PUBLIC_FEDERATED,
|
|
@ -13,7 +13,7 @@
|
|||
* You should have received a copy of the GNU General Public License along with Tusky; if not,
|
||||
* see <http://www.gnu.org/licenses>. */
|
||||
|
||||
package com.keylesspalace.tusky;
|
||||
package com.keylesspalace.tusky.fragment;
|
||||
|
||||
import android.app.AlertDialog;
|
||||
import android.app.DownloadManager;
|
||||
|
@ -36,6 +36,7 @@ import android.view.View;
|
|||
import android.view.ViewGroup;
|
||||
import android.view.WindowManager;
|
||||
|
||||
import com.keylesspalace.tusky.R;
|
||||
import com.squareup.picasso.Callback;
|
||||
import com.squareup.picasso.Picasso;
|
||||
|
|
@ -13,7 +13,7 @@
|
|||
* You should have received a copy of the GNU General Public License along with Tusky; if not,
|
||||
* see <http://www.gnu.org/licenses>. */
|
||||
|
||||
package com.keylesspalace.tusky;
|
||||
package com.keylesspalace.tusky.fragment;
|
||||
|
||||
import android.content.Context;
|
||||
import android.graphics.drawable.Drawable;
|
||||
|
@ -29,8 +29,18 @@ import android.view.LayoutInflater;
|
|||
import android.view.View;
|
||||
import android.view.ViewGroup;
|
||||
|
||||
|
||||
import com.keylesspalace.tusky.adapter.ThreadAdapter;
|
||||
import com.keylesspalace.tusky.BaseActivity;
|
||||
import com.keylesspalace.tusky.entity.Status;
|
||||
import com.keylesspalace.tusky.entity.StatusContext;
|
||||
import com.keylesspalace.tusky.network.MastodonAPI;
|
||||
import com.keylesspalace.tusky.R;
|
||||
import com.keylesspalace.tusky.interfaces.StatusActionListener;
|
||||
import com.keylesspalace.tusky.interfaces.StatusRemoveListener;
|
||||
import com.keylesspalace.tusky.util.ConversationLineItemDecoration;
|
||||
import com.keylesspalace.tusky.util.Log;
|
||||
import com.keylesspalace.tusky.util.ThemeUtils;
|
||||
|
||||
import retrofit2.Call;
|
||||
import retrofit2.Callback;
|
|
@ -13,9 +13,9 @@
|
|||
* You should have received a copy of the GNU General Public License along with Tusky; if not,
|
||||
* see <http://www.gnu.org/licenses>. */
|
||||
|
||||
package com.keylesspalace.tusky;
|
||||
package com.keylesspalace.tusky.interfaces;
|
||||
|
||||
interface AccountActionListener {
|
||||
public interface AccountActionListener {
|
||||
void onViewAccount(String id);
|
||||
void onMute(final boolean mute, final String id, final int position);
|
||||
void onBlock(final boolean block, final String id, final int position);
|
|
@ -13,8 +13,8 @@
|
|||
* You should have received a copy of the GNU General Public License along with Tusky; if not,
|
||||
* see <http://www.gnu.org/licenses>. */
|
||||
|
||||
package com.keylesspalace.tusky;
|
||||
package com.keylesspalace.tusky.interfaces;
|
||||
|
||||
interface AdapterItemRemover {
|
||||
public interface AdapterItemRemover {
|
||||
void removeItem(int position);
|
||||
}
|
|
@ -13,9 +13,9 @@
|
|||
* You should have received a copy of the GNU General Public License along with Tusky; if not,
|
||||
* see <http://www.gnu.org/licenses>. */
|
||||
|
||||
package com.keylesspalace.tusky;
|
||||
package com.keylesspalace.tusky.interfaces;
|
||||
|
||||
interface LinkListener {
|
||||
public interface LinkListener {
|
||||
void onViewTag(String tag);
|
||||
void onViewAccount(String id);
|
||||
}
|
|
@ -13,13 +13,13 @@
|
|||
* You should have received a copy of the GNU General Public License along with Tusky; if not,
|
||||
* see <http://www.gnu.org/licenses>. */
|
||||
|
||||
package com.keylesspalace.tusky;
|
||||
package com.keylesspalace.tusky.interfaces;
|
||||
|
||||
import android.view.View;
|
||||
|
||||
import com.keylesspalace.tusky.entity.Status;
|
||||
|
||||
interface StatusActionListener extends LinkListener {
|
||||
public interface StatusActionListener extends LinkListener {
|
||||
void onReply(int position);
|
||||
void onReblog(final boolean reblog, final int position);
|
||||
void onFavourite(final boolean favourite, final int position);
|
|
@ -13,8 +13,8 @@
|
|||
* You should have received a copy of the GNU General Public License along with Tusky; if not,
|
||||
* see <http://www.gnu.org/licenses>. */
|
||||
|
||||
package com.keylesspalace.tusky;
|
||||
package com.keylesspalace.tusky.interfaces;
|
||||
|
||||
interface StatusRemoveListener {
|
||||
public interface StatusRemoveListener {
|
||||
void removePostsByUser(String accountId);
|
||||
}
|
|
@ -13,7 +13,7 @@
|
|||
* You should have received a copy of the GNU General Public License along with Tusky; if not,
|
||||
* see <http://www.gnu.org/licenses>. */
|
||||
|
||||
package com.keylesspalace.tusky;
|
||||
package com.keylesspalace.tusky.json;
|
||||
|
||||
import android.text.Spanned;
|
||||
|
||||
|
@ -22,6 +22,7 @@ import com.google.gson.JsonDeserializationContext;
|
|||
import com.google.gson.JsonDeserializer;
|
||||
import com.google.gson.JsonElement;
|
||||
import com.google.gson.JsonParseException;
|
||||
import com.keylesspalace.tusky.util.HtmlUtils;
|
||||
|
||||
import java.lang.reflect.Type;
|
||||
|
|
@ -13,7 +13,7 @@
|
|||
* You should have received a copy of the GNU General Public License along with Tusky; if not,
|
||||
* see <http://www.gnu.org/licenses>. */
|
||||
|
||||
package com.keylesspalace.tusky;
|
||||
package com.keylesspalace.tusky.json;
|
||||
|
||||
/**
|
||||
* This is just a wrapper class for a String.
|
|
@ -13,7 +13,7 @@
|
|||
* You should have received a copy of the GNU General Public License along with Tusky; if not,
|
||||
* see <http://www.gnu.org/licenses>. */
|
||||
|
||||
package com.keylesspalace.tusky;
|
||||
package com.keylesspalace.tusky.json;
|
||||
|
||||
import com.emojione.Emojione;
|
||||
import com.google.gson.JsonDeserializationContext;
|
||||
|
@ -24,7 +24,7 @@ import com.google.gson.JsonParseException;
|
|||
import java.lang.reflect.Type;
|
||||
|
||||
/** This is a type-based workaround to allow for shortcode conversion when loading display names. */
|
||||
class StringWithEmojiTypeAdapter implements JsonDeserializer<StringWithEmoji> {
|
||||
public class StringWithEmojiTypeAdapter implements JsonDeserializer<StringWithEmoji> {
|
||||
@Override
|
||||
public StringWithEmoji deserialize(JsonElement json, Type typeOfT,
|
||||
JsonDeserializationContext context) throws JsonParseException {
|
|
@ -13,7 +13,7 @@
|
|||
* You should have received a copy of the GNU General Public License along with Tusky; if not,
|
||||
* see <http://www.gnu.org/licenses>. */
|
||||
|
||||
package com.keylesspalace.tusky;
|
||||
package com.keylesspalace.tusky.network;
|
||||
|
||||
import com.keylesspalace.tusky.entity.AccessToken;
|
||||
import com.keylesspalace.tusky.entity.Account;
|
|
@ -13,7 +13,7 @@
|
|||
* You should have received a copy of the GNU General Public License along with Tusky; if not,
|
||||
* see <http://www.gnu.org/licenses>. */
|
||||
|
||||
package com.keylesspalace.tusky;
|
||||
package com.keylesspalace.tusky.network;
|
||||
|
||||
import okhttp3.ResponseBody;
|
||||
import retrofit2.Call;
|
|
@ -13,7 +13,7 @@
|
|||
* You should have received a copy of the GNU General Public License along with Tusky; if not,
|
||||
* see <http://www.gnu.org/licenses>. */
|
||||
|
||||
package com.keylesspalace.tusky;
|
||||
package com.keylesspalace.tusky.pager;
|
||||
|
||||
import android.content.Context;
|
||||
import android.support.v4.app.Fragment;
|
||||
|
@ -24,23 +24,27 @@ import android.view.View;
|
|||
import android.view.ViewGroup;
|
||||
import android.widget.TextView;
|
||||
|
||||
import com.keylesspalace.tusky.R;
|
||||
import com.keylesspalace.tusky.fragment.AccountListFragment;
|
||||
import com.keylesspalace.tusky.fragment.TimelineFragment;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
class AccountPagerAdapter extends FragmentPagerAdapter {
|
||||
public class AccountPagerAdapter extends FragmentPagerAdapter {
|
||||
private Context context;
|
||||
private String accountId;
|
||||
private String[] pageTitles;
|
||||
private List<Fragment> registeredFragments;
|
||||
|
||||
AccountPagerAdapter(FragmentManager manager, Context context, String accountId) {
|
||||
public AccountPagerAdapter(FragmentManager manager, Context context, String accountId) {
|
||||
super(manager);
|
||||
this.context = context;
|
||||
this.accountId = accountId;
|
||||
registeredFragments = new ArrayList<>();
|
||||
}
|
||||
|
||||
void setPageTitles(String[] titles) {
|
||||
public void setPageTitles(String[] titles) {
|
||||
pageTitles = titles;
|
||||
}
|
||||
|
||||
|
@ -72,7 +76,7 @@ class AccountPagerAdapter extends FragmentPagerAdapter {
|
|||
return pageTitles[position];
|
||||
}
|
||||
|
||||
View getTabView(int position, ViewGroup root) {
|
||||
public View getTabView(int position, ViewGroup root) {
|
||||
View view = LayoutInflater.from(context).inflate(R.layout.tab_account, root, false);
|
||||
TextView title = (TextView) view.findViewById(R.id.title);
|
||||
title.setText(pageTitles[position]);
|
||||
|
@ -92,7 +96,7 @@ class AccountPagerAdapter extends FragmentPagerAdapter {
|
|||
super.destroyItem(container, position, object);
|
||||
}
|
||||
|
||||
List<Fragment> getRegisteredFragments() {
|
||||
public List<Fragment> getRegisteredFragments() {
|
||||
return registeredFragments;
|
||||
}
|
||||
}
|
|
@ -13,31 +13,34 @@
|
|||
* You should have received a copy of the GNU General Public License along with Tusky; if not,
|
||||
* see <http://www.gnu.org/licenses>. */
|
||||
|
||||
package com.keylesspalace.tusky;
|
||||
package com.keylesspalace.tusky.pager;
|
||||
|
||||
import android.support.v4.app.Fragment;
|
||||
import android.support.v4.app.FragmentManager;
|
||||
import android.support.v4.app.FragmentPagerAdapter;
|
||||
import android.view.ViewGroup;
|
||||
|
||||
import com.keylesspalace.tusky.fragment.NotificationsFragment;
|
||||
import com.keylesspalace.tusky.fragment.TimelineFragment;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
class TimelinePagerAdapter extends FragmentPagerAdapter {
|
||||
public class TimelinePagerAdapter extends FragmentPagerAdapter {
|
||||
private int currentFragmentIndex;
|
||||
private List<Fragment> registeredFragments;
|
||||
|
||||
TimelinePagerAdapter(FragmentManager manager) {
|
||||
public TimelinePagerAdapter(FragmentManager manager) {
|
||||
super(manager);
|
||||
currentFragmentIndex = 0;
|
||||
registeredFragments = new ArrayList<>();
|
||||
}
|
||||
|
||||
Fragment getCurrentFragment() {
|
||||
public Fragment getCurrentFragment() {
|
||||
return registeredFragments.get(currentFragmentIndex);
|
||||
}
|
||||
|
||||
List<Fragment> getRegisteredFragments() {
|
||||
public List<Fragment> getRegisteredFragments() {
|
||||
return registeredFragments;
|
||||
}
|
||||
|
|
@ -13,12 +13,14 @@
|
|||
* You should have received a copy of the GNU General Public License along with Tusky; if not,
|
||||
* see <http://www.gnu.org/licenses>. */
|
||||
|
||||
package com.keylesspalace.tusky;
|
||||
package com.keylesspalace.tusky.service;
|
||||
|
||||
import android.annotation.TargetApi;
|
||||
import android.content.Intent;
|
||||
import android.service.quicksettings.TileService;
|
||||
|
||||
import com.keylesspalace.tusky.ComposeActivity;
|
||||
|
||||
/**
|
||||
* Small Addition that adds in a QuickSettings tile that opens the Compose activity when clicked
|
||||
* Created by ztepps on 4/3/17.
|
|
@ -0,0 +1,29 @@
|
|||
/* Copyright 2017 Andrew Dawson
|
||||
*
|
||||
* This file is a part of Tusky.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify it under the terms of the
|
||||
* GNU General Public License as published by the Free Software Foundation; either version 3 of the
|
||||
* License, or (at your option) any later version.
|
||||
*
|
||||
* Tusky is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even
|
||||
* the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General
|
||||
* Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License along with Tusky; if not,
|
||||
* see <http://www.gnu.org/licenses>. */
|
||||
|
||||
package com.keylesspalace.tusky.util;
|
||||
|
||||
import com.keylesspalace.tusky.BuildConfig;
|
||||
|
||||
/** Android Studio complains about built-in assertions so this is an alternative. */
|
||||
public class Assert {
|
||||
private static boolean ENABLED = BuildConfig.DEBUG;
|
||||
|
||||
public static void expect(boolean expression) {
|
||||
if (ENABLED && !expression) {
|
||||
throw new AssertionError();
|
||||
}
|
||||
}
|
||||
}
|
|
@ -13,19 +13,17 @@
|
|||
* You should have received a copy of the GNU General Public License along with Tusky; if not,
|
||||
* see <http://www.gnu.org/licenses>. */
|
||||
|
||||
package com.keylesspalace.tusky;
|
||||
package com.keylesspalace.tusky.util;
|
||||
|
||||
import android.content.Context;
|
||||
import android.content.res.Resources;
|
||||
import android.graphics.Canvas;
|
||||
import android.graphics.drawable.Drawable;
|
||||
import android.support.v7.widget.RecyclerView;
|
||||
import android.util.TypedValue;
|
||||
import android.view.View;
|
||||
|
||||
import static android.util.TypedValue.COMPLEX_UNIT_DIP;
|
||||
import com.keylesspalace.tusky.R;
|
||||
|
||||
class ConversationLineItemDecoration extends RecyclerView.ItemDecoration {
|
||||
public class ConversationLineItemDecoration extends RecyclerView.ItemDecoration {
|
||||
private final Context mContext;
|
||||
private final Drawable mDivider;
|
||||
|
|
@ -0,0 +1,40 @@
|
|||
/* Copyright 2017 Andrew Dawson
|
||||
*
|
||||
* This file is a part of Tusky.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify it under the terms of the
|
||||
* GNU General Public License as published by the Free Software Foundation; either version 3 of the
|
||||
* License, or (at your option) any later version.
|
||||
*
|
||||
* Tusky is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even
|
||||
* the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General
|
||||
* Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License along with Tusky; if not,
|
||||
* see <http://www.gnu.org/licenses>. */
|
||||
|
||||
package com.keylesspalace.tusky.util;
|
||||
|
||||
public class CountUpDownLatch {
|
||||
private int count;
|
||||
|
||||
public CountUpDownLatch() {
|
||||
this.count = 0;
|
||||
}
|
||||
|
||||
public synchronized void countDown() {
|
||||
count--;
|
||||
notifyAll();
|
||||
}
|
||||
|
||||
public synchronized void countUp() {
|
||||
count++;
|
||||
notifyAll();
|
||||
}
|
||||
|
||||
public synchronized void await() throws InterruptedException {
|
||||
while (count != 0) {
|
||||
wait();
|
||||
}
|
||||
}
|
||||
}
|
|
@ -1,4 +1,4 @@
|
|||
package com.keylesspalace.tusky;
|
||||
package com.keylesspalace.tusky.util;
|
||||
|
||||
import android.content.ActivityNotFoundException;
|
||||
import android.content.Context;
|
||||
|
@ -11,6 +11,8 @@ import android.support.v4.content.ContextCompat;
|
|||
import android.text.style.URLSpan;
|
||||
import android.view.View;
|
||||
|
||||
import com.keylesspalace.tusky.R;
|
||||
|
||||
class CustomTabURLSpan extends URLSpan {
|
||||
CustomTabURLSpan(String url) {
|
||||
super(url);
|
|
@ -1,4 +1,4 @@
|
|||
package com.keylesspalace.tusky;
|
||||
package com.keylesspalace.tusky.util;
|
||||
import android.content.Context;
|
||||
import android.content.Intent;
|
||||
import android.content.IntentFilter;
|
|
@ -0,0 +1,50 @@
|
|||
/* Copyright 2017 Andrew Dawson
|
||||
*
|
||||
* This file is a part of Tusky.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify it under the terms of the
|
||||
* GNU General Public License as published by the Free Software Foundation; either version 3 of the
|
||||
* License, or (at your option) any later version.
|
||||
*
|
||||
* Tusky is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even
|
||||
* the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General
|
||||
* Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License along with Tusky; if not,
|
||||
* see <http://www.gnu.org/licenses>. */
|
||||
|
||||
package com.keylesspalace.tusky.util;
|
||||
|
||||
public class DateUtils {
|
||||
/* This is a rough duplicate of android.text.format.DateUtils.getRelativeTimeSpanString,
|
||||
* but even with the FORMAT_ABBREV_RELATIVE flag it wasn't abbreviating enough. */
|
||||
public static String getRelativeTimeSpanString(long then, long now) {
|
||||
final long MINUTE = 60;
|
||||
final long HOUR = 60 * MINUTE;
|
||||
final long DAY = 24 * HOUR;
|
||||
final long YEAR = 365 * DAY;
|
||||
long span = (now - then) / 1000;
|
||||
String prefix = "";
|
||||
if (span < 0) {
|
||||
prefix = "in ";
|
||||
span = -span;
|
||||
}
|
||||
String unit;
|
||||
if (span < MINUTE) {
|
||||
unit = "s";
|
||||
} else if (span < HOUR) {
|
||||
span /= MINUTE;
|
||||
unit = "m";
|
||||
} else if (span < DAY) {
|
||||
span /= HOUR;
|
||||
unit = "h";
|
||||
} else if (span < YEAR) {
|
||||
span /= DAY;
|
||||
unit = "d";
|
||||
} else {
|
||||
span /= YEAR;
|
||||
unit = "y";
|
||||
}
|
||||
return prefix + span + unit;
|
||||
}
|
||||
}
|
|
@ -13,7 +13,7 @@
|
|||
* You should have received a copy of the GNU General Public License along with Tusky; if not,
|
||||
* see <http://www.gnu.org/licenses>. */
|
||||
|
||||
package com.keylesspalace.tusky;
|
||||
package com.keylesspalace.tusky.util;
|
||||
|
||||
import android.content.ContentResolver;
|
||||
import android.graphics.Bitmap;
|
||||
|
@ -31,13 +31,13 @@ import java.io.InputStream;
|
|||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
class DownsizeImageTask extends AsyncTask<Uri, Void, Boolean> {
|
||||
public class DownsizeImageTask extends AsyncTask<Uri, Void, Boolean> {
|
||||
private int sizeLimit;
|
||||
private ContentResolver contentResolver;
|
||||
private Listener listener;
|
||||
private List<byte[]> resultList;
|
||||
|
||||
DownsizeImageTask(int sizeLimit, ContentResolver contentResolver, Listener listener) {
|
||||
public DownsizeImageTask(int sizeLimit, ContentResolver contentResolver, Listener listener) {
|
||||
this.sizeLimit = sizeLimit;
|
||||
this.contentResolver = contentResolver;
|
||||
this.listener = listener;
|
||||
|
@ -219,7 +219,7 @@ class DownsizeImageTask extends AsyncTask<Uri, Void, Boolean> {
|
|||
super.onPostExecute(successful);
|
||||
}
|
||||
|
||||
interface Listener {
|
||||
public interface Listener {
|
||||
void onSuccess(List<byte[]> contentList);
|
||||
void onFailure();
|
||||
}
|
|
@ -13,7 +13,7 @@
|
|||
* You should have received a copy of the GNU General Public License along with Tusky; if not,
|
||||
* see <http://www.gnu.org/licenses>. */
|
||||
|
||||
package com.keylesspalace.tusky;
|
||||
package com.keylesspalace.tusky.util;
|
||||
|
||||
import android.content.Context;
|
||||
import android.support.v13.view.inputmethod.EditorInfoCompat;
|
|
@ -13,12 +13,12 @@
|
|||
* You should have received a copy of the GNU General Public License along with Tusky; if not,
|
||||
* see <http://www.gnu.org/licenses>. */
|
||||
|
||||
package com.keylesspalace.tusky;
|
||||
package com.keylesspalace.tusky.util;
|
||||
|
||||
import android.support.v7.widget.LinearLayoutManager;
|
||||
import android.support.v7.widget.RecyclerView;
|
||||
|
||||
abstract class EndlessOnScrollListener extends RecyclerView.OnScrollListener {
|
||||
public abstract class EndlessOnScrollListener extends RecyclerView.OnScrollListener {
|
||||
private static final int VISIBLE_THRESHOLD = 15;
|
||||
private int currentPage;
|
||||
private int previousTotalItemCount;
|
||||
|
@ -26,7 +26,7 @@ abstract class EndlessOnScrollListener extends RecyclerView.OnScrollListener {
|
|||
private int startingPageIndex;
|
||||
private LinearLayoutManager layoutManager;
|
||||
|
||||
EndlessOnScrollListener(LinearLayoutManager layoutManager) {
|
||||
public EndlessOnScrollListener(LinearLayoutManager layoutManager) {
|
||||
this.layoutManager = layoutManager;
|
||||
currentPage = 0;
|
||||
previousTotalItemCount = 0;
|
||||
|
@ -56,7 +56,7 @@ abstract class EndlessOnScrollListener extends RecyclerView.OnScrollListener {
|
|||
}
|
||||
}
|
||||
|
||||
void reset() {
|
||||
public void reset() {
|
||||
currentPage = startingPageIndex;
|
||||
previousTotalItemCount = 0;
|
||||
loading = true;
|
|
@ -13,7 +13,7 @@
|
|||
* You should have received a copy of the GNU General Public License along with Tusky; if not,
|
||||
* see <http://www.gnu.org/licenses>. */
|
||||
|
||||
package com.keylesspalace.tusky;
|
||||
package com.keylesspalace.tusky.util;
|
||||
|
||||
import android.content.Context;
|
||||
import android.content.res.TypedArray;
|
||||
|
@ -21,6 +21,8 @@ import android.util.AttributeSet;
|
|||
import android.view.View;
|
||||
import android.view.ViewGroup;
|
||||
|
||||
import com.keylesspalace.tusky.R;
|
||||
|
||||
public class FlowLayout extends ViewGroup {
|
||||
private int paddingHorizontal; // internal padding between child views
|
||||
private int paddingVertical; //
|
|
@ -0,0 +1,54 @@
|
|||
/* Copyright 2017 Andrew Dawson
|
||||
*
|
||||
* This file is a part of Tusky.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify it under the terms of the
|
||||
* GNU General Public License as published by the Free Software Foundation; either version 3 of the
|
||||
* License, or (at your option) any later version.
|
||||
*
|
||||
* Tusky is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even
|
||||
* the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General
|
||||
* Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License along with Tusky; if not,
|
||||
* see <http://www.gnu.org/licenses>. */
|
||||
|
||||
package com.keylesspalace.tusky.util;
|
||||
|
||||
import android.os.Build;
|
||||
import android.text.Html;
|
||||
import android.text.Spanned;
|
||||
|
||||
public class HtmlUtils {
|
||||
private static CharSequence trimTrailingWhitespace(CharSequence s) {
|
||||
int i = s.length();
|
||||
do {
|
||||
i--;
|
||||
} while (i >= 0 && Character.isWhitespace(s.charAt(i)));
|
||||
return s.subSequence(0, i + 1);
|
||||
}
|
||||
|
||||
@SuppressWarnings("deprecation")
|
||||
public static Spanned fromHtml(String html) {
|
||||
Spanned result;
|
||||
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) {
|
||||
result = Html.fromHtml(html, Html.FROM_HTML_MODE_LEGACY);
|
||||
} else {
|
||||
result = Html.fromHtml(html);
|
||||
}
|
||||
/* Html.fromHtml returns trailing whitespace if the html ends in a </p> tag, which
|
||||
* all status contents do, so it should be trimmed. */
|
||||
return (Spanned) trimTrailingWhitespace(result);
|
||||
}
|
||||
|
||||
@SuppressWarnings("deprecation")
|
||||
public static String toHtml(Spanned text) {
|
||||
String result;
|
||||
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) {
|
||||
result = Html.toHtml(text, Html.TO_HTML_PARAGRAPH_LINES_CONSECUTIVE);
|
||||
} else {
|
||||
result = Html.toHtml(text);
|
||||
}
|
||||
return result;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,44 @@
|
|||
/* Copyright 2017 Andrew Dawson
|
||||
*
|
||||
* This file is a part of Tusky.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify it under the terms of the
|
||||
* GNU General Public License as published by the Free Software Foundation; either version 3 of the
|
||||
* License, or (at your option) any later version.
|
||||
*
|
||||
* Tusky is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even
|
||||
* the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General
|
||||
* Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License along with Tusky; if not,
|
||||
* see <http://www.gnu.org/licenses>. */
|
||||
|
||||
package com.keylesspalace.tusky.util;
|
||||
|
||||
import android.support.annotation.Nullable;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.io.OutputStream;
|
||||
|
||||
public class IOUtils {
|
||||
public static void closeQuietly(@Nullable InputStream stream) {
|
||||
try {
|
||||
if (stream != null) {
|
||||
stream.close();
|
||||
}
|
||||
} catch (IOException e) {
|
||||
// intentionally unhandled
|
||||
}
|
||||
}
|
||||
|
||||
public static void closeQuietly(@Nullable OutputStream stream) {
|
||||
try {
|
||||
if (stream != null) {
|
||||
stream.close();
|
||||
}
|
||||
} catch (IOException e) {
|
||||
// intentionally unhandled
|
||||
}
|
||||
}
|
||||
}
|
|
@ -13,9 +13,8 @@
|
|||
* You should have received a copy of the GNU General Public License along with Tusky; if not,
|
||||
* see <http://www.gnu.org/licenses>. */
|
||||
|
||||
package com.keylesspalace.tusky;
|
||||
package com.keylesspalace.tusky.util;
|
||||
|
||||
import android.preference.PreferenceManager;
|
||||
import android.support.annotation.Nullable;
|
||||
import android.text.SpannableStringBuilder;
|
||||
import android.text.Spanned;
|
||||
|
@ -26,14 +25,13 @@ import android.view.View;
|
|||
import android.widget.TextView;
|
||||
|
||||
import com.keylesspalace.tusky.entity.Status;
|
||||
import com.keylesspalace.tusky.interfaces.LinkListener;
|
||||
|
||||
class LinkHelper {
|
||||
static void setClickableText(TextView view, Spanned content,
|
||||
@Nullable Status.Mention[] mentions,
|
||||
final LinkListener listener) {
|
||||
public class LinkHelper {
|
||||
public static void setClickableText(TextView view, Spanned content,
|
||||
@Nullable Status.Mention[] mentions, boolean useCustomTabs,
|
||||
final LinkListener listener) {
|
||||
SpannableStringBuilder builder = new SpannableStringBuilder(content);
|
||||
boolean useCustomTabs = PreferenceManager.getDefaultSharedPreferences(view.getContext())
|
||||
.getBoolean("customTabs", true);
|
||||
URLSpan[] urlSpans = content.getSpans(0, content.length(), URLSpan.class);
|
||||
for (URLSpan span : urlSpans) {
|
||||
int start = builder.getSpanStart(span);
|
|
@ -0,0 +1,53 @@
|
|||
/* Copyright 2017 Andrew Dawson
|
||||
*
|
||||
* This file is a part of Tusky.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify it under the terms of the
|
||||
* GNU General Public License as published by the Free Software Foundation; either version 3 of the
|
||||
* License, or (at your option) any later version.
|
||||
*
|
||||
* Tusky is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even
|
||||
* the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General
|
||||
* Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License along with Tusky; if not,
|
||||
* see <http://www.gnu.org/licenses>. */
|
||||
|
||||
package com.keylesspalace.tusky.util;
|
||||
|
||||
import com.keylesspalace.tusky.BuildConfig;
|
||||
|
||||
/**A wrapper for android.util.Log that allows for disabling logging, such as for release builds.*/
|
||||
public class Log {
|
||||
private static final boolean LOGGING_ENABLED = BuildConfig.DEBUG;
|
||||
|
||||
public static void i(String tag, String string) {
|
||||
if (LOGGING_ENABLED) {
|
||||
android.util.Log.i(tag, string);
|
||||
}
|
||||
}
|
||||
|
||||
public static void e(String tag, String string) {
|
||||
if (LOGGING_ENABLED) {
|
||||
android.util.Log.e(tag, string);
|
||||
}
|
||||
}
|
||||
|
||||
public static void d(String tag, String string) {
|
||||
if (LOGGING_ENABLED) {
|
||||
android.util.Log.d(tag, string);
|
||||
}
|
||||
}
|
||||
|
||||
public static void v(String tag, String string) {
|
||||
if (LOGGING_ENABLED) {
|
||||
android.util.Log.v(tag, string);
|
||||
}
|
||||
}
|
||||
|
||||
public static void w(String tag, String string) {
|
||||
if (LOGGING_ENABLED) {
|
||||
android.util.Log.w(tag, string);
|
||||
}
|
||||
}
|
||||
}
|
|
@ -13,7 +13,7 @@
|
|||
* You should have received a copy of the GNU General Public License along with Tusky; if not,
|
||||
* see <http://www.gnu.org/licenses>. */
|
||||
|
||||
package com.keylesspalace.tusky;
|
||||
package com.keylesspalace.tusky.util;
|
||||
|
||||
import android.content.BroadcastReceiver;
|
||||
import android.content.Context;
|
|
@ -13,7 +13,7 @@
|
|||
* You should have received a copy of the GNU General Public License along with Tusky; if not,
|
||||
* see <http://www.gnu.org/licenses>. */
|
||||
|
||||
package com.keylesspalace.tusky;
|
||||
package com.keylesspalace.tusky.util;
|
||||
|
||||
import android.app.NotificationManager;
|
||||
import android.app.PendingIntent;
|
||||
|
@ -29,6 +29,8 @@ import android.support.annotation.Nullable;
|
|||
import android.support.v4.app.NotificationCompat;
|
||||
import android.support.v4.app.TaskStackBuilder;
|
||||
|
||||
import com.keylesspalace.tusky.MainActivity;
|
||||
import com.keylesspalace.tusky.R;
|
||||
import com.keylesspalace.tusky.entity.Notification;
|
||||
import com.squareup.picasso.Picasso;
|
||||
import com.squareup.picasso.Target;
|
||||
|
@ -36,8 +38,8 @@ import com.squareup.picasso.Target;
|
|||
import org.json.JSONArray;
|
||||
import org.json.JSONException;
|
||||
|
||||
class NotificationMaker {
|
||||
static void make(final Context context, final int notifyId, Notification body) {
|
||||
public class NotificationMaker {
|
||||
public static void make(final Context context, final int notifyId, Notification body) {
|
||||
final SharedPreferences preferences =
|
||||
PreferenceManager.getDefaultSharedPreferences(context);
|
||||
final SharedPreferences notificationPreferences = context.getSharedPreferences(
|
|
@ -0,0 +1,244 @@
|
|||
/* Copyright 2017 Andrew Dawson
|
||||
*
|
||||
* This file is part of Tusky.
|
||||
*
|
||||
* Tusky is free software: you can redistribute it and/or modify it under the terms of the GNU
|
||||
* Lesser General Public License as published by the Free Software Foundation, either version 3 of
|
||||
* the License, or (at your option) any later version.
|
||||
*
|
||||
* Tusky is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even
|
||||
* the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser
|
||||
* General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public License along with Tusky. If
|
||||
* not, see <http://www.gnu.org/licenses/>. */
|
||||
|
||||
package com.keylesspalace.tusky.util;
|
||||
|
||||
import android.os.Build;
|
||||
import android.support.annotation.NonNull;
|
||||
|
||||
import com.keylesspalace.tusky.BuildConfig;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.net.InetAddress;
|
||||
import java.net.Socket;
|
||||
import java.security.KeyManagementException;
|
||||
import java.security.KeyStore;
|
||||
import java.security.KeyStoreException;
|
||||
import java.security.NoSuchAlgorithmException;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.List;
|
||||
|
||||
import javax.net.ssl.SSLContext;
|
||||
import javax.net.ssl.SSLSocket;
|
||||
import javax.net.ssl.SSLSocketFactory;
|
||||
import javax.net.ssl.TrustManager;
|
||||
import javax.net.ssl.TrustManagerFactory;
|
||||
import javax.net.ssl.X509TrustManager;
|
||||
|
||||
import okhttp3.ConnectionSpec;
|
||||
import okhttp3.Interceptor;
|
||||
import okhttp3.OkHttpClient;
|
||||
import okhttp3.Request;
|
||||
import okhttp3.Response;
|
||||
|
||||
public class OkHttpUtils {
|
||||
static final String TAG = "OkHttpUtils"; // logging tag
|
||||
|
||||
/**
|
||||
* Makes a Builder with the maximum range of TLS versions and cipher suites enabled.
|
||||
*
|
||||
* It first tries the "approved" list of cipher suites given in OkHttp (the default in
|
||||
* ConnectionSpec.MODERN_TLS) and if that doesn't work falls back to the set of ALL enabled,
|
||||
* then falls back to plain http.
|
||||
*
|
||||
* API level 24 has a regression in elliptic curves where it only supports secp256r1, so this
|
||||
* first tries a fallback without elliptic curves at all, and then tries them after.
|
||||
*
|
||||
* TLS 1.1 and 1.2 have to be manually enabled on API levels 16-20.
|
||||
*/
|
||||
@NonNull
|
||||
public static OkHttpClient.Builder getCompatibleClientBuilder() {
|
||||
ConnectionSpec fallback = new ConnectionSpec.Builder(ConnectionSpec.MODERN_TLS)
|
||||
.allEnabledCipherSuites()
|
||||
.supportsTlsExtensions(true)
|
||||
.build();
|
||||
|
||||
List<ConnectionSpec> specList = new ArrayList<>();
|
||||
specList.add(ConnectionSpec.MODERN_TLS);
|
||||
addNougatFixConnectionSpec(specList);
|
||||
specList.add(fallback);
|
||||
specList.add(ConnectionSpec.CLEARTEXT);
|
||||
|
||||
OkHttpClient.Builder builder = new OkHttpClient.Builder()
|
||||
.addInterceptor(getUserAgentInterceptor())
|
||||
.connectionSpecs(specList);
|
||||
|
||||
return enableHigherTlsOnPreLollipop(builder);
|
||||
}
|
||||
|
||||
@NonNull
|
||||
public static OkHttpClient getCompatibleClient() {
|
||||
return getCompatibleClientBuilder().build();
|
||||
}
|
||||
|
||||
/**
|
||||
* Add a custom User-Agent that contains Tusky & Android Version to all requests
|
||||
* Example:
|
||||
* User-Agent: Tusky/1.1.2 Android/5.0.2
|
||||
*/
|
||||
@NonNull
|
||||
private static Interceptor getUserAgentInterceptor() {
|
||||
return new Interceptor() {
|
||||
@Override
|
||||
public Response intercept(Chain chain) throws IOException {
|
||||
Request originalRequest = chain.request();
|
||||
Request requestWithUserAgent = originalRequest.newBuilder()
|
||||
.header("User-Agent", "Tusky/"+ BuildConfig.VERSION_NAME+" Android/"+Build.VERSION.RELEASE)
|
||||
.build();
|
||||
return chain.proceed(requestWithUserAgent);
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Android version Nougat has a regression where elliptic curve cipher suites are supported, but
|
||||
* only the curve secp256r1 is allowed. So, first it's best to just disable all elliptic
|
||||
* ciphers, try the connection, and fall back to the all cipher suites enabled list after.
|
||||
*/
|
||||
private static void addNougatFixConnectionSpec(List<ConnectionSpec> specList) {
|
||||
if (Build.VERSION.SDK_INT != Build.VERSION_CODES.N) {
|
||||
return;
|
||||
}
|
||||
SSLSocketFactory socketFactory;
|
||||
try {
|
||||
TrustManagerFactory trustManagerFactory = TrustManagerFactory.getInstance(
|
||||
TrustManagerFactory.getDefaultAlgorithm());
|
||||
trustManagerFactory.init((KeyStore) null);
|
||||
TrustManager[] trustManagers = trustManagerFactory.getTrustManagers();
|
||||
if (trustManagers.length != 1 || !(trustManagers[0] instanceof X509TrustManager)) {
|
||||
throw new IllegalStateException("Unexpected default trust managers:"
|
||||
+ Arrays.toString(trustManagers));
|
||||
}
|
||||
|
||||
X509TrustManager trustManager = (X509TrustManager) trustManagers[0];
|
||||
|
||||
SSLContext sslContext = SSLContext.getInstance("TLS");
|
||||
sslContext.init(null, new TrustManager[] { trustManager }, null);
|
||||
socketFactory = sslContext.getSocketFactory();
|
||||
} catch (NoSuchAlgorithmException|KeyStoreException|KeyManagementException e) {
|
||||
Log.e(TAG, "Failed obtaining the SSL socket factory.");
|
||||
return;
|
||||
}
|
||||
String[] cipherSuites = socketFactory.getDefaultCipherSuites();
|
||||
ArrayList<String> allowedList = new ArrayList<>();
|
||||
for (String suite : cipherSuites) {
|
||||
if (!suite.contains("ECDH")) {
|
||||
allowedList.add(suite);
|
||||
}
|
||||
}
|
||||
ConnectionSpec spec = new ConnectionSpec.Builder(ConnectionSpec.MODERN_TLS)
|
||||
.cipherSuites(allowedList.toArray(new String[0]))
|
||||
.supportsTlsExtensions(true)
|
||||
.build();
|
||||
specList.add(spec);
|
||||
}
|
||||
|
||||
private static OkHttpClient.Builder enableHigherTlsOnPreLollipop(OkHttpClient.Builder builder) {
|
||||
if (Build.VERSION.SDK_INT >= 16 && Build.VERSION.SDK_INT < 22) {
|
||||
try {
|
||||
TrustManagerFactory trustManagerFactory = TrustManagerFactory.getInstance(
|
||||
TrustManagerFactory.getDefaultAlgorithm());
|
||||
trustManagerFactory.init((KeyStore) null);
|
||||
TrustManager[] trustManagers = trustManagerFactory.getTrustManagers();
|
||||
if (trustManagers.length != 1 || !(trustManagers[0] instanceof X509TrustManager)) {
|
||||
throw new IllegalStateException("Unexpected default trust managers:"
|
||||
+ Arrays.toString(trustManagers));
|
||||
}
|
||||
|
||||
X509TrustManager trustManager = (X509TrustManager) trustManagers[0];
|
||||
|
||||
SSLContext sslContext = SSLContext.getInstance("TLS");
|
||||
sslContext.init(null, new TrustManager[] { trustManager }, null);
|
||||
SSLSocketFactory sslSocketFactory = sslContext.getSocketFactory();
|
||||
|
||||
builder.sslSocketFactory(new SSLSocketFactoryCompat(sslSocketFactory),
|
||||
trustManager);
|
||||
} catch (NoSuchAlgorithmException|KeyStoreException|KeyManagementException e) {
|
||||
Log.e(TAG, "Failed enabling TLS 1.1 & 1.2. " + e.getMessage());
|
||||
}
|
||||
}
|
||||
|
||||
return builder;
|
||||
}
|
||||
|
||||
private static class SSLSocketFactoryCompat extends SSLSocketFactory {
|
||||
private static final String[] DESIRED_TLS_VERSIONS = { "TLSv1", "TLSv1.1", "TLSv1.2",
|
||||
"TLSv1.3" };
|
||||
|
||||
final SSLSocketFactory delegate;
|
||||
|
||||
SSLSocketFactoryCompat(SSLSocketFactory base) {
|
||||
this.delegate = base;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String[] getDefaultCipherSuites() {
|
||||
return delegate.getDefaultCipherSuites();
|
||||
}
|
||||
|
||||
@Override
|
||||
public String[] getSupportedCipherSuites() {
|
||||
return delegate.getSupportedCipherSuites();
|
||||
}
|
||||
|
||||
@Override
|
||||
public Socket createSocket(Socket s, String host, int port, boolean autoClose)
|
||||
throws IOException {
|
||||
return patch(delegate.createSocket(s, host, port, autoClose));
|
||||
}
|
||||
|
||||
@Override
|
||||
public Socket createSocket(String host, int port) throws IOException {
|
||||
return patch(delegate.createSocket(host, port));
|
||||
}
|
||||
|
||||
@Override
|
||||
public Socket createSocket(String host, int port, InetAddress localHost, int localPort)
|
||||
throws IOException {
|
||||
return patch(delegate.createSocket(host, port, localHost, localPort));
|
||||
}
|
||||
|
||||
@Override
|
||||
public Socket createSocket(InetAddress host, int port) throws IOException {
|
||||
return patch(delegate.createSocket(host, port));
|
||||
}
|
||||
|
||||
@Override
|
||||
public Socket createSocket(InetAddress address, int port, InetAddress localAddress,
|
||||
int localPort) throws IOException {
|
||||
return patch(delegate.createSocket(address, port, localAddress, localPort));
|
||||
}
|
||||
|
||||
@NonNull
|
||||
private static String[] getMatches(String[] wanted, String[] have) {
|
||||
List<String> a = new ArrayList<>(Arrays.asList(wanted));
|
||||
List<String> b = Arrays.asList(have);
|
||||
a.retainAll(b);
|
||||
return a.toArray(new String[0]);
|
||||
}
|
||||
|
||||
private Socket patch(Socket socket) {
|
||||
if (socket instanceof SSLSocket) {
|
||||
SSLSocket sslSocket = (SSLSocket) socket;
|
||||
String[] protocols = getMatches(DESIRED_TLS_VERSIONS,
|
||||
sslSocket.getSupportedProtocols());
|
||||
sslSocket.setEnabledProtocols(protocols);
|
||||
}
|
||||
return socket;
|
||||
}
|
||||
}
|
||||
}
|
|
@ -13,7 +13,7 @@
|
|||
* You should have received a copy of the GNU General Public License along with Tusky; if not,
|
||||
* see <http://www.gnu.org/licenses>. */
|
||||
|
||||
package com.keylesspalace.tusky;
|
||||
package com.keylesspalace.tusky.util;
|
||||
|
||||
import android.graphics.Bitmap;
|
||||
import android.graphics.BitmapShader;
|
|
@ -0,0 +1,129 @@
|
|||
/* Copyright 2017 Andrew Dawson
|
||||
*
|
||||
* This file is a part of Tusky.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify it under the terms of the
|
||||
* GNU General Public License as published by the Free Software Foundation; either version 3 of the
|
||||
* License, or (at your option) any later version.
|
||||
*
|
||||
* Tusky is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even
|
||||
* the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General
|
||||
* Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License along with Tusky; if not,
|
||||
* see <http://www.gnu.org/licenses>. */
|
||||
|
||||
package com.keylesspalace.tusky.util;
|
||||
|
||||
import android.text.Spannable;
|
||||
import android.text.Spanned;
|
||||
import android.text.style.ForegroundColorSpan;
|
||||
|
||||
public class SpanUtils {
|
||||
private static class FindCharsResult {
|
||||
int charIndex;
|
||||
int stringIndex;
|
||||
|
||||
FindCharsResult() {
|
||||
charIndex = -1;
|
||||
stringIndex = -1;
|
||||
}
|
||||
}
|
||||
|
||||
private static FindCharsResult findChars(String string, int fromIndex, char[] chars) {
|
||||
FindCharsResult result = new FindCharsResult();
|
||||
final int length = string.length();
|
||||
for (int i = fromIndex; i < length; i++) {
|
||||
char c = string.charAt(i);
|
||||
for (int j = 0; j < chars.length; j++) {
|
||||
if (chars[j] == c) {
|
||||
result.charIndex = j;
|
||||
result.stringIndex = i;
|
||||
return result;
|
||||
}
|
||||
}
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
private static FindCharsResult findStart(String string, int fromIndex, char[] chars) {
|
||||
final int length = string.length();
|
||||
while (fromIndex < length) {
|
||||
FindCharsResult found = findChars(string, fromIndex, chars);
|
||||
int i = found.stringIndex;
|
||||
if (i < 0) {
|
||||
break;
|
||||
} else if (i == 0 || i >= 1 && Character.isWhitespace(string.codePointBefore(i))) {
|
||||
return found;
|
||||
} else {
|
||||
fromIndex = i + 1;
|
||||
}
|
||||
}
|
||||
return new FindCharsResult();
|
||||
}
|
||||
|
||||
private static int findEndOfHashtag(String string, int fromIndex) {
|
||||
final int length = string.length();
|
||||
for (int i = fromIndex + 1; i < length;) {
|
||||
int codepoint = string.codePointAt(i);
|
||||
if (Character.isWhitespace(codepoint)) {
|
||||
return i;
|
||||
} else if (codepoint == '#') {
|
||||
return -1;
|
||||
}
|
||||
i += Character.charCount(codepoint);
|
||||
}
|
||||
return length;
|
||||
}
|
||||
|
||||
private static int findEndOfMention(String string, int fromIndex) {
|
||||
int atCount = 0;
|
||||
final int length = string.length();
|
||||
for (int i = fromIndex + 1; i < length;) {
|
||||
int codepoint = string.codePointAt(i);
|
||||
if (Character.isWhitespace(codepoint)) {
|
||||
return i;
|
||||
} else if (codepoint == '@') {
|
||||
atCount += 1;
|
||||
if (atCount >= 2) {
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
i += Character.charCount(codepoint);
|
||||
}
|
||||
return length;
|
||||
}
|
||||
|
||||
public static void highlightSpans(Spannable text, int colour) {
|
||||
// Strip all existing colour spans.
|
||||
int n = text.length();
|
||||
ForegroundColorSpan[] oldSpans = text.getSpans(0, n, ForegroundColorSpan.class);
|
||||
for (int i = oldSpans.length - 1; i >= 0; i--) {
|
||||
text.removeSpan(oldSpans[i]);
|
||||
}
|
||||
// Colour the mentions and hashtags.
|
||||
String string = text.toString();
|
||||
int start;
|
||||
int end = 0;
|
||||
while (end < n) {
|
||||
char[] chars = { '#', '@' };
|
||||
FindCharsResult found = findStart(string, end, chars);
|
||||
start = found.stringIndex;
|
||||
if (start < 0) {
|
||||
break;
|
||||
}
|
||||
if (found.charIndex == 0) {
|
||||
end = findEndOfHashtag(string, start);
|
||||
} else if (found.charIndex == 1) {
|
||||
end = findEndOfMention(string, start);
|
||||
} else {
|
||||
break;
|
||||
}
|
||||
if (end < 0) {
|
||||
break;
|
||||
}
|
||||
text.setSpan(new ForegroundColorSpan(colour), start, end,
|
||||
Spanned.SPAN_INCLUSIVE_EXCLUSIVE);
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,68 @@
|
|||
/* Copyright 2017 Andrew Dawson
|
||||
*
|
||||
* This file is a part of Tusky.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify it under the terms of the
|
||||
* GNU General Public License as published by the Free Software Foundation; either version 3 of the
|
||||
* License, or (at your option) any later version.
|
||||
*
|
||||
* Tusky is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even
|
||||
* the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General
|
||||
* Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License along with Tusky; if not,
|
||||
* see <http://www.gnu.org/licenses>. */
|
||||
|
||||
package com.keylesspalace.tusky.util;
|
||||
|
||||
import android.content.Context;
|
||||
import android.graphics.Color;
|
||||
import android.graphics.PorterDuff;
|
||||
import android.graphics.drawable.Drawable;
|
||||
import android.support.annotation.AttrRes;
|
||||
import android.support.annotation.ColorInt;
|
||||
import android.support.annotation.DrawableRes;
|
||||
import android.support.v4.content.ContextCompat;
|
||||
import android.util.TypedValue;
|
||||
import android.widget.ImageView;
|
||||
|
||||
public class ThemeUtils {
|
||||
public static Drawable getDrawable(Context context, @AttrRes int attribute,
|
||||
@DrawableRes int fallbackDrawable) {
|
||||
TypedValue value = new TypedValue();
|
||||
@DrawableRes int resourceId;
|
||||
if (context.getTheme().resolveAttribute(attribute, value, true)) {
|
||||
resourceId = value.resourceId;
|
||||
} else {
|
||||
resourceId = fallbackDrawable;
|
||||
}
|
||||
return ContextCompat.getDrawable(context, resourceId);
|
||||
}
|
||||
|
||||
public static @DrawableRes int getDrawableId(Context context, @AttrRes int attribute,
|
||||
@DrawableRes int fallbackDrawableId) {
|
||||
TypedValue value = new TypedValue();
|
||||
if (context.getTheme().resolveAttribute(attribute, value, true)) {
|
||||
return value.resourceId;
|
||||
} else {
|
||||
return fallbackDrawableId;
|
||||
}
|
||||
}
|
||||
|
||||
public static @ColorInt int getColor(Context context, @AttrRes int attribute) {
|
||||
TypedValue value = new TypedValue();
|
||||
if (context.getTheme().resolveAttribute(attribute, value, true)) {
|
||||
return value.data;
|
||||
} else {
|
||||
return Color.BLACK;
|
||||
}
|
||||
}
|
||||
|
||||
public static void setImageViewTint(ImageView view, @AttrRes int attribute) {
|
||||
view.setColorFilter(getColor(view.getContext(), attribute), PorterDuff.Mode.SRC_IN);
|
||||
}
|
||||
|
||||
public static void setDrawableTint(Context context, Drawable drawable, @AttrRes int attribute) {
|
||||
drawable.setColorFilter(getColor(context, attribute), PorterDuff.Mode.SRC_IN);
|
||||
}
|
||||
}
|
|
@ -54,7 +54,7 @@
|
|||
android:paddingLeft="16dp"
|
||||
android:paddingRight="16dp">
|
||||
|
||||
<com.keylesspalace.tusky.EditTextTyped
|
||||
<com.keylesspalace.tusky.util.EditTextTyped
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
android:id="@+id/compose_edit_field"
|
||||
|
|
|
@ -95,7 +95,7 @@
|
|||
|
||||
</RelativeLayout>
|
||||
|
||||
<com.keylesspalace.tusky.FlowLayout
|
||||
<com.keylesspalace.tusky.util.FlowLayout
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:id="@+id/status_content_warning_bar"
|
||||
|
@ -127,7 +127,7 @@
|
|||
android:textAllCaps="true"
|
||||
android:background="?attr/content_warning_button" />
|
||||
|
||||
</com.keylesspalace.tusky.FlowLayout>
|
||||
</com.keylesspalace.tusky.util.FlowLayout>
|
||||
|
||||
<TextView
|
||||
android:id="@+id/status_content"
|
||||
|
|
Loading…
Reference in New Issue