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.content.SharedPreferences;
|
||||||
import android.preference.PreferenceManager;
|
import android.preference.PreferenceManager;
|
||||||
import android.text.Spanned;
|
import android.text.Spanned;
|
||||||
import android.util.ArraySet;
|
|
||||||
|
|
||||||
import com.google.gson.Gson;
|
import com.google.gson.Gson;
|
||||||
import com.google.gson.GsonBuilder;
|
import com.google.gson.GsonBuilder;
|
||||||
|
|
||||||
import com.keylesspalace.tusky.entity.Notification;
|
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.HashSet;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
|
|
@ -79,11 +79,11 @@
|
||||||
android:name="com.theartofdev.edmodo.cropper.CropImageActivity"
|
android:name="com.theartofdev.edmodo.cropper.CropImageActivity"
|
||||||
android:theme="@style/Base.Theme.AppCompat" />
|
android:theme="@style/Base.Theme.AppCompat" />
|
||||||
|
|
||||||
<receiver android:name=".NotificationClearBroadcastReceiver" />
|
<receiver android:name=".util.NotificationClearBroadcastReceiver" />
|
||||||
|
|
||||||
<service
|
<service
|
||||||
tools:targetApi="24"
|
tools:targetApi="24"
|
||||||
android:name="com.keylesspalace.tusky.TuskyTileService"
|
android:name="com.keylesspalace.tusky.service.TuskyTileService"
|
||||||
android:icon="@drawable/ic_send_24dp"
|
android:icon="@drawable/ic_send_24dp"
|
||||||
android:label="Compose Toot"
|
android:label="Compose Toot"
|
||||||
android:permission="android.permission.BIND_QUICK_SETTINGS_TILE">
|
android:permission="android.permission.BIND_QUICK_SETTINGS_TILE">
|
||||||
|
|
|
@ -23,6 +23,7 @@ import android.content.SharedPreferences;
|
||||||
import android.graphics.drawable.Drawable;
|
import android.graphics.drawable.Drawable;
|
||||||
import android.net.Uri;
|
import android.net.Uri;
|
||||||
import android.os.Bundle;
|
import android.os.Bundle;
|
||||||
|
import android.preference.PreferenceManager;
|
||||||
import android.support.annotation.AttrRes;
|
import android.support.annotation.AttrRes;
|
||||||
import android.support.annotation.Nullable;
|
import android.support.annotation.Nullable;
|
||||||
import android.support.design.widget.AppBarLayout;
|
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.Account;
|
||||||
import com.keylesspalace.tusky.entity.Relationship;
|
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.pkmmte.view.CircularImageView;
|
||||||
import com.squareup.picasso.Picasso;
|
import com.squareup.picasso.Picasso;
|
||||||
|
|
||||||
|
@ -237,7 +246,9 @@ public class AccountActivity extends BaseActivity implements SFragment.OnUserRem
|
||||||
|
|
||||||
displayName.setText(account.getDisplayName());
|
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
|
@Override
|
||||||
public void onViewTag(String tag) {
|
public void onViewTag(String tag) {
|
||||||
Intent intent = new Intent(AccountActivity.this, ViewTagActivity.class);
|
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.support.v7.widget.Toolbar;
|
||||||
import android.view.MenuItem;
|
import android.view.MenuItem;
|
||||||
|
|
||||||
|
import com.keylesspalace.tusky.fragment.AccountListFragment;
|
||||||
|
|
||||||
public class AccountListActivity extends BaseActivity {
|
public class AccountListActivity extends BaseActivity {
|
||||||
enum Type {
|
enum Type {
|
||||||
BLOCKS,
|
BLOCKS,
|
||||||
|
|
|
@ -34,6 +34,13 @@ import android.view.Menu;
|
||||||
|
|
||||||
import com.google.gson.Gson;
|
import com.google.gson.Gson;
|
||||||
import com.google.gson.GsonBuilder;
|
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;
|
import java.io.IOException;
|
||||||
|
|
||||||
|
@ -51,7 +58,7 @@ import retrofit2.converter.gson.GsonConverterFactory;
|
||||||
public class BaseActivity extends AppCompatActivity {
|
public class BaseActivity extends AppCompatActivity {
|
||||||
private static final String TAG = "BaseActivity"; // logging tag
|
private static final String TAG = "BaseActivity"; // logging tag
|
||||||
|
|
||||||
protected MastodonAPI mastodonAPI;
|
public MastodonAPI mastodonAPI;
|
||||||
protected TuskyAPI tuskyAPI;
|
protected TuskyAPI tuskyAPI;
|
||||||
protected Dispatcher mastodonApiDispatcher;
|
protected Dispatcher mastodonApiDispatcher;
|
||||||
protected PendingIntent serviceAlarmIntent;
|
protected PendingIntent serviceAlarmIntent;
|
||||||
|
|
|
@ -71,6 +71,14 @@ import android.widget.TextView;
|
||||||
|
|
||||||
import com.keylesspalace.tusky.entity.Media;
|
import com.keylesspalace.tusky.entity.Media;
|
||||||
import com.keylesspalace.tusky.entity.Status;
|
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.ByteArrayOutputStream;
|
||||||
import java.io.File;
|
import java.io.File;
|
||||||
|
@ -119,7 +127,8 @@ public class ComposeActivity extends BaseActivity implements ComposeOptionsFrag
|
||||||
private Uri photoUploadUri;
|
private Uri photoUploadUri;
|
||||||
// this only exists when a status is trying to be sent, but uploads are still occurring
|
// this only exists when a status is trying to be sent, but uploads are still occurring
|
||||||
private ProgressDialog finishingUploadDialog;
|
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_media_preview_bar) LinearLayout mediaPreviewBar;
|
||||||
@BindView(R.id.compose_content_warning_bar) View contentWarningBar;
|
@BindView(R.id.compose_content_warning_bar) View contentWarningBar;
|
||||||
@BindView(R.id.field_content_warning) EditText contentWarningEditor;
|
@BindView(R.id.field_content_warning) EditText contentWarningEditor;
|
||||||
|
|
|
@ -36,7 +36,6 @@ import android.util.Base64;
|
||||||
import android.view.Menu;
|
import android.view.Menu;
|
||||||
import android.view.MenuItem;
|
import android.view.MenuItem;
|
||||||
import android.view.View;
|
import android.view.View;
|
||||||
import android.widget.Button;
|
|
||||||
import android.widget.EditText;
|
import android.widget.EditText;
|
||||||
import android.widget.ImageButton;
|
import android.widget.ImageButton;
|
||||||
import android.widget.ImageView;
|
import android.widget.ImageView;
|
||||||
|
@ -44,6 +43,8 @@ import android.widget.ProgressBar;
|
||||||
|
|
||||||
import com.keylesspalace.tusky.entity.Account;
|
import com.keylesspalace.tusky.entity.Account;
|
||||||
import com.keylesspalace.tusky.entity.Profile;
|
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.pkmmte.view.CircularImageView;
|
||||||
import com.squareup.picasso.Picasso;
|
import com.squareup.picasso.Picasso;
|
||||||
import com.theartofdev.edmodo.cropper.CropImage;
|
import com.theartofdev.edmodo.cropper.CropImage;
|
||||||
|
|
|
@ -23,6 +23,10 @@ import android.support.v7.app.ActionBar;
|
||||||
import android.support.v7.widget.Toolbar;
|
import android.support.v7.widget.Toolbar;
|
||||||
import android.view.MenuItem;
|
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 {
|
public class FavouritesActivity extends BaseActivity implements SFragment.OnUserRemovedListener {
|
||||||
private StatusRemoveListener statusRemoveListener;
|
private StatusRemoveListener statusRemoveListener;
|
||||||
|
|
||||||
|
|
|
@ -36,6 +36,10 @@ import android.widget.TextView;
|
||||||
|
|
||||||
import com.keylesspalace.tusky.entity.AccessToken;
|
import com.keylesspalace.tusky.entity.AccessToken;
|
||||||
import com.keylesspalace.tusky.entity.AppCredentials;
|
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.HashMap;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
|
|
|
@ -42,6 +42,11 @@ import com.arlib.floatingsearchview.FloatingSearchView;
|
||||||
import com.arlib.floatingsearchview.suggestions.SearchSuggestionsAdapter;
|
import com.arlib.floatingsearchview.suggestions.SearchSuggestionsAdapter;
|
||||||
import com.arlib.floatingsearchview.suggestions.model.SearchSuggestion;
|
import com.arlib.floatingsearchview.suggestions.model.SearchSuggestion;
|
||||||
import com.keylesspalace.tusky.entity.Account;
|
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.google_material_typeface_library.GoogleMaterial;
|
||||||
import com.mikepenz.materialdrawer.AccountHeader;
|
import com.mikepenz.materialdrawer.AccountHeader;
|
||||||
import com.mikepenz.materialdrawer.AccountHeaderBuilder;
|
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.tab_layout) TabLayout tabLayout;
|
||||||
@BindView(R.id.pager) ViewPager viewPager;
|
@BindView(R.id.pager) ViewPager viewPager;
|
||||||
|
|
||||||
FloatingActionButton composeButton;
|
public FloatingActionButton composeButton;
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected void onCreate(Bundle savedInstanceState) {
|
protected void onCreate(Bundle savedInstanceState) {
|
||||||
|
|
|
@ -21,6 +21,8 @@ import android.os.Bundle;
|
||||||
import android.preference.PreferenceManager;
|
import android.preference.PreferenceManager;
|
||||||
import android.support.annotation.Nullable;
|
import android.support.annotation.Nullable;
|
||||||
|
|
||||||
|
import com.keylesspalace.tusky.fragment.PreferencesFragment;
|
||||||
|
|
||||||
public class PreferencesActivity extends BaseActivity
|
public class PreferencesActivity extends BaseActivity
|
||||||
implements SharedPreferences.OnSharedPreferenceChangeListener {
|
implements SharedPreferences.OnSharedPreferenceChangeListener {
|
||||||
private boolean themeSwitched;
|
private boolean themeSwitched;
|
||||||
|
|
|
@ -30,7 +30,11 @@ import android.view.MenuItem;
|
||||||
import android.view.View;
|
import android.view.View;
|
||||||
import android.widget.EditText;
|
import android.widget.EditText;
|
||||||
|
|
||||||
|
import com.keylesspalace.tusky.adapter.ReportAdapter;
|
||||||
import com.keylesspalace.tusky.entity.Status;
|
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.ArrayList;
|
||||||
import java.util.Arrays;
|
import java.util.Arrays;
|
||||||
|
|
|
@ -23,6 +23,10 @@ import android.support.v7.app.ActionBar;
|
||||||
import android.support.v7.widget.Toolbar;
|
import android.support.v7.widget.Toolbar;
|
||||||
import android.view.MenuItem;
|
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.BindView;
|
||||||
import butterknife.ButterKnife;
|
import butterknife.ButterKnife;
|
||||||
|
|
||||||
|
|
|
@ -25,6 +25,10 @@ import android.support.v7.widget.Toolbar;
|
||||||
import android.view.Menu;
|
import android.view.Menu;
|
||||||
import android.view.MenuItem;
|
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 {
|
public class ViewThreadActivity extends BaseActivity implements SFragment.OnUserRemovedListener {
|
||||||
Fragment viewThreadFragment;
|
Fragment viewThreadFragment;
|
||||||
|
|
||||||
|
|
|
@ -13,17 +13,18 @@
|
||||||
* You should have received a copy of the GNU General Public License along with Tusky; if not,
|
* You should have received a copy of the GNU General Public License along with Tusky; if not,
|
||||||
* see <http://www.gnu.org/licenses>. */
|
* see <http://www.gnu.org/licenses>. */
|
||||||
|
|
||||||
package com.keylesspalace.tusky;
|
package com.keylesspalace.tusky.adapter;
|
||||||
|
|
||||||
import android.support.annotation.Nullable;
|
import android.support.annotation.Nullable;
|
||||||
import android.support.v7.widget.RecyclerView;
|
import android.support.v7.widget.RecyclerView;
|
||||||
|
|
||||||
import com.keylesspalace.tusky.entity.Account;
|
import com.keylesspalace.tusky.entity.Account;
|
||||||
|
import com.keylesspalace.tusky.interfaces.AccountActionListener;
|
||||||
|
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
|
||||||
abstract class AccountAdapter extends RecyclerView.Adapter {
|
public abstract class AccountAdapter extends RecyclerView.Adapter {
|
||||||
List<Account> accountList;
|
List<Account> accountList;
|
||||||
AccountActionListener accountActionListener;
|
AccountActionListener accountActionListener;
|
||||||
|
|
||||||
|
@ -38,7 +39,7 @@ abstract class AccountAdapter extends RecyclerView.Adapter {
|
||||||
return accountList.size() + 1;
|
return accountList.size() + 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
void update(List<Account> newAccounts) {
|
public void update(List<Account> newAccounts) {
|
||||||
if (newAccounts == null || newAccounts.isEmpty()) {
|
if (newAccounts == null || newAccounts.isEmpty()) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
@ -59,14 +60,14 @@ abstract class AccountAdapter extends RecyclerView.Adapter {
|
||||||
notifyDataSetChanged();
|
notifyDataSetChanged();
|
||||||
}
|
}
|
||||||
|
|
||||||
void addItems(List<Account> newAccounts) {
|
public void addItems(List<Account> newAccounts) {
|
||||||
int end = accountList.size();
|
int end = accountList.size();
|
||||||
accountList.addAll(newAccounts);
|
accountList.addAll(newAccounts);
|
||||||
notifyItemRangeInserted(end, newAccounts.size());
|
notifyItemRangeInserted(end, newAccounts.size());
|
||||||
}
|
}
|
||||||
|
|
||||||
@Nullable
|
@Nullable
|
||||||
Account removeItem(int position) {
|
public Account removeItem(int position) {
|
||||||
if (position < 0 || position >= accountList.size()) {
|
if (position < 0 || position >= accountList.size()) {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
@ -75,7 +76,7 @@ abstract class AccountAdapter extends RecyclerView.Adapter {
|
||||||
return account;
|
return account;
|
||||||
}
|
}
|
||||||
|
|
||||||
void addItem(Account account, int position) {
|
public void addItem(Account account, int position) {
|
||||||
if (position < 0 || position > accountList.size()) {
|
if (position < 0 || position > accountList.size()) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
|
@ -13,7 +13,7 @@
|
||||||
* You should have received a copy of the GNU General Public License along with Tusky; if not,
|
* You should have received a copy of the GNU General Public License along with Tusky; if not,
|
||||||
* see <http://www.gnu.org/licenses>. */
|
* see <http://www.gnu.org/licenses>. */
|
||||||
|
|
||||||
package com.keylesspalace.tusky;
|
package com.keylesspalace.tusky.adapter;
|
||||||
|
|
||||||
import android.support.v7.widget.RecyclerView;
|
import android.support.v7.widget.RecyclerView;
|
||||||
import android.view.LayoutInflater;
|
import android.view.LayoutInflater;
|
||||||
|
@ -22,18 +22,20 @@ import android.view.ViewGroup;
|
||||||
import android.widget.ImageButton;
|
import android.widget.ImageButton;
|
||||||
import android.widget.TextView;
|
import android.widget.TextView;
|
||||||
|
|
||||||
|
import com.keylesspalace.tusky.R;
|
||||||
import com.keylesspalace.tusky.entity.Account;
|
import com.keylesspalace.tusky.entity.Account;
|
||||||
|
import com.keylesspalace.tusky.interfaces.AccountActionListener;
|
||||||
import com.pkmmte.view.CircularImageView;
|
import com.pkmmte.view.CircularImageView;
|
||||||
import com.squareup.picasso.Picasso;
|
import com.squareup.picasso.Picasso;
|
||||||
|
|
||||||
import butterknife.BindView;
|
import butterknife.BindView;
|
||||||
import butterknife.ButterKnife;
|
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_BLOCKED_USER = 0;
|
||||||
private static final int VIEW_TYPE_FOOTER = 1;
|
private static final int VIEW_TYPE_FOOTER = 1;
|
||||||
|
|
||||||
BlocksAdapter(AccountActionListener accountActionListener) {
|
public BlocksAdapter(AccountActionListener accountActionListener) {
|
||||||
super(accountActionListener);
|
super(accountActionListener);
|
||||||
}
|
}
|
||||||
|
|
|
@ -13,7 +13,7 @@
|
||||||
* You should have received a copy of the GNU General Public License along with Tusky; if not,
|
* You should have received a copy of the GNU General Public License along with Tusky; if not,
|
||||||
* see <http://www.gnu.org/licenses>. */
|
* see <http://www.gnu.org/licenses>. */
|
||||||
|
|
||||||
package com.keylesspalace.tusky;
|
package com.keylesspalace.tusky.adapter;
|
||||||
|
|
||||||
import android.content.Context;
|
import android.content.Context;
|
||||||
import android.support.v7.widget.RecyclerView;
|
import android.support.v7.widget.RecyclerView;
|
||||||
|
@ -22,16 +22,18 @@ import android.view.View;
|
||||||
import android.view.ViewGroup;
|
import android.view.ViewGroup;
|
||||||
import android.widget.TextView;
|
import android.widget.TextView;
|
||||||
|
|
||||||
|
import com.keylesspalace.tusky.R;
|
||||||
import com.keylesspalace.tusky.entity.Account;
|
import com.keylesspalace.tusky.entity.Account;
|
||||||
|
import com.keylesspalace.tusky.interfaces.AccountActionListener;
|
||||||
import com.pkmmte.view.CircularImageView;
|
import com.pkmmte.view.CircularImageView;
|
||||||
import com.squareup.picasso.Picasso;
|
import com.squareup.picasso.Picasso;
|
||||||
|
|
||||||
/** Both for follows and following lists. */
|
/** 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_ACCOUNT = 0;
|
||||||
private static final int VIEW_TYPE_FOOTER = 1;
|
private static final int VIEW_TYPE_FOOTER = 1;
|
||||||
|
|
||||||
FollowAdapter(AccountActionListener accountActionListener) {
|
public FollowAdapter(AccountActionListener accountActionListener) {
|
||||||
super(accountActionListener);
|
super(accountActionListener);
|
||||||
}
|
}
|
||||||
|
|
|
@ -13,7 +13,7 @@
|
||||||
* You should have received a copy of the GNU General Public License along with Tusky; if not,
|
* You should have received a copy of the GNU General Public License along with Tusky; if not,
|
||||||
* see <http://www.gnu.org/licenses>. */
|
* see <http://www.gnu.org/licenses>. */
|
||||||
|
|
||||||
package com.keylesspalace.tusky;
|
package com.keylesspalace.tusky.adapter;
|
||||||
|
|
||||||
import android.support.v7.widget.RecyclerView;
|
import android.support.v7.widget.RecyclerView;
|
||||||
import android.view.LayoutInflater;
|
import android.view.LayoutInflater;
|
||||||
|
@ -22,6 +22,8 @@ import android.view.ViewGroup;
|
||||||
import android.widget.ImageButton;
|
import android.widget.ImageButton;
|
||||||
import android.widget.TextView;
|
import android.widget.TextView;
|
||||||
|
|
||||||
|
import com.keylesspalace.tusky.interfaces.AccountActionListener;
|
||||||
|
import com.keylesspalace.tusky.R;
|
||||||
import com.keylesspalace.tusky.entity.Account;
|
import com.keylesspalace.tusky.entity.Account;
|
||||||
import com.pkmmte.view.CircularImageView;
|
import com.pkmmte.view.CircularImageView;
|
||||||
import com.squareup.picasso.Picasso;
|
import com.squareup.picasso.Picasso;
|
||||||
|
@ -29,11 +31,11 @@ import com.squareup.picasso.Picasso;
|
||||||
import butterknife.BindView;
|
import butterknife.BindView;
|
||||||
import butterknife.ButterKnife;
|
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_FOLLOW_REQUEST = 0;
|
||||||
private static final int VIEW_TYPE_FOOTER = 1;
|
private static final int VIEW_TYPE_FOOTER = 1;
|
||||||
|
|
||||||
FollowRequestsAdapter(AccountActionListener accountActionListener) {
|
public FollowRequestsAdapter(AccountActionListener accountActionListener) {
|
||||||
super(accountActionListener);
|
super(accountActionListener);
|
||||||
}
|
}
|
||||||
|
|
|
@ -13,12 +13,14 @@
|
||||||
* You should have received a copy of the GNU General Public License along with Tusky; if not,
|
* You should have received a copy of the GNU General Public License along with Tusky; if not,
|
||||||
* see <http://www.gnu.org/licenses>. */
|
* see <http://www.gnu.org/licenses>. */
|
||||||
|
|
||||||
package com.keylesspalace.tusky;
|
package com.keylesspalace.tusky.adapter;
|
||||||
|
|
||||||
import android.support.v7.widget.RecyclerView;
|
import android.support.v7.widget.RecyclerView;
|
||||||
import android.view.View;
|
import android.view.View;
|
||||||
import android.widget.ProgressBar;
|
import android.widget.ProgressBar;
|
||||||
|
|
||||||
|
import com.keylesspalace.tusky.R;
|
||||||
|
|
||||||
class FooterViewHolder extends RecyclerView.ViewHolder {
|
class FooterViewHolder extends RecyclerView.ViewHolder {
|
||||||
FooterViewHolder(View itemView) {
|
FooterViewHolder(View itemView) {
|
||||||
super(itemView);
|
super(itemView);
|
|
@ -1,4 +1,4 @@
|
||||||
package com.keylesspalace.tusky;
|
package com.keylesspalace.tusky.adapter;
|
||||||
|
|
||||||
import android.support.v7.widget.RecyclerView;
|
import android.support.v7.widget.RecyclerView;
|
||||||
import android.view.LayoutInflater;
|
import android.view.LayoutInflater;
|
||||||
|
@ -7,21 +7,20 @@ import android.view.ViewGroup;
|
||||||
import android.widget.ImageButton;
|
import android.widget.ImageButton;
|
||||||
import android.widget.TextView;
|
import android.widget.TextView;
|
||||||
|
|
||||||
|
import com.keylesspalace.tusky.R;
|
||||||
import com.keylesspalace.tusky.entity.Account;
|
import com.keylesspalace.tusky.entity.Account;
|
||||||
|
import com.keylesspalace.tusky.interfaces.AccountActionListener;
|
||||||
import com.pkmmte.view.CircularImageView;
|
import com.pkmmte.view.CircularImageView;
|
||||||
import com.squareup.picasso.Picasso;
|
import com.squareup.picasso.Picasso;
|
||||||
|
|
||||||
import java.util.HashSet;
|
|
||||||
import java.util.Set;
|
|
||||||
|
|
||||||
import butterknife.BindView;
|
import butterknife.BindView;
|
||||||
import butterknife.ButterKnife;
|
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_MUTED_USER = 0;
|
||||||
private static final int VIEW_TYPE_FOOTER = 1;
|
private static final int VIEW_TYPE_FOOTER = 1;
|
||||||
|
|
||||||
MutesAdapter(AccountActionListener accountActionListener) {
|
public MutesAdapter(AccountActionListener accountActionListener) {
|
||||||
super(accountActionListener);
|
super(accountActionListener);
|
||||||
}
|
}
|
||||||
|
|
|
@ -13,7 +13,7 @@
|
||||||
* You should have received a copy of the GNU General Public License along with Tusky; if not,
|
* You should have received a copy of the GNU General Public License along with Tusky; if not,
|
||||||
* see <http://www.gnu.org/licenses>. */
|
* see <http://www.gnu.org/licenses>. */
|
||||||
|
|
||||||
package com.keylesspalace.tusky;
|
package com.keylesspalace.tusky.adapter;
|
||||||
|
|
||||||
import android.content.Context;
|
import android.content.Context;
|
||||||
import android.graphics.Typeface;
|
import android.graphics.Typeface;
|
||||||
|
@ -29,21 +29,24 @@ import android.view.ViewGroup;
|
||||||
import android.widget.ImageView;
|
import android.widget.ImageView;
|
||||||
import android.widget.TextView;
|
import android.widget.TextView;
|
||||||
|
|
||||||
|
import com.keylesspalace.tusky.R;
|
||||||
import com.keylesspalace.tusky.entity.Notification;
|
import com.keylesspalace.tusky.entity.Notification;
|
||||||
import com.keylesspalace.tusky.entity.Status;
|
import com.keylesspalace.tusky.entity.Status;
|
||||||
|
import com.keylesspalace.tusky.interfaces.AdapterItemRemover;
|
||||||
|
import com.keylesspalace.tusky.interfaces.StatusActionListener;
|
||||||
import com.squareup.picasso.Picasso;
|
import com.squareup.picasso.Picasso;
|
||||||
|
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.Iterator;
|
import java.util.Iterator;
|
||||||
import java.util.List;
|
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_MENTION = 0;
|
||||||
private static final int VIEW_TYPE_FOOTER = 1;
|
private static final int VIEW_TYPE_FOOTER = 1;
|
||||||
private static final int VIEW_TYPE_STATUS_NOTIFICATION = 2;
|
private static final int VIEW_TYPE_STATUS_NOTIFICATION = 2;
|
||||||
private static final int VIEW_TYPE_FOLLOW = 3;
|
private static final int VIEW_TYPE_FOLLOW = 3;
|
||||||
|
|
||||||
enum FooterState {
|
public enum FooterState {
|
||||||
EMPTY,
|
EMPTY,
|
||||||
END,
|
END,
|
||||||
LOADING
|
LOADING
|
||||||
|
@ -54,7 +57,7 @@ class NotificationsAdapter extends RecyclerView.Adapter implements AdapterItemRe
|
||||||
private NotificationActionListener notificationActionListener;
|
private NotificationActionListener notificationActionListener;
|
||||||
private FooterState footerState = FooterState.END;
|
private FooterState footerState = FooterState.END;
|
||||||
|
|
||||||
NotificationsAdapter(StatusActionListener statusListener,
|
public NotificationsAdapter(StatusActionListener statusListener,
|
||||||
NotificationActionListener notificationActionListener) {
|
NotificationActionListener notificationActionListener) {
|
||||||
super();
|
super();
|
||||||
notifications = new ArrayList<>();
|
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 oldValue = footerState;
|
||||||
footerState = newFooterState;
|
footerState = newFooterState;
|
||||||
if (footerState != oldValue) {
|
if (footerState != oldValue) {
|
||||||
|
@ -179,7 +182,7 @@ class NotificationsAdapter extends RecyclerView.Adapter implements AdapterItemRe
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
void update(List<Notification> newNotifications) {
|
public void update(List<Notification> newNotifications) {
|
||||||
if (newNotifications == null || newNotifications.isEmpty()) {
|
if (newNotifications == null || newNotifications.isEmpty()) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
@ -200,7 +203,7 @@ class NotificationsAdapter extends RecyclerView.Adapter implements AdapterItemRe
|
||||||
notifyDataSetChanged();
|
notifyDataSetChanged();
|
||||||
}
|
}
|
||||||
|
|
||||||
void addItems(List<Notification> new_notifications) {
|
public void addItems(List<Notification> new_notifications) {
|
||||||
int end = notifications.size();
|
int end = notifications.size();
|
||||||
notifications.addAll(new_notifications);
|
notifications.addAll(new_notifications);
|
||||||
notifyItemRangeInserted(end, new_notifications.size());
|
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);
|
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,
|
* You should have received a copy of the GNU General Public License along with Tusky; if not,
|
||||||
* see <http://www.gnu.org/licenses>. */
|
* see <http://www.gnu.org/licenses>. */
|
||||||
|
|
||||||
package com.keylesspalace.tusky;
|
package com.keylesspalace.tusky.adapter;
|
||||||
|
|
||||||
import android.support.v7.widget.RecyclerView;
|
import android.support.v7.widget.RecyclerView;
|
||||||
import android.text.Spanned;
|
import android.text.Spanned;
|
||||||
|
@ -24,16 +24,18 @@ import android.widget.CheckBox;
|
||||||
import android.widget.CompoundButton;
|
import android.widget.CompoundButton;
|
||||||
import android.widget.TextView;
|
import android.widget.TextView;
|
||||||
|
|
||||||
|
import com.keylesspalace.tusky.R;
|
||||||
|
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
|
||||||
class ReportAdapter extends RecyclerView.Adapter {
|
public class ReportAdapter extends RecyclerView.Adapter {
|
||||||
static class ReportStatus {
|
public static class ReportStatus {
|
||||||
String id;
|
String id;
|
||||||
Spanned content;
|
Spanned content;
|
||||||
boolean checked;
|
boolean checked;
|
||||||
|
|
||||||
ReportStatus(String id, Spanned content, boolean checked) {
|
public ReportStatus(String id, Spanned content, boolean checked) {
|
||||||
this.id = id;
|
this.id = id;
|
||||||
this.content = content;
|
this.content = content;
|
||||||
this.checked = checked;
|
this.checked = checked;
|
||||||
|
@ -58,7 +60,7 @@ class ReportAdapter extends RecyclerView.Adapter {
|
||||||
|
|
||||||
private List<ReportStatus> statusList;
|
private List<ReportStatus> statusList;
|
||||||
|
|
||||||
ReportAdapter() {
|
public ReportAdapter() {
|
||||||
super();
|
super();
|
||||||
statusList = new ArrayList<>();
|
statusList = new ArrayList<>();
|
||||||
}
|
}
|
||||||
|
@ -82,13 +84,13 @@ class ReportAdapter extends RecyclerView.Adapter {
|
||||||
return statusList.size();
|
return statusList.size();
|
||||||
}
|
}
|
||||||
|
|
||||||
void addItem(ReportStatus status) {
|
public void addItem(ReportStatus status) {
|
||||||
int end = statusList.size();
|
int end = statusList.size();
|
||||||
statusList.add(status);
|
statusList.add(status);
|
||||||
notifyItemInserted(end);
|
notifyItemInserted(end);
|
||||||
}
|
}
|
||||||
|
|
||||||
void addItems(List<ReportStatus> newStatuses) {
|
public void addItems(List<ReportStatus> newStatuses) {
|
||||||
int end = statusList.size();
|
int end = statusList.size();
|
||||||
int added = 0;
|
int added = 0;
|
||||||
for (ReportStatus status : newStatuses) {
|
for (ReportStatus status : newStatuses) {
|
||||||
|
@ -102,7 +104,7 @@ class ReportAdapter extends RecyclerView.Adapter {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
String[] getCheckedStatusIds() {
|
public String[] getCheckedStatusIds() {
|
||||||
List<String> idList = new ArrayList<>();
|
List<String> idList = new ArrayList<>();
|
||||||
for (ReportStatus status : statusList) {
|
for (ReportStatus status : statusList) {
|
||||||
if (status.checked) {
|
if (status.checked) {
|
|
@ -13,9 +13,10 @@
|
||||||
* You should have received a copy of the GNU General Public License along with Tusky; if not,
|
* You should have received a copy of the GNU General Public License along with Tusky; if not,
|
||||||
* see <http://www.gnu.org/licenses>. */
|
* see <http://www.gnu.org/licenses>. */
|
||||||
|
|
||||||
package com.keylesspalace.tusky;
|
package com.keylesspalace.tusky.adapter;
|
||||||
|
|
||||||
import android.content.Context;
|
import android.content.Context;
|
||||||
|
import android.preference.PreferenceManager;
|
||||||
import android.support.annotation.Nullable;
|
import android.support.annotation.Nullable;
|
||||||
import android.support.v7.widget.RecyclerView;
|
import android.support.v7.widget.RecyclerView;
|
||||||
import android.text.Spanned;
|
import android.text.Spanned;
|
||||||
|
@ -26,7 +27,13 @@ import android.widget.ImageView;
|
||||||
import android.widget.TextView;
|
import android.widget.TextView;
|
||||||
import android.widget.ToggleButton;
|
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.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.squareup.picasso.Picasso;
|
||||||
import com.varunest.sparkbutton.SparkButton;
|
import com.varunest.sparkbutton.SparkButton;
|
||||||
import com.varunest.sparkbutton.SparkEventListener;
|
import com.varunest.sparkbutton.SparkEventListener;
|
||||||
|
@ -100,7 +107,10 @@ class StatusViewHolder extends RecyclerView.ViewHolder {
|
||||||
StatusActionListener listener) {
|
StatusActionListener listener) {
|
||||||
/* Redirect URLSpan's in the status content to the listener for viewing tag pages and
|
/* Redirect URLSpan's in the status content to the listener for viewing tag pages and
|
||||||
* account pages. */
|
* 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) {
|
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,
|
* You should have received a copy of the GNU General Public License along with Tusky; if not,
|
||||||
* see <http://www.gnu.org/licenses>. */
|
* see <http://www.gnu.org/licenses>. */
|
||||||
|
|
||||||
package com.keylesspalace.tusky;
|
package com.keylesspalace.tusky.adapter;
|
||||||
|
|
||||||
import android.support.v7.widget.RecyclerView;
|
import android.support.v7.widget.RecyclerView;
|
||||||
import android.view.LayoutInflater;
|
import android.view.LayoutInflater;
|
||||||
import android.view.View;
|
import android.view.View;
|
||||||
import android.view.ViewGroup;
|
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 com.keylesspalace.tusky.entity.Status;
|
||||||
|
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
|
||||||
class ThreadAdapter extends RecyclerView.Adapter implements AdapterItemRemover {
|
public class ThreadAdapter extends RecyclerView.Adapter implements AdapterItemRemover {
|
||||||
private List<Status> statuses;
|
private List<Status> statuses;
|
||||||
private StatusActionListener statusActionListener;
|
private StatusActionListener statusActionListener;
|
||||||
private int statusIndex;
|
private int statusIndex;
|
||||||
|
|
||||||
ThreadAdapter(StatusActionListener listener) {
|
public ThreadAdapter(StatusActionListener listener) {
|
||||||
this.statusActionListener = listener;
|
this.statusActionListener = listener;
|
||||||
this.statuses = new ArrayList<>();
|
this.statuses = new ArrayList<>();
|
||||||
this.statusIndex = 0;
|
this.statusIndex = 0;
|
||||||
|
@ -55,7 +58,7 @@ class ThreadAdapter extends RecyclerView.Adapter implements AdapterItemRemover {
|
||||||
return statuses.size();
|
return statuses.size();
|
||||||
}
|
}
|
||||||
|
|
||||||
Status getItem(int position) {
|
public Status getItem(int position) {
|
||||||
return statuses.get(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)) {
|
if (statuses.size() > 0 && statuses.get(statusIndex).equals(status)) {
|
||||||
// Do not add this status on refresh, it's already in there.
|
// Do not add this status on refresh, it's already in there.
|
||||||
statuses.set(statusIndex, status);
|
statuses.set(statusIndex, status);
|
||||||
|
@ -88,7 +91,7 @@ class ThreadAdapter extends RecyclerView.Adapter implements AdapterItemRemover {
|
||||||
return i;
|
return i;
|
||||||
}
|
}
|
||||||
|
|
||||||
void setContext(List<Status> ancestors, List<Status> descendants) {
|
public void setContext(List<Status> ancestors, List<Status> descendants) {
|
||||||
Status mainStatus = null;
|
Status mainStatus = null;
|
||||||
|
|
||||||
// In case of refresh, remove old ancestors and descendants first. We'll remove all blindly,
|
// 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,
|
* You should have received a copy of the GNU General Public License along with Tusky; if not,
|
||||||
* see <http://www.gnu.org/licenses>. */
|
* see <http://www.gnu.org/licenses>. */
|
||||||
|
|
||||||
package com.keylesspalace.tusky;
|
package com.keylesspalace.tusky.adapter;
|
||||||
|
|
||||||
import android.support.annotation.Nullable;
|
import android.support.annotation.Nullable;
|
||||||
import android.support.v7.widget.RecyclerView;
|
import android.support.v7.widget.RecyclerView;
|
||||||
|
@ -21,16 +21,19 @@ import android.view.LayoutInflater;
|
||||||
import android.view.View;
|
import android.view.View;
|
||||||
import android.view.ViewGroup;
|
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 com.keylesspalace.tusky.entity.Status;
|
||||||
|
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.List;
|
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_STATUS = 0;
|
||||||
private static final int VIEW_TYPE_FOOTER = 1;
|
private static final int VIEW_TYPE_FOOTER = 1;
|
||||||
|
|
||||||
enum FooterState {
|
public enum FooterState {
|
||||||
EMPTY,
|
EMPTY,
|
||||||
END,
|
END,
|
||||||
LOADING
|
LOADING
|
||||||
|
@ -40,7 +43,7 @@ class TimelineAdapter extends RecyclerView.Adapter implements AdapterItemRemover
|
||||||
private StatusActionListener statusListener;
|
private StatusActionListener statusListener;
|
||||||
private FooterState footerState = FooterState.END;
|
private FooterState footerState = FooterState.END;
|
||||||
|
|
||||||
TimelineAdapter(StatusActionListener statusListener) {
|
public TimelineAdapter(StatusActionListener statusListener) {
|
||||||
super();
|
super();
|
||||||
statuses = new ArrayList<>();
|
statuses = new ArrayList<>();
|
||||||
this.statusListener = statusListener;
|
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 oldValue = footerState;
|
||||||
footerState = newFooterState;
|
footerState = newFooterState;
|
||||||
if (footerState != oldValue) {
|
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()) {
|
if (newStatuses == null || newStatuses.isEmpty()) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
@ -131,7 +134,7 @@ class TimelineAdapter extends RecyclerView.Adapter implements AdapterItemRemover
|
||||||
notifyDataSetChanged();
|
notifyDataSetChanged();
|
||||||
}
|
}
|
||||||
|
|
||||||
void addItems(List<Status> newStatuses) {
|
public void addItems(List<Status> newStatuses) {
|
||||||
int end = statuses.size();
|
int end = statuses.size();
|
||||||
statuses.addAll(newStatuses);
|
statuses.addAll(newStatuses);
|
||||||
notifyItemRangeInserted(end, newStatuses.size());
|
notifyItemRangeInserted(end, newStatuses.size());
|
||||||
|
@ -142,7 +145,7 @@ class TimelineAdapter extends RecyclerView.Adapter implements AdapterItemRemover
|
||||||
notifyItemRemoved(position);
|
notifyItemRemoved(position);
|
||||||
}
|
}
|
||||||
|
|
||||||
void removeAllByAccountId(String accountId) {
|
public void removeAllByAccountId(String accountId) {
|
||||||
for (int i = 0; i < statuses.size();) {
|
for (int i = 0; i < statuses.size();) {
|
||||||
Status status = statuses.get(i);
|
Status status = statuses.get(i);
|
||||||
if (accountId.equals(status.account.id)) {
|
if (accountId.equals(status.account.id)) {
|
||||||
|
@ -155,7 +158,7 @@ class TimelineAdapter extends RecyclerView.Adapter implements AdapterItemRemover
|
||||||
}
|
}
|
||||||
|
|
||||||
@Nullable
|
@Nullable
|
||||||
Status getItem(int position) {
|
public Status getItem(int position) {
|
||||||
if (position >= 0 && position < statuses.size()) {
|
if (position >= 0 && position < statuses.size()) {
|
||||||
return statuses.get(position);
|
return statuses.get(position);
|
||||||
}
|
}
|
|
@ -20,8 +20,8 @@ import android.text.Spanned;
|
||||||
|
|
||||||
import com.arlib.floatingsearchview.suggestions.model.SearchSuggestion;
|
import com.arlib.floatingsearchview.suggestions.model.SearchSuggestion;
|
||||||
import com.google.gson.annotations.SerializedName;
|
import com.google.gson.annotations.SerializedName;
|
||||||
import com.keylesspalace.tusky.HtmlUtils;
|
import com.keylesspalace.tusky.util.HtmlUtils;
|
||||||
import com.keylesspalace.tusky.StringWithEmoji;
|
import com.keylesspalace.tusky.json.StringWithEmoji;
|
||||||
|
|
||||||
public class Account implements SearchSuggestion {
|
public class Account implements SearchSuggestion {
|
||||||
public String id;
|
public String id;
|
||||||
|
|
|
@ -13,7 +13,7 @@
|
||||||
* You should have received a copy of the GNU General Public License along with Tusky; if not,
|
* You should have received a copy of the GNU General Public License along with Tusky; if not,
|
||||||
* see <http://www.gnu.org/licenses>. */
|
* see <http://www.gnu.org/licenses>. */
|
||||||
|
|
||||||
package com.keylesspalace.tusky;
|
package com.keylesspalace.tusky.fragment;
|
||||||
|
|
||||||
import android.content.Context;
|
import android.content.Context;
|
||||||
import android.content.Intent;
|
import android.content.Intent;
|
||||||
|
@ -29,8 +29,22 @@ import android.view.LayoutInflater;
|
||||||
import android.view.View;
|
import android.view.View;
|
||||||
import android.view.ViewGroup;
|
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.Account;
|
||||||
import com.keylesspalace.tusky.entity.Relationship;
|
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;
|
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,
|
* You should have received a copy of the GNU General Public License along with Tusky; if not,
|
||||||
* see <http://www.gnu.org/licenses>. */
|
* see <http://www.gnu.org/licenses>. */
|
||||||
|
|
||||||
package com.keylesspalace.tusky;
|
package com.keylesspalace.tusky.fragment;
|
||||||
|
|
||||||
import android.content.Context;
|
import android.content.Context;
|
||||||
import android.content.SharedPreferences;
|
import android.content.SharedPreferences;
|
||||||
|
@ -21,6 +21,8 @@ import android.os.Bundle;
|
||||||
import android.support.annotation.Nullable;
|
import android.support.annotation.Nullable;
|
||||||
import android.support.v4.app.Fragment;
|
import android.support.v4.app.Fragment;
|
||||||
|
|
||||||
|
import com.keylesspalace.tusky.R;
|
||||||
|
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.List;
|
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,
|
* You should have received a copy of the GNU General Public License along with Tusky; if not,
|
||||||
* see <http://www.gnu.org/licenses>. */
|
* see <http://www.gnu.org/licenses>. */
|
||||||
|
|
||||||
package com.keylesspalace.tusky;
|
package com.keylesspalace.tusky.fragment;
|
||||||
|
|
||||||
import android.content.Context;
|
import android.content.Context;
|
||||||
import android.content.res.ColorStateList;
|
import android.content.res.ColorStateList;
|
||||||
|
@ -33,8 +33,11 @@ import android.widget.CompoundButton;
|
||||||
import android.widget.RadioButton;
|
import android.widget.RadioButton;
|
||||||
import android.widget.RadioGroup;
|
import android.widget.RadioGroup;
|
||||||
|
|
||||||
|
import com.keylesspalace.tusky.R;
|
||||||
|
import com.keylesspalace.tusky.util.ThemeUtils;
|
||||||
|
|
||||||
public class ComposeOptionsFragment extends BottomSheetDialogFragment {
|
public class ComposeOptionsFragment extends BottomSheetDialogFragment {
|
||||||
interface Listener {
|
public interface Listener {
|
||||||
void onVisibilityChanged(String visibility);
|
void onVisibilityChanged(String visibility);
|
||||||
void onContentWarningChanged(boolean hideText);
|
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,
|
* You should have received a copy of the GNU General Public License along with Tusky; if not,
|
||||||
* see <http://www.gnu.org/licenses>. */
|
* see <http://www.gnu.org/licenses>. */
|
||||||
|
|
||||||
package com.keylesspalace.tusky;
|
package com.keylesspalace.tusky.fragment;
|
||||||
|
|
||||||
import android.content.Context;
|
import android.content.Context;
|
||||||
import android.content.SharedPreferences;
|
import android.content.SharedPreferences;
|
||||||
|
@ -31,8 +31,17 @@ import android.view.LayoutInflater;
|
||||||
import android.view.View;
|
import android.view.View;
|
||||||
import android.view.ViewGroup;
|
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.Notification;
|
||||||
import com.keylesspalace.tusky.entity.Status;
|
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;
|
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,
|
* You should have received a copy of the GNU General Public License along with Tusky; if not,
|
||||||
* see <http://www.gnu.org/licenses>. */
|
* see <http://www.gnu.org/licenses>. */
|
||||||
|
|
||||||
package com.keylesspalace.tusky;
|
package com.keylesspalace.tusky.fragment;
|
||||||
|
|
||||||
import android.os.Bundle;
|
import android.os.Bundle;
|
||||||
import android.preference.PreferenceFragment;
|
import android.preference.PreferenceFragment;
|
||||||
|
|
||||||
|
import com.keylesspalace.tusky.R;
|
||||||
|
|
||||||
public class PreferencesFragment extends PreferenceFragment {
|
public class PreferencesFragment extends PreferenceFragment {
|
||||||
@Override
|
@Override
|
||||||
public void onCreate(Bundle savedInstanceState) {
|
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,
|
* You should have received a copy of the GNU General Public License along with Tusky; if not,
|
||||||
* see <http://www.gnu.org/licenses>. */
|
* see <http://www.gnu.org/licenses>. */
|
||||||
|
|
||||||
package com.keylesspalace.tusky;
|
package com.keylesspalace.tusky.fragment;
|
||||||
|
|
||||||
import android.content.Intent;
|
import android.content.Intent;
|
||||||
import android.content.SharedPreferences;
|
import android.content.SharedPreferences;
|
||||||
|
@ -27,8 +27,19 @@ import android.text.Spanned;
|
||||||
import android.view.MenuItem;
|
import android.view.MenuItem;
|
||||||
import android.view.View;
|
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.Relationship;
|
||||||
import com.keylesspalace.tusky.entity.Status;
|
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.ArrayList;
|
||||||
import java.util.List;
|
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
|
* overlap functionality. So, I'm momentarily leaving it and hopefully working on those will clear
|
||||||
* up what needs to be where. */
|
* up what needs to be where. */
|
||||||
public abstract class SFragment extends BaseFragment {
|
public abstract class SFragment extends BaseFragment {
|
||||||
interface OnUserRemovedListener {
|
public interface OnUserRemovedListener {
|
||||||
void onUserRemoved(String accountId);
|
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,
|
* You should have received a copy of the GNU General Public License along with Tusky; if not,
|
||||||
* see <http://www.gnu.org/licenses>. */
|
* see <http://www.gnu.org/licenses>. */
|
||||||
|
|
||||||
package com.keylesspalace.tusky;
|
package com.keylesspalace.tusky.fragment;
|
||||||
|
|
||||||
import android.content.Context;
|
import android.content.Context;
|
||||||
import android.content.SharedPreferences;
|
import android.content.SharedPreferences;
|
||||||
|
@ -31,7 +31,15 @@ import android.view.LayoutInflater;
|
||||||
import android.view.View;
|
import android.view.View;
|
||||||
import android.view.ViewGroup;
|
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.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;
|
import java.util.List;
|
||||||
|
|
||||||
|
@ -47,7 +55,7 @@ public class TimelineFragment extends SFragment implements
|
||||||
|
|
||||||
private Call<List<Status>> listCall;
|
private Call<List<Status>> listCall;
|
||||||
|
|
||||||
enum Kind {
|
public enum Kind {
|
||||||
HOME,
|
HOME,
|
||||||
PUBLIC_LOCAL,
|
PUBLIC_LOCAL,
|
||||||
PUBLIC_FEDERATED,
|
PUBLIC_FEDERATED,
|
|
@ -13,7 +13,7 @@
|
||||||
* You should have received a copy of the GNU General Public License along with Tusky; if not,
|
* You should have received a copy of the GNU General Public License along with Tusky; if not,
|
||||||
* see <http://www.gnu.org/licenses>. */
|
* see <http://www.gnu.org/licenses>. */
|
||||||
|
|
||||||
package com.keylesspalace.tusky;
|
package com.keylesspalace.tusky.fragment;
|
||||||
|
|
||||||
import android.app.AlertDialog;
|
import android.app.AlertDialog;
|
||||||
import android.app.DownloadManager;
|
import android.app.DownloadManager;
|
||||||
|
@ -36,6 +36,7 @@ import android.view.View;
|
||||||
import android.view.ViewGroup;
|
import android.view.ViewGroup;
|
||||||
import android.view.WindowManager;
|
import android.view.WindowManager;
|
||||||
|
|
||||||
|
import com.keylesspalace.tusky.R;
|
||||||
import com.squareup.picasso.Callback;
|
import com.squareup.picasso.Callback;
|
||||||
import com.squareup.picasso.Picasso;
|
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,
|
* You should have received a copy of the GNU General Public License along with Tusky; if not,
|
||||||
* see <http://www.gnu.org/licenses>. */
|
* see <http://www.gnu.org/licenses>. */
|
||||||
|
|
||||||
package com.keylesspalace.tusky;
|
package com.keylesspalace.tusky.fragment;
|
||||||
|
|
||||||
import android.content.Context;
|
import android.content.Context;
|
||||||
import android.graphics.drawable.Drawable;
|
import android.graphics.drawable.Drawable;
|
||||||
|
@ -29,8 +29,18 @@ import android.view.LayoutInflater;
|
||||||
import android.view.View;
|
import android.view.View;
|
||||||
import android.view.ViewGroup;
|
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.Status;
|
||||||
import com.keylesspalace.tusky.entity.StatusContext;
|
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.Call;
|
||||||
import retrofit2.Callback;
|
import retrofit2.Callback;
|
|
@ -13,9 +13,9 @@
|
||||||
* You should have received a copy of the GNU General Public License along with Tusky; if not,
|
* You should have received a copy of the GNU General Public License along with Tusky; if not,
|
||||||
* see <http://www.gnu.org/licenses>. */
|
* 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 onViewAccount(String id);
|
||||||
void onMute(final boolean mute, final String id, final int position);
|
void onMute(final boolean mute, final String id, final int position);
|
||||||
void onBlock(final boolean block, 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,
|
* You should have received a copy of the GNU General Public License along with Tusky; if not,
|
||||||
* see <http://www.gnu.org/licenses>. */
|
* see <http://www.gnu.org/licenses>. */
|
||||||
|
|
||||||
package com.keylesspalace.tusky;
|
package com.keylesspalace.tusky.interfaces;
|
||||||
|
|
||||||
interface AdapterItemRemover {
|
public interface AdapterItemRemover {
|
||||||
void removeItem(int position);
|
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,
|
* You should have received a copy of the GNU General Public License along with Tusky; if not,
|
||||||
* see <http://www.gnu.org/licenses>. */
|
* 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 onViewTag(String tag);
|
||||||
void onViewAccount(String id);
|
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,
|
* You should have received a copy of the GNU General Public License along with Tusky; if not,
|
||||||
* see <http://www.gnu.org/licenses>. */
|
* see <http://www.gnu.org/licenses>. */
|
||||||
|
|
||||||
package com.keylesspalace.tusky;
|
package com.keylesspalace.tusky.interfaces;
|
||||||
|
|
||||||
import android.view.View;
|
import android.view.View;
|
||||||
|
|
||||||
import com.keylesspalace.tusky.entity.Status;
|
import com.keylesspalace.tusky.entity.Status;
|
||||||
|
|
||||||
interface StatusActionListener extends LinkListener {
|
public interface StatusActionListener extends LinkListener {
|
||||||
void onReply(int position);
|
void onReply(int position);
|
||||||
void onReblog(final boolean reblog, final int position);
|
void onReblog(final boolean reblog, final int position);
|
||||||
void onFavourite(final boolean favourite, 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,
|
* You should have received a copy of the GNU General Public License along with Tusky; if not,
|
||||||
* see <http://www.gnu.org/licenses>. */
|
* see <http://www.gnu.org/licenses>. */
|
||||||
|
|
||||||
package com.keylesspalace.tusky;
|
package com.keylesspalace.tusky.interfaces;
|
||||||
|
|
||||||
interface StatusRemoveListener {
|
public interface StatusRemoveListener {
|
||||||
void removePostsByUser(String accountId);
|
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,
|
* You should have received a copy of the GNU General Public License along with Tusky; if not,
|
||||||
* see <http://www.gnu.org/licenses>. */
|
* see <http://www.gnu.org/licenses>. */
|
||||||
|
|
||||||
package com.keylesspalace.tusky;
|
package com.keylesspalace.tusky.json;
|
||||||
|
|
||||||
import android.text.Spanned;
|
import android.text.Spanned;
|
||||||
|
|
||||||
|
@ -22,6 +22,7 @@ import com.google.gson.JsonDeserializationContext;
|
||||||
import com.google.gson.JsonDeserializer;
|
import com.google.gson.JsonDeserializer;
|
||||||
import com.google.gson.JsonElement;
|
import com.google.gson.JsonElement;
|
||||||
import com.google.gson.JsonParseException;
|
import com.google.gson.JsonParseException;
|
||||||
|
import com.keylesspalace.tusky.util.HtmlUtils;
|
||||||
|
|
||||||
import java.lang.reflect.Type;
|
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,
|
* You should have received a copy of the GNU General Public License along with Tusky; if not,
|
||||||
* see <http://www.gnu.org/licenses>. */
|
* see <http://www.gnu.org/licenses>. */
|
||||||
|
|
||||||
package com.keylesspalace.tusky;
|
package com.keylesspalace.tusky.json;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* This is just a wrapper class for a String.
|
* 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,
|
* You should have received a copy of the GNU General Public License along with Tusky; if not,
|
||||||
* see <http://www.gnu.org/licenses>. */
|
* see <http://www.gnu.org/licenses>. */
|
||||||
|
|
||||||
package com.keylesspalace.tusky;
|
package com.keylesspalace.tusky.json;
|
||||||
|
|
||||||
import com.emojione.Emojione;
|
import com.emojione.Emojione;
|
||||||
import com.google.gson.JsonDeserializationContext;
|
import com.google.gson.JsonDeserializationContext;
|
||||||
|
@ -24,7 +24,7 @@ import com.google.gson.JsonParseException;
|
||||||
import java.lang.reflect.Type;
|
import java.lang.reflect.Type;
|
||||||
|
|
||||||
/** This is a type-based workaround to allow for shortcode conversion when loading display names. */
|
/** 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
|
@Override
|
||||||
public StringWithEmoji deserialize(JsonElement json, Type typeOfT,
|
public StringWithEmoji deserialize(JsonElement json, Type typeOfT,
|
||||||
JsonDeserializationContext context) throws JsonParseException {
|
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,
|
* You should have received a copy of the GNU General Public License along with Tusky; if not,
|
||||||
* see <http://www.gnu.org/licenses>. */
|
* 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.AccessToken;
|
||||||
import com.keylesspalace.tusky.entity.Account;
|
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,
|
* You should have received a copy of the GNU General Public License along with Tusky; if not,
|
||||||
* see <http://www.gnu.org/licenses>. */
|
* see <http://www.gnu.org/licenses>. */
|
||||||
|
|
||||||
package com.keylesspalace.tusky;
|
package com.keylesspalace.tusky.network;
|
||||||
|
|
||||||
import okhttp3.ResponseBody;
|
import okhttp3.ResponseBody;
|
||||||
import retrofit2.Call;
|
import retrofit2.Call;
|
|
@ -13,7 +13,7 @@
|
||||||
* You should have received a copy of the GNU General Public License along with Tusky; if not,
|
* You should have received a copy of the GNU General Public License along with Tusky; if not,
|
||||||
* see <http://www.gnu.org/licenses>. */
|
* see <http://www.gnu.org/licenses>. */
|
||||||
|
|
||||||
package com.keylesspalace.tusky;
|
package com.keylesspalace.tusky.pager;
|
||||||
|
|
||||||
import android.content.Context;
|
import android.content.Context;
|
||||||
import android.support.v4.app.Fragment;
|
import android.support.v4.app.Fragment;
|
||||||
|
@ -24,23 +24,27 @@ import android.view.View;
|
||||||
import android.view.ViewGroup;
|
import android.view.ViewGroup;
|
||||||
import android.widget.TextView;
|
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.ArrayList;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
|
||||||
class AccountPagerAdapter extends FragmentPagerAdapter {
|
public class AccountPagerAdapter extends FragmentPagerAdapter {
|
||||||
private Context context;
|
private Context context;
|
||||||
private String accountId;
|
private String accountId;
|
||||||
private String[] pageTitles;
|
private String[] pageTitles;
|
||||||
private List<Fragment> registeredFragments;
|
private List<Fragment> registeredFragments;
|
||||||
|
|
||||||
AccountPagerAdapter(FragmentManager manager, Context context, String accountId) {
|
public AccountPagerAdapter(FragmentManager manager, Context context, String accountId) {
|
||||||
super(manager);
|
super(manager);
|
||||||
this.context = context;
|
this.context = context;
|
||||||
this.accountId = accountId;
|
this.accountId = accountId;
|
||||||
registeredFragments = new ArrayList<>();
|
registeredFragments = new ArrayList<>();
|
||||||
}
|
}
|
||||||
|
|
||||||
void setPageTitles(String[] titles) {
|
public void setPageTitles(String[] titles) {
|
||||||
pageTitles = titles;
|
pageTitles = titles;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -72,7 +76,7 @@ class AccountPagerAdapter extends FragmentPagerAdapter {
|
||||||
return pageTitles[position];
|
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);
|
View view = LayoutInflater.from(context).inflate(R.layout.tab_account, root, false);
|
||||||
TextView title = (TextView) view.findViewById(R.id.title);
|
TextView title = (TextView) view.findViewById(R.id.title);
|
||||||
title.setText(pageTitles[position]);
|
title.setText(pageTitles[position]);
|
||||||
|
@ -92,7 +96,7 @@ class AccountPagerAdapter extends FragmentPagerAdapter {
|
||||||
super.destroyItem(container, position, object);
|
super.destroyItem(container, position, object);
|
||||||
}
|
}
|
||||||
|
|
||||||
List<Fragment> getRegisteredFragments() {
|
public List<Fragment> getRegisteredFragments() {
|
||||||
return registeredFragments;
|
return registeredFragments;
|
||||||
}
|
}
|
||||||
}
|
}
|
|
@ -13,31 +13,34 @@
|
||||||
* You should have received a copy of the GNU General Public License along with Tusky; if not,
|
* You should have received a copy of the GNU General Public License along with Tusky; if not,
|
||||||
* see <http://www.gnu.org/licenses>. */
|
* 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.Fragment;
|
||||||
import android.support.v4.app.FragmentManager;
|
import android.support.v4.app.FragmentManager;
|
||||||
import android.support.v4.app.FragmentPagerAdapter;
|
import android.support.v4.app.FragmentPagerAdapter;
|
||||||
import android.view.ViewGroup;
|
import android.view.ViewGroup;
|
||||||
|
|
||||||
|
import com.keylesspalace.tusky.fragment.NotificationsFragment;
|
||||||
|
import com.keylesspalace.tusky.fragment.TimelineFragment;
|
||||||
|
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
|
||||||
class TimelinePagerAdapter extends FragmentPagerAdapter {
|
public class TimelinePagerAdapter extends FragmentPagerAdapter {
|
||||||
private int currentFragmentIndex;
|
private int currentFragmentIndex;
|
||||||
private List<Fragment> registeredFragments;
|
private List<Fragment> registeredFragments;
|
||||||
|
|
||||||
TimelinePagerAdapter(FragmentManager manager) {
|
public TimelinePagerAdapter(FragmentManager manager) {
|
||||||
super(manager);
|
super(manager);
|
||||||
currentFragmentIndex = 0;
|
currentFragmentIndex = 0;
|
||||||
registeredFragments = new ArrayList<>();
|
registeredFragments = new ArrayList<>();
|
||||||
}
|
}
|
||||||
|
|
||||||
Fragment getCurrentFragment() {
|
public Fragment getCurrentFragment() {
|
||||||
return registeredFragments.get(currentFragmentIndex);
|
return registeredFragments.get(currentFragmentIndex);
|
||||||
}
|
}
|
||||||
|
|
||||||
List<Fragment> getRegisteredFragments() {
|
public List<Fragment> getRegisteredFragments() {
|
||||||
return registeredFragments;
|
return registeredFragments;
|
||||||
}
|
}
|
||||||
|
|
|
@ -13,12 +13,14 @@
|
||||||
* You should have received a copy of the GNU General Public License along with Tusky; if not,
|
* You should have received a copy of the GNU General Public License along with Tusky; if not,
|
||||||
* see <http://www.gnu.org/licenses>. */
|
* see <http://www.gnu.org/licenses>. */
|
||||||
|
|
||||||
package com.keylesspalace.tusky;
|
package com.keylesspalace.tusky.service;
|
||||||
|
|
||||||
import android.annotation.TargetApi;
|
import android.annotation.TargetApi;
|
||||||
import android.content.Intent;
|
import android.content.Intent;
|
||||||
import android.service.quicksettings.TileService;
|
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
|
* Small Addition that adds in a QuickSettings tile that opens the Compose activity when clicked
|
||||||
* Created by ztepps on 4/3/17.
|
* 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,
|
* You should have received a copy of the GNU General Public License along with Tusky; if not,
|
||||||
* see <http://www.gnu.org/licenses>. */
|
* see <http://www.gnu.org/licenses>. */
|
||||||
|
|
||||||
package com.keylesspalace.tusky;
|
package com.keylesspalace.tusky.util;
|
||||||
|
|
||||||
import android.content.Context;
|
import android.content.Context;
|
||||||
import android.content.res.Resources;
|
|
||||||
import android.graphics.Canvas;
|
import android.graphics.Canvas;
|
||||||
import android.graphics.drawable.Drawable;
|
import android.graphics.drawable.Drawable;
|
||||||
import android.support.v7.widget.RecyclerView;
|
import android.support.v7.widget.RecyclerView;
|
||||||
import android.util.TypedValue;
|
|
||||||
import android.view.View;
|
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 Context mContext;
|
||||||
private final Drawable mDivider;
|
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.ActivityNotFoundException;
|
||||||
import android.content.Context;
|
import android.content.Context;
|
||||||
|
@ -11,6 +11,8 @@ import android.support.v4.content.ContextCompat;
|
||||||
import android.text.style.URLSpan;
|
import android.text.style.URLSpan;
|
||||||
import android.view.View;
|
import android.view.View;
|
||||||
|
|
||||||
|
import com.keylesspalace.tusky.R;
|
||||||
|
|
||||||
class CustomTabURLSpan extends URLSpan {
|
class CustomTabURLSpan extends URLSpan {
|
||||||
CustomTabURLSpan(String url) {
|
CustomTabURLSpan(String url) {
|
||||||
super(url);
|
super(url);
|
|
@ -1,4 +1,4 @@
|
||||||
package com.keylesspalace.tusky;
|
package com.keylesspalace.tusky.util;
|
||||||
import android.content.Context;
|
import android.content.Context;
|
||||||
import android.content.Intent;
|
import android.content.Intent;
|
||||||
import android.content.IntentFilter;
|
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,
|
* You should have received a copy of the GNU General Public License along with Tusky; if not,
|
||||||
* see <http://www.gnu.org/licenses>. */
|
* see <http://www.gnu.org/licenses>. */
|
||||||
|
|
||||||
package com.keylesspalace.tusky;
|
package com.keylesspalace.tusky.util;
|
||||||
|
|
||||||
import android.content.ContentResolver;
|
import android.content.ContentResolver;
|
||||||
import android.graphics.Bitmap;
|
import android.graphics.Bitmap;
|
||||||
|
@ -31,13 +31,13 @@ import java.io.InputStream;
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
|
||||||
class DownsizeImageTask extends AsyncTask<Uri, Void, Boolean> {
|
public class DownsizeImageTask extends AsyncTask<Uri, Void, Boolean> {
|
||||||
private int sizeLimit;
|
private int sizeLimit;
|
||||||
private ContentResolver contentResolver;
|
private ContentResolver contentResolver;
|
||||||
private Listener listener;
|
private Listener listener;
|
||||||
private List<byte[]> resultList;
|
private List<byte[]> resultList;
|
||||||
|
|
||||||
DownsizeImageTask(int sizeLimit, ContentResolver contentResolver, Listener listener) {
|
public DownsizeImageTask(int sizeLimit, ContentResolver contentResolver, Listener listener) {
|
||||||
this.sizeLimit = sizeLimit;
|
this.sizeLimit = sizeLimit;
|
||||||
this.contentResolver = contentResolver;
|
this.contentResolver = contentResolver;
|
||||||
this.listener = listener;
|
this.listener = listener;
|
||||||
|
@ -219,7 +219,7 @@ class DownsizeImageTask extends AsyncTask<Uri, Void, Boolean> {
|
||||||
super.onPostExecute(successful);
|
super.onPostExecute(successful);
|
||||||
}
|
}
|
||||||
|
|
||||||
interface Listener {
|
public interface Listener {
|
||||||
void onSuccess(List<byte[]> contentList);
|
void onSuccess(List<byte[]> contentList);
|
||||||
void onFailure();
|
void onFailure();
|
||||||
}
|
}
|
|
@ -13,7 +13,7 @@
|
||||||
* You should have received a copy of the GNU General Public License along with Tusky; if not,
|
* You should have received a copy of the GNU General Public License along with Tusky; if not,
|
||||||
* see <http://www.gnu.org/licenses>. */
|
* see <http://www.gnu.org/licenses>. */
|
||||||
|
|
||||||
package com.keylesspalace.tusky;
|
package com.keylesspalace.tusky.util;
|
||||||
|
|
||||||
import android.content.Context;
|
import android.content.Context;
|
||||||
import android.support.v13.view.inputmethod.EditorInfoCompat;
|
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,
|
* You should have received a copy of the GNU General Public License along with Tusky; if not,
|
||||||
* see <http://www.gnu.org/licenses>. */
|
* 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.LinearLayoutManager;
|
||||||
import android.support.v7.widget.RecyclerView;
|
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 static final int VISIBLE_THRESHOLD = 15;
|
||||||
private int currentPage;
|
private int currentPage;
|
||||||
private int previousTotalItemCount;
|
private int previousTotalItemCount;
|
||||||
|
@ -26,7 +26,7 @@ abstract class EndlessOnScrollListener extends RecyclerView.OnScrollListener {
|
||||||
private int startingPageIndex;
|
private int startingPageIndex;
|
||||||
private LinearLayoutManager layoutManager;
|
private LinearLayoutManager layoutManager;
|
||||||
|
|
||||||
EndlessOnScrollListener(LinearLayoutManager layoutManager) {
|
public EndlessOnScrollListener(LinearLayoutManager layoutManager) {
|
||||||
this.layoutManager = layoutManager;
|
this.layoutManager = layoutManager;
|
||||||
currentPage = 0;
|
currentPage = 0;
|
||||||
previousTotalItemCount = 0;
|
previousTotalItemCount = 0;
|
||||||
|
@ -56,7 +56,7 @@ abstract class EndlessOnScrollListener extends RecyclerView.OnScrollListener {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void reset() {
|
public void reset() {
|
||||||
currentPage = startingPageIndex;
|
currentPage = startingPageIndex;
|
||||||
previousTotalItemCount = 0;
|
previousTotalItemCount = 0;
|
||||||
loading = true;
|
loading = true;
|
|
@ -13,7 +13,7 @@
|
||||||
* You should have received a copy of the GNU General Public License along with Tusky; if not,
|
* You should have received a copy of the GNU General Public License along with Tusky; if not,
|
||||||
* see <http://www.gnu.org/licenses>. */
|
* see <http://www.gnu.org/licenses>. */
|
||||||
|
|
||||||
package com.keylesspalace.tusky;
|
package com.keylesspalace.tusky.util;
|
||||||
|
|
||||||
import android.content.Context;
|
import android.content.Context;
|
||||||
import android.content.res.TypedArray;
|
import android.content.res.TypedArray;
|
||||||
|
@ -21,6 +21,8 @@ import android.util.AttributeSet;
|
||||||
import android.view.View;
|
import android.view.View;
|
||||||
import android.view.ViewGroup;
|
import android.view.ViewGroup;
|
||||||
|
|
||||||
|
import com.keylesspalace.tusky.R;
|
||||||
|
|
||||||
public class FlowLayout extends ViewGroup {
|
public class FlowLayout extends ViewGroup {
|
||||||
private int paddingHorizontal; // internal padding between child views
|
private int paddingHorizontal; // internal padding between child views
|
||||||
private int paddingVertical; //
|
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,
|
* You should have received a copy of the GNU General Public License along with Tusky; if not,
|
||||||
* see <http://www.gnu.org/licenses>. */
|
* 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.support.annotation.Nullable;
|
||||||
import android.text.SpannableStringBuilder;
|
import android.text.SpannableStringBuilder;
|
||||||
import android.text.Spanned;
|
import android.text.Spanned;
|
||||||
|
@ -26,14 +25,13 @@ import android.view.View;
|
||||||
import android.widget.TextView;
|
import android.widget.TextView;
|
||||||
|
|
||||||
import com.keylesspalace.tusky.entity.Status;
|
import com.keylesspalace.tusky.entity.Status;
|
||||||
|
import com.keylesspalace.tusky.interfaces.LinkListener;
|
||||||
|
|
||||||
class LinkHelper {
|
public class LinkHelper {
|
||||||
static void setClickableText(TextView view, Spanned content,
|
public static void setClickableText(TextView view, Spanned content,
|
||||||
@Nullable Status.Mention[] mentions,
|
@Nullable Status.Mention[] mentions, boolean useCustomTabs,
|
||||||
final LinkListener listener) {
|
final LinkListener listener) {
|
||||||
SpannableStringBuilder builder = new SpannableStringBuilder(content);
|
SpannableStringBuilder builder = new SpannableStringBuilder(content);
|
||||||
boolean useCustomTabs = PreferenceManager.getDefaultSharedPreferences(view.getContext())
|
|
||||||
.getBoolean("customTabs", true);
|
|
||||||
URLSpan[] urlSpans = content.getSpans(0, content.length(), URLSpan.class);
|
URLSpan[] urlSpans = content.getSpans(0, content.length(), URLSpan.class);
|
||||||
for (URLSpan span : urlSpans) {
|
for (URLSpan span : urlSpans) {
|
||||||
int start = builder.getSpanStart(span);
|
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,
|
* You should have received a copy of the GNU General Public License along with Tusky; if not,
|
||||||
* see <http://www.gnu.org/licenses>. */
|
* see <http://www.gnu.org/licenses>. */
|
||||||
|
|
||||||
package com.keylesspalace.tusky;
|
package com.keylesspalace.tusky.util;
|
||||||
|
|
||||||
import android.content.BroadcastReceiver;
|
import android.content.BroadcastReceiver;
|
||||||
import android.content.Context;
|
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,
|
* You should have received a copy of the GNU General Public License along with Tusky; if not,
|
||||||
* see <http://www.gnu.org/licenses>. */
|
* see <http://www.gnu.org/licenses>. */
|
||||||
|
|
||||||
package com.keylesspalace.tusky;
|
package com.keylesspalace.tusky.util;
|
||||||
|
|
||||||
import android.app.NotificationManager;
|
import android.app.NotificationManager;
|
||||||
import android.app.PendingIntent;
|
import android.app.PendingIntent;
|
||||||
|
@ -29,6 +29,8 @@ import android.support.annotation.Nullable;
|
||||||
import android.support.v4.app.NotificationCompat;
|
import android.support.v4.app.NotificationCompat;
|
||||||
import android.support.v4.app.TaskStackBuilder;
|
import android.support.v4.app.TaskStackBuilder;
|
||||||
|
|
||||||
|
import com.keylesspalace.tusky.MainActivity;
|
||||||
|
import com.keylesspalace.tusky.R;
|
||||||
import com.keylesspalace.tusky.entity.Notification;
|
import com.keylesspalace.tusky.entity.Notification;
|
||||||
import com.squareup.picasso.Picasso;
|
import com.squareup.picasso.Picasso;
|
||||||
import com.squareup.picasso.Target;
|
import com.squareup.picasso.Target;
|
||||||
|
@ -36,8 +38,8 @@ import com.squareup.picasso.Target;
|
||||||
import org.json.JSONArray;
|
import org.json.JSONArray;
|
||||||
import org.json.JSONException;
|
import org.json.JSONException;
|
||||||
|
|
||||||
class NotificationMaker {
|
public class NotificationMaker {
|
||||||
static void make(final Context context, final int notifyId, Notification body) {
|
public static void make(final Context context, final int notifyId, Notification body) {
|
||||||
final SharedPreferences preferences =
|
final SharedPreferences preferences =
|
||||||
PreferenceManager.getDefaultSharedPreferences(context);
|
PreferenceManager.getDefaultSharedPreferences(context);
|
||||||
final SharedPreferences notificationPreferences = context.getSharedPreferences(
|
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,
|
* You should have received a copy of the GNU General Public License along with Tusky; if not,
|
||||||
* see <http://www.gnu.org/licenses>. */
|
* see <http://www.gnu.org/licenses>. */
|
||||||
|
|
||||||
package com.keylesspalace.tusky;
|
package com.keylesspalace.tusky.util;
|
||||||
|
|
||||||
import android.graphics.Bitmap;
|
import android.graphics.Bitmap;
|
||||||
import android.graphics.BitmapShader;
|
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:paddingLeft="16dp"
|
||||||
android:paddingRight="16dp">
|
android:paddingRight="16dp">
|
||||||
|
|
||||||
<com.keylesspalace.tusky.EditTextTyped
|
<com.keylesspalace.tusky.util.EditTextTyped
|
||||||
android:layout_width="match_parent"
|
android:layout_width="match_parent"
|
||||||
android:layout_height="match_parent"
|
android:layout_height="match_parent"
|
||||||
android:id="@+id/compose_edit_field"
|
android:id="@+id/compose_edit_field"
|
||||||
|
|
|
@ -95,7 +95,7 @@
|
||||||
|
|
||||||
</RelativeLayout>
|
</RelativeLayout>
|
||||||
|
|
||||||
<com.keylesspalace.tusky.FlowLayout
|
<com.keylesspalace.tusky.util.FlowLayout
|
||||||
android:layout_width="wrap_content"
|
android:layout_width="wrap_content"
|
||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
android:id="@+id/status_content_warning_bar"
|
android:id="@+id/status_content_warning_bar"
|
||||||
|
@ -127,7 +127,7 @@
|
||||||
android:textAllCaps="true"
|
android:textAllCaps="true"
|
||||||
android:background="?attr/content_warning_button" />
|
android:background="?attr/content_warning_button" />
|
||||||
|
|
||||||
</com.keylesspalace.tusky.FlowLayout>
|
</com.keylesspalace.tusky.util.FlowLayout>
|
||||||
|
|
||||||
<TextView
|
<TextView
|
||||||
android:id="@+id/status_content"
|
android:id="@+id/status_content"
|
||||||
|
|
Loading…
Reference in New Issue