added multi account support, restructured database, directmessage fix, layout fix
Signed-off-by: nuclearfog <hatespirit666@gmail.com>
This commit is contained in:
parent
b7fb816d59
commit
5ffc89b578
@ -121,6 +121,11 @@
|
||||
android:screenOrientation="portrait"
|
||||
android:theme="@style/TransparencyDim" />
|
||||
|
||||
<activity
|
||||
android:name=".activity.AccountActivity"
|
||||
android:screenOrientation="portrait"
|
||||
android:theme="@style/AppTheme" />
|
||||
|
||||
</application>
|
||||
|
||||
</manifest>
|
@ -0,0 +1,108 @@
|
||||
package org.nuclearfog.twidda.activity;
|
||||
|
||||
import android.app.Activity;
|
||||
import android.content.Intent;
|
||||
import android.os.Bundle;
|
||||
import android.view.Menu;
|
||||
import android.view.MenuItem;
|
||||
import android.view.View;
|
||||
|
||||
import androidx.annotation.NonNull;
|
||||
import androidx.annotation.Nullable;
|
||||
import androidx.appcompat.app.AppCompatActivity;
|
||||
import androidx.appcompat.widget.Toolbar;
|
||||
import androidx.fragment.app.FragmentTransaction;
|
||||
|
||||
import org.nuclearfog.twidda.R;
|
||||
import org.nuclearfog.twidda.backend.utils.AppStyles;
|
||||
import org.nuclearfog.twidda.database.GlobalSettings;
|
||||
import org.nuclearfog.twidda.fragment.AccountFragment;
|
||||
import org.nuclearfog.twidda.fragment.ListFragment;
|
||||
|
||||
|
||||
/**
|
||||
* account manager activity
|
||||
*
|
||||
* @author nuclearfog
|
||||
*/
|
||||
public class AccountActivity extends AppCompatActivity {
|
||||
|
||||
/**
|
||||
* request login page
|
||||
*/
|
||||
private static final int REQ_LOGIN = 0xDF14;
|
||||
|
||||
/**
|
||||
* result code when an account was selected
|
||||
*/
|
||||
public static final int RET_ACCOUNT_CHANGE = 0x0456;
|
||||
|
||||
/**
|
||||
* key to disable account selector option from menu
|
||||
*/
|
||||
public static final String KEY_DISABLE_SELECTOR = "disable-acc-manager";
|
||||
|
||||
private GlobalSettings settings;
|
||||
private ListFragment fragment;
|
||||
|
||||
|
||||
@Override
|
||||
protected void onCreate(@Nullable Bundle savedInstanceState) {
|
||||
super.onCreate(savedInstanceState);
|
||||
setContentView(R.layout.page_fragment);
|
||||
View root = findViewById(R.id.fragment_root);
|
||||
Toolbar tool = findViewById(R.id.fragment_toolbar);
|
||||
fragment = new AccountFragment();
|
||||
|
||||
FragmentTransaction fragmentTransaction = getSupportFragmentManager().beginTransaction();
|
||||
fragmentTransaction.replace(R.id.fragment_container, fragment);
|
||||
fragmentTransaction.commit();
|
||||
|
||||
tool.setTitle(R.string.account_page);
|
||||
setSupportActionBar(tool);
|
||||
|
||||
settings = GlobalSettings.getInstance(this);
|
||||
AppStyles.setTheme(settings, root);
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public void onBackPressed() {
|
||||
setResult(RESULT_OK);
|
||||
super.onBackPressed();
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public boolean onCreateOptionsMenu(Menu m) {
|
||||
getMenuInflater().inflate(R.menu.accounts, m);
|
||||
// disable account selector icon if this activity started from LoginActivity
|
||||
boolean disableSelector = getIntent().getBooleanExtra(KEY_DISABLE_SELECTOR, false);
|
||||
m.findItem(R.id.action_add_account).setVisible(!disableSelector);
|
||||
// theme icons
|
||||
AppStyles.setMenuIconColor(m, settings.getIconColor());
|
||||
return super.onCreateOptionsMenu(m);
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public boolean onOptionsItemSelected(@NonNull MenuItem item) {
|
||||
if (item.getItemId() == R.id.action_add_account) {
|
||||
// open login page to add new account
|
||||
Intent loginIntent = new Intent(this, LoginActivity.class);
|
||||
startActivityForResult(loginIntent, REQ_LOGIN);
|
||||
return true;
|
||||
}
|
||||
return super.onOptionsItemSelected(item);
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
protected void onActivityResult(int requestCode, int resultCode, @Nullable Intent data) {
|
||||
super.onActivityResult(requestCode, resultCode, data);
|
||||
if (requestCode == REQ_LOGIN && resultCode == Activity.RESULT_OK) {
|
||||
// new account registered, reload fragment
|
||||
fragment.reset();
|
||||
}
|
||||
}
|
||||
}
|
@ -39,6 +39,7 @@ import org.nuclearfog.twidda.backend.engine.TwitterEngine;
|
||||
import org.nuclearfog.twidda.backend.model.TrendLocation;
|
||||
import org.nuclearfog.twidda.backend.utils.AppStyles;
|
||||
import org.nuclearfog.twidda.backend.utils.ErrorHandler;
|
||||
import org.nuclearfog.twidda.database.AccountDatabase;
|
||||
import org.nuclearfog.twidda.database.DatabaseAdapter;
|
||||
import org.nuclearfog.twidda.database.GlobalSettings;
|
||||
import org.nuclearfog.twidda.dialog.ConfirmDialog;
|
||||
@ -257,9 +258,13 @@ public class AppSettings extends AppCompatActivity implements OnClickListener, O
|
||||
public void onConfirm(DialogType type) {
|
||||
// confirm log out
|
||||
if (type == DialogType.APP_LOG_OUT) {
|
||||
settings.logout();
|
||||
// reset twitter singleton
|
||||
TwitterEngine.resetTwitter();
|
||||
// remove account from database
|
||||
// todo remove database and entry asynchronously
|
||||
AccountDatabase.getInstance(this).removeLogin(settings.getCurrentUserId());
|
||||
DatabaseAdapter.deleteDatabase(getApplicationContext());
|
||||
settings.logout();
|
||||
setResult(RETURN_APP_LOGOUT);
|
||||
finish();
|
||||
}
|
||||
|
@ -10,12 +10,12 @@ import androidx.annotation.NonNull;
|
||||
import androidx.annotation.Nullable;
|
||||
import androidx.appcompat.app.AppCompatActivity;
|
||||
import androidx.appcompat.widget.Toolbar;
|
||||
import androidx.viewpager.widget.ViewPager;
|
||||
import androidx.fragment.app.FragmentTransaction;
|
||||
|
||||
import org.nuclearfog.twidda.R;
|
||||
import org.nuclearfog.twidda.adapter.FragmentAdapter;
|
||||
import org.nuclearfog.twidda.backend.utils.AppStyles;
|
||||
import org.nuclearfog.twidda.database.GlobalSettings;
|
||||
import org.nuclearfog.twidda.fragment.MessageFragment;
|
||||
|
||||
/**
|
||||
* Activity for the direct message page of the current user
|
||||
@ -29,19 +29,17 @@ public class DirectMessage extends AppCompatActivity {
|
||||
@Override
|
||||
protected void onCreate(@Nullable Bundle b) {
|
||||
super.onCreate(b);
|
||||
setContentView(R.layout.page_dm);
|
||||
Toolbar tool = findViewById(R.id.dm_toolbar);
|
||||
View root = findViewById(R.id.dm_layout);
|
||||
ViewPager pager = findViewById(R.id.dm_pager);
|
||||
setContentView(R.layout.page_fragment);
|
||||
View root = findViewById(R.id.fragment_root);
|
||||
Toolbar tool = findViewById(R.id.fragment_toolbar);
|
||||
|
||||
FragmentTransaction fragmentTransaction = getSupportFragmentManager().beginTransaction();
|
||||
fragmentTransaction.replace(R.id.fragment_container, new MessageFragment());
|
||||
fragmentTransaction.commit();
|
||||
|
||||
tool.setTitle(R.string.directmessage);
|
||||
setSupportActionBar(tool);
|
||||
|
||||
FragmentAdapter adapter = new FragmentAdapter(getSupportFragmentManager());
|
||||
adapter.setupMessagePage();
|
||||
pager.setOffscreenPageLimit(1);
|
||||
pager.setAdapter(adapter);
|
||||
|
||||
settings = GlobalSettings.getInstance(this);
|
||||
AppStyles.setTheme(settings, root);
|
||||
}
|
||||
|
@ -30,15 +30,19 @@ import static android.os.AsyncTask.Status.FINISHED;
|
||||
import static android.os.AsyncTask.Status.RUNNING;
|
||||
import static android.widget.Toast.LENGTH_LONG;
|
||||
import static android.widget.Toast.LENGTH_SHORT;
|
||||
import static org.nuclearfog.twidda.activity.AccountActivity.KEY_DISABLE_SELECTOR;
|
||||
import static org.nuclearfog.twidda.activity.AccountActivity.RET_ACCOUNT_CHANGE;
|
||||
|
||||
/**
|
||||
* Login Activity of the App
|
||||
* Account Activity of the App
|
||||
* called from {@link MainActivity} when this app isn't logged in to twitter
|
||||
*
|
||||
* @author nuclearfog
|
||||
*/
|
||||
public class LoginActivity extends AppCompatActivity implements OnClickListener {
|
||||
|
||||
private static final int REQUEST_ACCOUNT_SELECT = 0x384F;
|
||||
|
||||
private Registration registerAsync;
|
||||
private GlobalSettings settings;
|
||||
|
||||
@ -100,11 +104,24 @@ public class LoginActivity extends AppCompatActivity implements OnClickListener
|
||||
if (item.getItemId() == R.id.login_setting) {
|
||||
Intent settings = new Intent(this, AppSettings.class);
|
||||
startActivity(settings);
|
||||
} else if (item.getItemId() == R.id.login_select_account) {
|
||||
Intent accountManager = new Intent(this, AccountActivity.class);
|
||||
accountManager.putExtra(KEY_DISABLE_SELECTOR, true);
|
||||
startActivityForResult(accountManager, REQUEST_ACCOUNT_SELECT);
|
||||
}
|
||||
return super.onOptionsItemSelected(item);
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
protected void onActivityResult(int requestCode, int resultCode, @Nullable Intent data) {
|
||||
super.onActivityResult(requestCode, resultCode, data);
|
||||
if (requestCode == REQUEST_ACCOUNT_SELECT && resultCode == RET_ACCOUNT_CHANGE) {
|
||||
// account selected, return to MainActivity
|
||||
onSuccess();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onClick(View v) {
|
||||
// get login request link
|
||||
@ -117,9 +134,12 @@ public class LoginActivity extends AppCompatActivity implements OnClickListener
|
||||
}
|
||||
// verify user
|
||||
else if (v.getId() == R.id.login_verifier) {
|
||||
// check if user clicked on PIN button
|
||||
if (registerAsync == null || registerAsync.getStatus() != FINISHED) {
|
||||
Toast.makeText(this, R.string.info_get_link, LENGTH_LONG).show();
|
||||
} else if (pinInput.getText() != null && pinInput.length() > 0) {
|
||||
}
|
||||
// check if PIN exists
|
||||
else if (pinInput.getText() != null && pinInput.length() > 0) {
|
||||
Toast.makeText(this, R.string.info_login_to_twitter, LENGTH_LONG).show();
|
||||
String twitterPin = pinInput.getText().toString();
|
||||
registerAsync = new Registration(this);
|
||||
|
@ -161,6 +161,7 @@ public class MainActivity extends AppCompatActivity implements OnTabSelectedList
|
||||
MenuItem tweet = m.findItem(R.id.action_tweet);
|
||||
MenuItem search = m.findItem(R.id.action_search);
|
||||
MenuItem setting = m.findItem(R.id.action_settings);
|
||||
MenuItem account = m.findItem(R.id.action_account);
|
||||
|
||||
switch (tablayout.getSelectedTabPosition()) {
|
||||
case 0:
|
||||
@ -168,6 +169,7 @@ public class MainActivity extends AppCompatActivity implements OnTabSelectedList
|
||||
search.setVisible(false);
|
||||
tweet.setVisible(true);
|
||||
setting.setVisible(false);
|
||||
account.setVisible(false);
|
||||
search.collapseActionView();
|
||||
break;
|
||||
|
||||
@ -176,6 +178,7 @@ public class MainActivity extends AppCompatActivity implements OnTabSelectedList
|
||||
search.setVisible(true);
|
||||
tweet.setVisible(false);
|
||||
setting.setVisible(true);
|
||||
account.setVisible(false);
|
||||
break;
|
||||
|
||||
case 2:
|
||||
@ -183,6 +186,7 @@ public class MainActivity extends AppCompatActivity implements OnTabSelectedList
|
||||
search.setVisible(false);
|
||||
tweet.setVisible(false);
|
||||
setting.setVisible(true);
|
||||
account.setVisible(true);
|
||||
search.collapseActionView();
|
||||
break;
|
||||
}
|
||||
@ -213,6 +217,11 @@ public class MainActivity extends AppCompatActivity implements OnTabSelectedList
|
||||
SearchView searchView = (SearchView) item.getActionView();
|
||||
AppStyles.setTheme(settings, searchView, Color.TRANSPARENT);
|
||||
}
|
||||
// open account manager
|
||||
else if (item.getItemId() == R.id.action_account) {
|
||||
Intent accountManager = new Intent(this, AccountActivity.class);
|
||||
startActivityForResult(accountManager, REQUEST_APP_LOGIN);
|
||||
}
|
||||
return super.onOptionsItemSelected(item);
|
||||
}
|
||||
|
||||
|
@ -158,10 +158,10 @@ public class MediaViewer extends MediaActivity implements OnImageClickListener,
|
||||
play.setImageResource(R.drawable.play);
|
||||
pause.setImageResource(R.drawable.pause);
|
||||
|
||||
adapter = new ImageAdapter(this);
|
||||
GlobalSettings settings = GlobalSettings.getInstance(this);
|
||||
AppStyles.setProgressColor(loadingCircle, settings.getHighlightColor());
|
||||
AppStyles.setTheme(settings, controlPanel, settings.getCardColor());
|
||||
adapter = new ImageAdapter(settings, this);
|
||||
|
||||
// get intent data and type
|
||||
mediaLinks = getIntent().getStringArrayExtra(KEY_MEDIA_LINK);
|
||||
|
@ -23,7 +23,7 @@ import androidx.annotation.NonNull;
|
||||
import androidx.annotation.Nullable;
|
||||
import androidx.appcompat.app.AppCompatActivity;
|
||||
import androidx.appcompat.widget.Toolbar;
|
||||
import androidx.viewpager.widget.ViewPager;
|
||||
import androidx.fragment.app.FragmentTransaction;
|
||||
|
||||
import com.squareup.picasso.Picasso;
|
||||
|
||||
@ -31,7 +31,6 @@ import org.nuclearfog.tag.Tagger;
|
||||
import org.nuclearfog.tag.Tagger.OnTagClickListener;
|
||||
import org.nuclearfog.textviewtool.LinkAndScrollMovement;
|
||||
import org.nuclearfog.twidda.R;
|
||||
import org.nuclearfog.twidda.adapter.FragmentAdapter;
|
||||
import org.nuclearfog.twidda.backend.TweetAction;
|
||||
import org.nuclearfog.twidda.backend.TweetAction.Action;
|
||||
import org.nuclearfog.twidda.backend.engine.EngineException;
|
||||
@ -44,6 +43,7 @@ import org.nuclearfog.twidda.dialog.ConfirmDialog;
|
||||
import org.nuclearfog.twidda.dialog.ConfirmDialog.DialogType;
|
||||
import org.nuclearfog.twidda.dialog.ConfirmDialog.OnConfirmListener;
|
||||
import org.nuclearfog.twidda.dialog.LinkDialog;
|
||||
import org.nuclearfog.twidda.fragment.TweetFragment;
|
||||
|
||||
import java.text.NumberFormat;
|
||||
import java.text.SimpleDateFormat;
|
||||
@ -68,8 +68,12 @@ import static org.nuclearfog.twidda.activity.UserDetail.KEY_USERDETAIL_MODE;
|
||||
import static org.nuclearfog.twidda.activity.UserDetail.USERLIST_RETWEETS;
|
||||
import static org.nuclearfog.twidda.fragment.TweetFragment.INTENT_TWEET_REMOVED_ID;
|
||||
import static org.nuclearfog.twidda.fragment.TweetFragment.INTENT_TWEET_UPDATE_DATA;
|
||||
import static org.nuclearfog.twidda.fragment.TweetFragment.KEY_FRAG_TWEET_ID;
|
||||
import static org.nuclearfog.twidda.fragment.TweetFragment.KEY_FRAG_TWEET_MODE;
|
||||
import static org.nuclearfog.twidda.fragment.TweetFragment.KEY_FRAG_TWEET_SEARCH;
|
||||
import static org.nuclearfog.twidda.fragment.TweetFragment.RETURN_TWEET_NOT_FOUND;
|
||||
import static org.nuclearfog.twidda.fragment.TweetFragment.RETURN_TWEET_UPDATE;
|
||||
import static org.nuclearfog.twidda.fragment.TweetFragment.TWEET_FRAG_ANSWER;
|
||||
|
||||
/**
|
||||
* Tweet Activity for tweet and user information
|
||||
@ -118,7 +122,6 @@ public class TweetActivity extends AppCompatActivity implements OnClickListener,
|
||||
super.onCreate(b);
|
||||
setContentView(R.layout.page_tweet);
|
||||
View root = findViewById(R.id.tweet_layout);
|
||||
ViewPager pager = findViewById(R.id.tweet_pager);
|
||||
toolbar = findViewById(R.id.tweet_toolbar);
|
||||
ansButton = findViewById(R.id.tweet_answer);
|
||||
rtwButton = findViewById(R.id.tweet_retweet);
|
||||
@ -136,6 +139,7 @@ public class TweetActivity extends AppCompatActivity implements OnClickListener,
|
||||
sensitive_media = findViewById(R.id.tweet_sensitive);
|
||||
retweeter = findViewById(R.id.tweet_retweeter_reference);
|
||||
|
||||
// get parameter
|
||||
Object data = getIntent().getSerializableExtra(KEY_TWEET_DATA);
|
||||
long tweetId;
|
||||
String username;
|
||||
@ -153,10 +157,17 @@ public class TweetActivity extends AppCompatActivity implements OnClickListener,
|
||||
username = getIntent().getStringExtra(KEY_TWEET_NAME);
|
||||
tweetId = getIntent().getLongExtra(KEY_TWEET_ID, -1);
|
||||
}
|
||||
FragmentAdapter adapter = new FragmentAdapter(getSupportFragmentManager());
|
||||
adapter.setupTweetPage(tweetId, username);
|
||||
pager.setOffscreenPageLimit(1);
|
||||
pager.setAdapter(adapter);
|
||||
|
||||
// create list fragment for tweet replies
|
||||
Bundle param = new Bundle();
|
||||
param.putInt(KEY_FRAG_TWEET_MODE, TWEET_FRAG_ANSWER);
|
||||
param.putString(KEY_FRAG_TWEET_SEARCH, username);
|
||||
param.putLong(KEY_FRAG_TWEET_ID, tweetId);
|
||||
|
||||
// insert fragment into view
|
||||
FragmentTransaction fragmentTransaction = getSupportFragmentManager().beginTransaction();
|
||||
fragmentTransaction.replace(R.id.tweet_reply_fragment, TweetFragment.class, param);
|
||||
fragmentTransaction.commit();
|
||||
|
||||
settings = GlobalSettings.getInstance(this);
|
||||
ansButton.setCompoundDrawablesWithIntrinsicBounds(R.drawable.answer, 0, 0, 0);
|
||||
@ -168,12 +179,14 @@ public class TweetActivity extends AppCompatActivity implements OnClickListener,
|
||||
retweeter.setCompoundDrawablesWithIntrinsicBounds(R.drawable.retweet, 0, 0, 0);
|
||||
tweetText.setMovementMethod(LinkAndScrollMovement.getInstance());
|
||||
tweetText.setLinkTextColor(settings.getHighlightColor());
|
||||
deleteDialog = new ConfirmDialog(this, DialogType.TWEET_DELETE, this);
|
||||
linkPreview = new LinkDialog(this);
|
||||
|
||||
toolbar.setTitle("");
|
||||
setSupportActionBar(toolbar);
|
||||
AppStyles.setTheme(settings, root);
|
||||
|
||||
deleteDialog = new ConfirmDialog(this, DialogType.TWEET_DELETE, this);
|
||||
linkPreview = new LinkDialog(this);
|
||||
|
||||
retweeter.setOnClickListener(this);
|
||||
replyName.setOnClickListener(this);
|
||||
ansButton.setOnClickListener(this);
|
||||
|
@ -7,12 +7,18 @@ import android.view.View;
|
||||
import androidx.annotation.Nullable;
|
||||
import androidx.appcompat.app.AppCompatActivity;
|
||||
import androidx.appcompat.widget.Toolbar;
|
||||
import androidx.viewpager.widget.ViewPager;
|
||||
import androidx.fragment.app.FragmentTransaction;
|
||||
|
||||
import org.nuclearfog.twidda.R;
|
||||
import org.nuclearfog.twidda.adapter.FragmentAdapter;
|
||||
import org.nuclearfog.twidda.backend.utils.AppStyles;
|
||||
import org.nuclearfog.twidda.database.GlobalSettings;
|
||||
import org.nuclearfog.twidda.fragment.UserFragment;
|
||||
|
||||
import static org.nuclearfog.twidda.fragment.UserFragment.KEY_FRAG_USER_ID;
|
||||
import static org.nuclearfog.twidda.fragment.UserFragment.KEY_FRAG_USER_MODE;
|
||||
import static org.nuclearfog.twidda.fragment.UserFragment.USER_FRAG_FOLLOWS;
|
||||
import static org.nuclearfog.twidda.fragment.UserFragment.USER_FRAG_FRIENDS;
|
||||
import static org.nuclearfog.twidda.fragment.UserFragment.USER_FRAG_RETWEET;
|
||||
|
||||
/**
|
||||
* Activity to show a list of twitter users
|
||||
@ -51,34 +57,52 @@ public class UserDetail extends AppCompatActivity {
|
||||
@Override
|
||||
protected void onCreate(@Nullable Bundle b) {
|
||||
super.onCreate(b);
|
||||
setContentView(R.layout.page_userlist);
|
||||
View root = findViewById(R.id.user_view);
|
||||
Toolbar toolbar = findViewById(R.id.user_toolbar);
|
||||
ViewPager pager = findViewById(R.id.user_pager);
|
||||
|
||||
GlobalSettings settings = GlobalSettings.getInstance(this);
|
||||
FragmentAdapter adapter = new FragmentAdapter(getSupportFragmentManager());
|
||||
pager.setAdapter(adapter);
|
||||
setContentView(R.layout.page_fragment);
|
||||
View root = findViewById(R.id.fragment_root);
|
||||
Toolbar toolbar = findViewById(R.id.fragment_toolbar);
|
||||
|
||||
// get parameter
|
||||
Intent data = getIntent();
|
||||
int mode = data.getIntExtra(KEY_USERDETAIL_MODE, 0);
|
||||
long id = data.getLongExtra(KEY_USERDETAIL_ID, -1);
|
||||
switch (data.getIntExtra(KEY_USERDETAIL_MODE, 0)) {
|
||||
|
||||
Bundle param = new Bundle();
|
||||
|
||||
switch (mode) {
|
||||
case USERLIST_FRIENDS:
|
||||
// set fragment parameter
|
||||
param.putLong(KEY_FRAG_USER_ID, id);
|
||||
param.putInt(KEY_FRAG_USER_MODE, USER_FRAG_FRIENDS);
|
||||
// set toolbar title
|
||||
toolbar.setTitle(R.string.userlist_following);
|
||||
adapter.setupFriendsPage(id);
|
||||
break;
|
||||
|
||||
case USERLIST_FOLLOWER:
|
||||
// set fragment parameter
|
||||
param.putLong(KEY_FRAG_USER_ID, id);
|
||||
param.putInt(KEY_FRAG_USER_MODE, USER_FRAG_FOLLOWS);
|
||||
// set toolbar title
|
||||
toolbar.setTitle(R.string.userlist_follower);
|
||||
adapter.setupFollowerPage(id);
|
||||
break;
|
||||
|
||||
case USERLIST_RETWEETS:
|
||||
// set fragment parameter
|
||||
param.putLong(KEY_FRAG_USER_ID, id);
|
||||
param.putInt(KEY_FRAG_USER_MODE, USER_FRAG_RETWEET);
|
||||
// set toolbar title
|
||||
toolbar.setTitle(R.string.toolbar_userlist_retweet);
|
||||
adapter.setupRetweeterPage(id);
|
||||
break;
|
||||
}
|
||||
// insert fragment into view
|
||||
FragmentTransaction fragmentTransaction = getSupportFragmentManager().beginTransaction();
|
||||
fragmentTransaction.replace(R.id.fragment_container, UserFragment.class, param, "");
|
||||
fragmentTransaction.commit();
|
||||
|
||||
// set toolbar
|
||||
setSupportActionBar(toolbar);
|
||||
|
||||
// style activity
|
||||
GlobalSettings settings = GlobalSettings.getInstance(this);
|
||||
AppStyles.setTheme(settings, root);
|
||||
}
|
||||
}
|
@ -0,0 +1,136 @@
|
||||
package org.nuclearfog.twidda.adapter;
|
||||
|
||||
import android.view.View;
|
||||
import android.view.ViewGroup;
|
||||
|
||||
import androidx.annotation.MainThread;
|
||||
import androidx.annotation.NonNull;
|
||||
import androidx.recyclerview.widget.RecyclerView.Adapter;
|
||||
|
||||
import com.squareup.picasso.Picasso;
|
||||
|
||||
import org.nuclearfog.twidda.R;
|
||||
import org.nuclearfog.twidda.adapter.holder.LoginHolder;
|
||||
import org.nuclearfog.twidda.backend.model.Account;
|
||||
import org.nuclearfog.twidda.backend.model.User;
|
||||
import org.nuclearfog.twidda.backend.utils.StringTools;
|
||||
import org.nuclearfog.twidda.database.GlobalSettings;
|
||||
import org.nuclearfog.twidda.fragment.AccountFragment;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
import jp.wasabeef.picasso.transformations.RoundedCornersTransformation;
|
||||
|
||||
import static androidx.recyclerview.widget.RecyclerView.NO_POSITION;
|
||||
|
||||
/**
|
||||
* adapter for {@link AccountFragment}
|
||||
*
|
||||
* @author nuclearfog
|
||||
*/
|
||||
public class AccountAdapter extends Adapter<LoginHolder> {
|
||||
|
||||
private List<Account> data = new ArrayList<>();
|
||||
private GlobalSettings settings;
|
||||
private OnLoginClickListener listener;
|
||||
|
||||
/**
|
||||
*
|
||||
*/
|
||||
public AccountAdapter(GlobalSettings settings, OnLoginClickListener l) {
|
||||
this.settings = settings;
|
||||
this.listener = l;
|
||||
}
|
||||
|
||||
/**
|
||||
* sets login data
|
||||
*
|
||||
* @param data list with login items
|
||||
*/
|
||||
public void setData(List<Account> data) {
|
||||
this.data.clear();
|
||||
this.data.addAll(data);
|
||||
notifyDataSetChanged();
|
||||
}
|
||||
|
||||
|
||||
@NonNull
|
||||
@Override
|
||||
public LoginHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) {
|
||||
final LoginHolder holder = new LoginHolder(parent, settings);
|
||||
holder.itemView.setOnClickListener(new View.OnClickListener() {
|
||||
@Override
|
||||
public void onClick(View v) {
|
||||
int position = holder.getLayoutPosition();
|
||||
if (position != NO_POSITION) {
|
||||
Account account = data.get(position);
|
||||
listener.onLoginClick(account);
|
||||
}
|
||||
}
|
||||
});
|
||||
holder.remove.setOnClickListener(new View.OnClickListener() {
|
||||
@Override
|
||||
public void onClick(View v) {
|
||||
int position = holder.getLayoutPosition();
|
||||
if (position != NO_POSITION) {
|
||||
Account account = data.get(position);
|
||||
listener.onDeleteClick(account);
|
||||
}
|
||||
}
|
||||
});
|
||||
return holder;
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public void onBindViewHolder(@NonNull LoginHolder holder, int position) {
|
||||
Account account = data.get(position);
|
||||
User user = account.getUser();
|
||||
String date = StringTools.formatCreationTime(account.getLoginDate());
|
||||
holder.date.setText(date);
|
||||
if (user != null) {
|
||||
holder.username.setText(user.getUsername());
|
||||
holder.screenname.setText(user.getScreenname());
|
||||
String pbLink = user.getImageLink();
|
||||
if (!user.hasDefaultProfileImage()) {
|
||||
pbLink += settings.getImageSuffix();
|
||||
}
|
||||
Picasso.get().load(pbLink).transform(new RoundedCornersTransformation(2, 0))
|
||||
.error(R.drawable.no_image).into(holder.profile);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public int getItemCount() {
|
||||
return data.size();
|
||||
}
|
||||
|
||||
|
||||
@MainThread
|
||||
public void clear() {
|
||||
data.clear();
|
||||
notifyDataSetChanged();
|
||||
}
|
||||
|
||||
/**
|
||||
* click listener for an item
|
||||
*/
|
||||
public interface OnLoginClickListener {
|
||||
|
||||
/**
|
||||
* called on item select
|
||||
*
|
||||
* @param account selected account information
|
||||
*/
|
||||
void onLoginClick(Account account);
|
||||
|
||||
/**
|
||||
* called to remove item
|
||||
*
|
||||
* @param account selected account information
|
||||
*/
|
||||
void onDeleteClick(Account account);
|
||||
}
|
||||
}
|
@ -8,7 +8,6 @@ import androidx.fragment.app.FragmentManager;
|
||||
import androidx.fragment.app.FragmentStatePagerAdapter;
|
||||
|
||||
import org.nuclearfog.twidda.fragment.ListFragment;
|
||||
import org.nuclearfog.twidda.fragment.MessageFragment;
|
||||
import org.nuclearfog.twidda.fragment.TrendFragment;
|
||||
import org.nuclearfog.twidda.fragment.TweetFragment;
|
||||
import org.nuclearfog.twidda.fragment.UserFragment;
|
||||
@ -17,7 +16,6 @@ import org.nuclearfog.twidda.fragment.UserListFragment;
|
||||
import static org.nuclearfog.twidda.fragment.TweetFragment.KEY_FRAG_TWEET_ID;
|
||||
import static org.nuclearfog.twidda.fragment.TweetFragment.KEY_FRAG_TWEET_MODE;
|
||||
import static org.nuclearfog.twidda.fragment.TweetFragment.KEY_FRAG_TWEET_SEARCH;
|
||||
import static org.nuclearfog.twidda.fragment.TweetFragment.TWEET_FRAG_ANSWER;
|
||||
import static org.nuclearfog.twidda.fragment.TweetFragment.TWEET_FRAG_FAVORS;
|
||||
import static org.nuclearfog.twidda.fragment.TweetFragment.TWEET_FRAG_HOME;
|
||||
import static org.nuclearfog.twidda.fragment.TweetFragment.TWEET_FRAG_LIST;
|
||||
@ -28,10 +26,7 @@ import static org.nuclearfog.twidda.fragment.UserFragment.KEY_FRAG_DEL_USER;
|
||||
import static org.nuclearfog.twidda.fragment.UserFragment.KEY_FRAG_USER_ID;
|
||||
import static org.nuclearfog.twidda.fragment.UserFragment.KEY_FRAG_USER_MODE;
|
||||
import static org.nuclearfog.twidda.fragment.UserFragment.KEY_FRAG_USER_SEARCH;
|
||||
import static org.nuclearfog.twidda.fragment.UserFragment.USER_FRAG_FOLLOWS;
|
||||
import static org.nuclearfog.twidda.fragment.UserFragment.USER_FRAG_FRIENDS;
|
||||
import static org.nuclearfog.twidda.fragment.UserFragment.USER_FRAG_LISTS;
|
||||
import static org.nuclearfog.twidda.fragment.UserFragment.USER_FRAG_RETWEET;
|
||||
import static org.nuclearfog.twidda.fragment.UserFragment.USER_FRAG_SEARCH;
|
||||
import static org.nuclearfog.twidda.fragment.UserFragment.USER_FRAG_SUBSCR;
|
||||
import static org.nuclearfog.twidda.fragment.UserListFragment.KEY_FRAG_LIST_LIST_TYPE;
|
||||
@ -149,77 +144,6 @@ public class FragmentAdapter extends FragmentStatePagerAdapter {
|
||||
notifyDataSetChanged();
|
||||
}
|
||||
|
||||
/**
|
||||
* setup adapter for tweet page to show replies of a tweet
|
||||
*
|
||||
* @param tweetId ID of the tweet
|
||||
* @param replyName screen name of the author, needed to search for answers
|
||||
*/
|
||||
public void setupTweetPage(long tweetId, String replyName) {
|
||||
Bundle param = new Bundle();
|
||||
param.putInt(KEY_FRAG_TWEET_MODE, TWEET_FRAG_ANSWER);
|
||||
param.putString(KEY_FRAG_TWEET_SEARCH, replyName);
|
||||
param.putLong(KEY_FRAG_TWEET_ID, tweetId);
|
||||
fragments = new ListFragment[1];
|
||||
fragments[0] = new TweetFragment();
|
||||
fragments[0].setArguments(param);
|
||||
notifyDataSetChanged();
|
||||
}
|
||||
|
||||
/**
|
||||
* setup adapter for a list of friends
|
||||
*
|
||||
* @param userId ID of the user
|
||||
*/
|
||||
public void setupFriendsPage(long userId) {
|
||||
Bundle param = new Bundle();
|
||||
param.putLong(KEY_FRAG_USER_ID, userId);
|
||||
param.putInt(KEY_FRAG_USER_MODE, USER_FRAG_FRIENDS);
|
||||
fragments = new ListFragment[1];
|
||||
fragments[0] = new UserFragment();
|
||||
fragments[0].setArguments(param);
|
||||
notifyDataSetChanged();
|
||||
}
|
||||
|
||||
/**
|
||||
* setup adapter for a list of follower
|
||||
*
|
||||
* @param userId ID of the user
|
||||
*/
|
||||
public void setupFollowerPage(long userId) {
|
||||
Bundle param = new Bundle();
|
||||
param.putLong(KEY_FRAG_USER_ID, userId);
|
||||
param.putInt(KEY_FRAG_USER_MODE, USER_FRAG_FOLLOWS);
|
||||
fragments = new ListFragment[1];
|
||||
fragments[0] = new UserFragment();
|
||||
fragments[0].setArguments(param);
|
||||
notifyDataSetChanged();
|
||||
}
|
||||
|
||||
/**
|
||||
* setup adapter for a list of direct messages
|
||||
*/
|
||||
public void setupMessagePage() {
|
||||
fragments = new ListFragment[1];
|
||||
fragments[0] = new MessageFragment();
|
||||
notifyDataSetChanged();
|
||||
}
|
||||
|
||||
/**
|
||||
* setup adapter for a list of users which retweets a tweet
|
||||
*
|
||||
* @param tweetId ID if the tweet
|
||||
*/
|
||||
public void setupRetweeterPage(long tweetId) {
|
||||
Bundle param = new Bundle();
|
||||
param.putLong(KEY_FRAG_USER_ID, tweetId);
|
||||
param.putInt(KEY_FRAG_USER_MODE, USER_FRAG_RETWEET);
|
||||
fragments = new ListFragment[1];
|
||||
fragments[0] = new UserFragment();
|
||||
fragments[0].setArguments(param);
|
||||
notifyDataSetChanged();
|
||||
}
|
||||
|
||||
/**
|
||||
* setup adapter for a list of user lists created by an user
|
||||
*
|
||||
|
@ -13,6 +13,7 @@ import androidx.recyclerview.widget.RecyclerView.ViewHolder;
|
||||
import org.nuclearfog.twidda.adapter.holder.Footer;
|
||||
import org.nuclearfog.twidda.adapter.holder.ImageItem;
|
||||
import org.nuclearfog.twidda.backend.holder.ImageHolder;
|
||||
import org.nuclearfog.twidda.database.GlobalSettings;
|
||||
|
||||
import java.util.LinkedList;
|
||||
import java.util.List;
|
||||
@ -39,6 +40,8 @@ public class ImageAdapter extends Adapter<ViewHolder> {
|
||||
|
||||
private OnImageClickListener itemClickListener;
|
||||
|
||||
private GlobalSettings settings;
|
||||
|
||||
private List<ImageHolder> images = new LinkedList<>();
|
||||
private boolean loading = false;
|
||||
private boolean saveImg = true;
|
||||
@ -46,8 +49,9 @@ public class ImageAdapter extends Adapter<ViewHolder> {
|
||||
/**
|
||||
* @param itemClickListener click listener
|
||||
*/
|
||||
public ImageAdapter(OnImageClickListener itemClickListener) {
|
||||
public ImageAdapter(GlobalSettings settings, OnImageClickListener itemClickListener) {
|
||||
this.itemClickListener = itemClickListener;
|
||||
this.settings = settings;
|
||||
}
|
||||
|
||||
/**
|
||||
@ -111,7 +115,7 @@ public class ImageAdapter extends Adapter<ViewHolder> {
|
||||
@Override
|
||||
public ViewHolder onCreateViewHolder(@NonNull final ViewGroup parent, int viewType) {
|
||||
if (viewType == PICTURE) {
|
||||
final ImageItem item = new ImageItem(parent);
|
||||
final ImageItem item = new ImageItem(parent, settings);
|
||||
item.preview.setOnClickListener(new OnClickListener() {
|
||||
@Override
|
||||
public void onClick(View v) {
|
||||
@ -137,7 +141,7 @@ public class ImageAdapter extends Adapter<ViewHolder> {
|
||||
}
|
||||
return item;
|
||||
} else {
|
||||
return new Footer(parent, true);
|
||||
return new Footer(parent, settings, true);
|
||||
}
|
||||
}
|
||||
|
||||
@ -157,16 +161,16 @@ public class ImageAdapter extends Adapter<ViewHolder> {
|
||||
public interface OnImageClickListener {
|
||||
|
||||
/**
|
||||
* simple click on image_add
|
||||
* called to select an image
|
||||
*
|
||||
* @param image selected image_add bitmap
|
||||
* @param image selected image bitmap
|
||||
*/
|
||||
void onImageClick(Bitmap image);
|
||||
|
||||
/**
|
||||
* long touch on image_add
|
||||
* called to save image to storage
|
||||
*
|
||||
* @param image selected image_add bitmap
|
||||
* @param image selected image bitmap
|
||||
* @param index current image index
|
||||
*/
|
||||
void onImageSave(Bitmap image, int index);
|
||||
|
@ -153,7 +153,7 @@ public class ListAdapter extends Adapter<ViewHolder> {
|
||||
@Override
|
||||
public ViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) {
|
||||
if (viewType == ITEM_LIST) {
|
||||
final ListHolder itemHolder = new ListHolder(parent);
|
||||
final ListHolder itemHolder = new ListHolder(parent, settings);
|
||||
itemHolder.profile_img.setOnClickListener(new OnClickListener() {
|
||||
@Override
|
||||
public void onClick(View v) {
|
||||
@ -178,7 +178,7 @@ public class ListAdapter extends Adapter<ViewHolder> {
|
||||
});
|
||||
return itemHolder;
|
||||
} else {
|
||||
final Footer footer = new Footer(parent, false);
|
||||
final Footer footer = new Footer(parent, settings, false);
|
||||
footer.loadBtn.setOnClickListener(new OnClickListener() {
|
||||
@Override
|
||||
public void onClick(View v) {
|
||||
|
@ -140,7 +140,7 @@ public class MessageAdapter extends Adapter<ViewHolder> {
|
||||
@Override
|
||||
public ViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) {
|
||||
if (viewType == TYPE_MESSAGE) {
|
||||
final MessageHolder vh = new MessageHolder(parent);
|
||||
final MessageHolder vh = new MessageHolder(parent, settings);
|
||||
vh.buttons[0].setOnClickListener(new View.OnClickListener() {
|
||||
@Override
|
||||
public void onClick(View v) {
|
||||
@ -170,7 +170,7 @@ public class MessageAdapter extends Adapter<ViewHolder> {
|
||||
});
|
||||
return vh;
|
||||
} else {
|
||||
final Footer footer = new Footer(parent, false);
|
||||
final Footer footer = new Footer(parent, settings, false);
|
||||
footer.loadBtn.setOnClickListener(new View.OnClickListener() {
|
||||
@Override
|
||||
public void onClick(View v) {
|
||||
|
@ -13,6 +13,7 @@ import androidx.recyclerview.widget.RecyclerView.ViewHolder;
|
||||
import org.nuclearfog.twidda.R;
|
||||
import org.nuclearfog.twidda.adapter.holder.TrendHolder;
|
||||
import org.nuclearfog.twidda.backend.model.Trend;
|
||||
import org.nuclearfog.twidda.database.GlobalSettings;
|
||||
|
||||
import java.text.NumberFormat;
|
||||
import java.util.ArrayList;
|
||||
@ -42,12 +43,14 @@ public class TrendAdapter extends Adapter<ViewHolder> {
|
||||
|
||||
|
||||
private TrendClickListener itemClickListener;
|
||||
private GlobalSettings settings;
|
||||
private List<Trend> trends = new ArrayList<>(INIT_COUNT);
|
||||
|
||||
/**
|
||||
* @param itemClickListener Listener for item click
|
||||
*/
|
||||
public TrendAdapter(TrendClickListener itemClickListener) {
|
||||
public TrendAdapter(GlobalSettings settings, TrendClickListener itemClickListener) {
|
||||
this.settings = settings;
|
||||
this.itemClickListener = itemClickListener;
|
||||
}
|
||||
|
||||
@ -91,7 +94,7 @@ public class TrendAdapter extends Adapter<ViewHolder> {
|
||||
@NonNull
|
||||
@Override
|
||||
public ViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) {
|
||||
final TrendHolder vh = new TrendHolder(parent);
|
||||
final TrendHolder vh = new TrendHolder(parent, settings);
|
||||
vh.itemView.setOnClickListener(new OnClickListener() {
|
||||
@Override
|
||||
public void onClick(View v) {
|
||||
|
@ -218,7 +218,7 @@ public class TweetAdapter extends Adapter<ViewHolder> {
|
||||
@Override
|
||||
public ViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) {
|
||||
if (viewType == VIEW_TWEET) {
|
||||
final TweetHolder vh = new TweetHolder(parent);
|
||||
final TweetHolder vh = new TweetHolder(parent, settings);
|
||||
vh.itemView.setOnClickListener(new OnClickListener() {
|
||||
@Override
|
||||
public void onClick(View v) {
|
||||
@ -231,7 +231,7 @@ public class TweetAdapter extends Adapter<ViewHolder> {
|
||||
});
|
||||
return vh;
|
||||
} else {
|
||||
final Footer footer = new Footer(parent, false);
|
||||
final Footer footer = new Footer(parent, settings, false);
|
||||
footer.loadBtn.setOnClickListener(new OnClickListener() {
|
||||
@Override
|
||||
public void onClick(View v) {
|
||||
|
@ -160,7 +160,7 @@ public class UserAdapter extends Adapter<ViewHolder> {
|
||||
@Override
|
||||
public ViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) {
|
||||
if (viewType == ITEM_USER) {
|
||||
final UserHolder vh = new UserHolder(parent);
|
||||
final UserHolder vh = new UserHolder(parent, settings);
|
||||
vh.itemView.setOnClickListener(new OnClickListener() {
|
||||
@Override
|
||||
public void onClick(View v) {
|
||||
@ -188,7 +188,7 @@ public class UserAdapter extends Adapter<ViewHolder> {
|
||||
}
|
||||
return vh;
|
||||
} else {
|
||||
final Footer footer = new Footer(parent, false);
|
||||
final Footer footer = new Footer(parent, settings, false);
|
||||
footer.loadBtn.setOnClickListener(new OnClickListener() {
|
||||
@Override
|
||||
public void onClick(View v) {
|
||||
|
@ -31,19 +31,19 @@ public class Footer extends ViewHolder {
|
||||
* @param parent Parent view from adapter
|
||||
* @param horizontal true if footer orientation is horizontal
|
||||
*/
|
||||
public Footer(ViewGroup parent, boolean horizontal) {
|
||||
public Footer(ViewGroup parent, GlobalSettings settings, boolean horizontal) {
|
||||
super(LayoutInflater.from(parent.getContext()).inflate(R.layout.item_placeholder, parent, false));
|
||||
// get views
|
||||
CardView background = (CardView) itemView;
|
||||
loadCircle = itemView.findViewById(R.id.placeholder_loading);
|
||||
loadBtn = itemView.findViewById(R.id.placeholder_button);
|
||||
|
||||
GlobalSettings settings = GlobalSettings.getInstance(parent.getContext());
|
||||
// theme views
|
||||
background.setCardBackgroundColor(settings.getCardColor());
|
||||
loadBtn.setTextColor(settings.getFontColor());
|
||||
loadBtn.setTypeface(settings.getTypeFace());
|
||||
AppStyles.setButtonColor(loadBtn, settings.getFontColor());
|
||||
AppStyles.setProgressColor(loadCircle, settings.getHighlightColor());
|
||||
|
||||
// enable extra views
|
||||
if (horizontal) {
|
||||
loadBtn.setVisibility(INVISIBLE);
|
||||
loadCircle.setVisibility(VISIBLE);
|
||||
@ -52,6 +52,11 @@ public class Footer extends ViewHolder {
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* enable or disable progress circle
|
||||
*
|
||||
* @param enable true to enable progress, false to disable
|
||||
*/
|
||||
public void setLoading(boolean enable) {
|
||||
if (enable) {
|
||||
loadCircle.setVisibility(VISIBLE);
|
||||
|
@ -26,14 +26,15 @@ public class ImageItem extends ViewHolder {
|
||||
/**
|
||||
* @param parent Parent view from adapter
|
||||
*/
|
||||
public ImageItem(ViewGroup parent) {
|
||||
public ImageItem(ViewGroup parent, GlobalSettings settings) {
|
||||
super(LayoutInflater.from(parent.getContext()).inflate(R.layout.item_image, parent, false));
|
||||
// get views
|
||||
CardView cardBackground = (CardView) itemView;
|
||||
preview = itemView.findViewById(R.id.item_image_preview);
|
||||
saveButton = itemView.findViewById(R.id.item_image_save);
|
||||
|
||||
// set icon
|
||||
saveButton.setImageResource(R.drawable.save);
|
||||
GlobalSettings settings = GlobalSettings.getInstance(parent.getContext());
|
||||
// theme views
|
||||
cardBackground.setCardBackgroundColor(settings.getCardColor());
|
||||
AppStyles.setButtonColor(saveButton, settings.getFontColor());
|
||||
AppStyles.setDrawableColor(saveButton, settings.getIconColor());
|
||||
|
@ -28,8 +28,9 @@ public class ListHolder extends ViewHolder {
|
||||
/**
|
||||
* @param parent Parent view from adapter
|
||||
*/
|
||||
public ListHolder(ViewGroup parent) {
|
||||
public ListHolder(ViewGroup parent, GlobalSettings settings) {
|
||||
super(LayoutInflater.from(parent.getContext()).inflate(R.layout.item_list, parent, false));
|
||||
// get views
|
||||
CardView background = (CardView) itemView;
|
||||
profile_img = itemView.findViewById(R.id.list_owner_profile);
|
||||
icons[0] = itemView.findViewById(R.id.list_user_verified);
|
||||
@ -47,7 +48,7 @@ public class ListHolder extends ViewHolder {
|
||||
textViews[5] = itemView.findViewById(R.id.list_member);
|
||||
textViews[6] = itemView.findViewById(R.id.list_subscriber);
|
||||
textViews[7] = itemView.findViewById(R.id.list_action);
|
||||
|
||||
// set icons
|
||||
icons[0].setImageResource(R.drawable.verify);
|
||||
icons[1].setImageResource(R.drawable.lock);
|
||||
icons[2].setImageResource(R.drawable.user);
|
||||
@ -55,8 +56,7 @@ public class ListHolder extends ViewHolder {
|
||||
icons[4].setImageResource(R.drawable.calendar);
|
||||
icons[5].setImageResource(R.drawable.lock);
|
||||
icons[6].setImageResource(R.drawable.followback);
|
||||
|
||||
GlobalSettings settings = GlobalSettings.getInstance(parent.getContext());
|
||||
// theme views
|
||||
for (TextView tv : textViews) {
|
||||
tv.setTextColor(settings.getFontColor());
|
||||
tv.setTypeface(settings.getTypeFace());
|
||||
|
@ -0,0 +1,53 @@
|
||||
package org.nuclearfog.twidda.adapter.holder;
|
||||
|
||||
import android.view.LayoutInflater;
|
||||
import android.view.ViewGroup;
|
||||
import android.widget.ImageButton;
|
||||
import android.widget.ImageView;
|
||||
import android.widget.TextView;
|
||||
|
||||
import androidx.cardview.widget.CardView;
|
||||
import androidx.recyclerview.widget.RecyclerView.ViewHolder;
|
||||
|
||||
import org.nuclearfog.twidda.R;
|
||||
import org.nuclearfog.twidda.backend.utils.AppStyles;
|
||||
import org.nuclearfog.twidda.database.GlobalSettings;
|
||||
|
||||
import static android.graphics.PorterDuff.Mode.SRC_IN;
|
||||
|
||||
/**
|
||||
* item holder for a user login item
|
||||
*
|
||||
* @author nuclearfog
|
||||
*/
|
||||
public class LoginHolder extends ViewHolder {
|
||||
|
||||
public final ImageView profile;
|
||||
public final TextView username, screenname, date;
|
||||
public final ImageButton remove;
|
||||
|
||||
/**
|
||||
*
|
||||
*/
|
||||
public LoginHolder(ViewGroup parent, GlobalSettings settings) {
|
||||
super(LayoutInflater.from(parent.getContext()).inflate(R.layout.item_login, parent, false));
|
||||
// get views
|
||||
CardView background = (CardView) itemView;
|
||||
username = itemView.findViewById(R.id.item_login_username);
|
||||
screenname = itemView.findViewById(R.id.item_login_screenname);
|
||||
date = itemView.findViewById(R.id.item_login_createdAt);
|
||||
remove = itemView.findViewById(R.id.item_login_remove);
|
||||
profile = itemView.findViewById(R.id.item_login_image);
|
||||
// theme views
|
||||
screenname.setTextColor(settings.getFontColor());
|
||||
screenname.setTypeface(settings.getTypeFace());
|
||||
screenname.setTextColor(settings.getFontColor());
|
||||
screenname.setTypeface(settings.getTypeFace());
|
||||
date.setTextColor(settings.getFontColor());
|
||||
date.setTypeface(settings.getTypeFace());
|
||||
remove.setImageResource(R.drawable.cross);
|
||||
remove.setColorFilter(settings.getIconColor(), SRC_IN);
|
||||
background.setCardBackgroundColor(settings.getCardColor());
|
||||
AppStyles.setButtonColor(remove, settings.getFontColor());
|
||||
}
|
||||
}
|
@ -31,8 +31,9 @@ public class MessageHolder extends ViewHolder {
|
||||
/**
|
||||
* @param parent Parent view from adapter
|
||||
*/
|
||||
public MessageHolder(ViewGroup parent) {
|
||||
public MessageHolder(ViewGroup parent, GlobalSettings settings) {
|
||||
super(LayoutInflater.from(parent.getContext()).inflate(R.layout.item_dm, parent, false));
|
||||
// get views
|
||||
CardView background = (CardView) itemView;
|
||||
ImageView receiver_icon = itemView.findViewById(R.id.dm_receiver_icon);
|
||||
profile_img = itemView.findViewById(R.id.dm_profile_img);
|
||||
@ -45,12 +46,11 @@ public class MessageHolder extends ViewHolder {
|
||||
textViews[4] = itemView.findViewById(R.id.dm_message);
|
||||
buttons[0] = itemView.findViewById(R.id.dm_answer);
|
||||
buttons[1] = itemView.findViewById(R.id.dm_delete);
|
||||
|
||||
// set icons
|
||||
receiver_icon.setImageResource(R.drawable.right);
|
||||
verifiedIcon.setImageResource(R.drawable.verify);
|
||||
lockedIcon.setImageResource(R.drawable.lock);
|
||||
|
||||
GlobalSettings settings = GlobalSettings.getInstance(parent.getContext());
|
||||
// theme views
|
||||
for (TextView tv : textViews) {
|
||||
tv.setTextColor(settings.getFontColor());
|
||||
tv.setTypeface(settings.getTypeFace());
|
||||
@ -64,6 +64,7 @@ public class MessageHolder extends ViewHolder {
|
||||
lockedIcon.setColorFilter(settings.getIconColor(), SRC_IN);
|
||||
receiver_icon.setColorFilter(settings.getIconColor(), SRC_IN);
|
||||
background.setCardBackgroundColor(settings.getCardColor());
|
||||
// make links clickable
|
||||
textViews[4].setMovementMethod(LinkMovementMethod.getInstance());
|
||||
}
|
||||
}
|
@ -23,14 +23,14 @@ public class TrendHolder extends ViewHolder {
|
||||
/**
|
||||
* @param parent Parent view from adapter
|
||||
*/
|
||||
public TrendHolder(ViewGroup parent) {
|
||||
public TrendHolder(ViewGroup parent, GlobalSettings settings) {
|
||||
super(LayoutInflater.from(parent.getContext()).inflate(R.layout.item_trend, parent, false));
|
||||
// get views
|
||||
CardView background = (CardView) itemView;
|
||||
textViews[0] = itemView.findViewById(R.id.trendpos);
|
||||
textViews[1] = itemView.findViewById(R.id.trendname);
|
||||
textViews[2] = itemView.findViewById(R.id.trendvol);
|
||||
|
||||
GlobalSettings settings = GlobalSettings.getInstance(parent.getContext());
|
||||
// theme views
|
||||
background.setCardBackgroundColor(settings.getCardColor());
|
||||
for (TextView tv : textViews) {
|
||||
tv.setTextColor(settings.getFontColor());
|
||||
|
@ -27,8 +27,9 @@ public class TweetHolder extends ViewHolder {
|
||||
/**
|
||||
* @param parent Parent view from adapter
|
||||
*/
|
||||
public TweetHolder(ViewGroup parent) {
|
||||
public TweetHolder(ViewGroup parent, GlobalSettings settings) {
|
||||
super(LayoutInflater.from(parent.getContext()).inflate(R.layout.item_tweet, parent, false));
|
||||
// get views
|
||||
CardView background = (CardView) itemView;
|
||||
profile = itemView.findViewById(R.id.tweetPb);
|
||||
verifiedIcon = itemView.findViewById(R.id.verified_icon);
|
||||
@ -43,14 +44,13 @@ public class TweetHolder extends ViewHolder {
|
||||
textViews[4] = itemView.findViewById(R.id.favorite_number);
|
||||
textViews[5] = itemView.findViewById(R.id.retweeter);
|
||||
textViews[6] = itemView.findViewById(R.id.time);
|
||||
|
||||
// set icons
|
||||
verifiedIcon.setImageResource(R.drawable.verify);
|
||||
lockedIcon.setImageResource(R.drawable.lock);
|
||||
rtUser.setImageResource(R.drawable.retweet);
|
||||
rtIcon.setImageResource(R.drawable.retweet);
|
||||
favIcon.setImageResource(R.drawable.favorite);
|
||||
|
||||
GlobalSettings settings = GlobalSettings.getInstance(parent.getContext());
|
||||
// theme views
|
||||
verifiedIcon.setColorFilter(settings.getIconColor(), SRC_IN);
|
||||
lockedIcon.setColorFilter(settings.getIconColor(), SRC_IN);
|
||||
rtUser.setColorFilter(settings.getIconColor(), SRC_IN);
|
||||
|
@ -30,8 +30,9 @@ public class UserHolder extends ViewHolder {
|
||||
/**
|
||||
* @param parent Parent view from adapter
|
||||
*/
|
||||
public UserHolder(ViewGroup parent) {
|
||||
public UserHolder(ViewGroup parent, GlobalSettings settings) {
|
||||
super(LayoutInflater.from(parent.getContext()).inflate(R.layout.item_user, parent, false));
|
||||
// get views
|
||||
CardView background = (CardView) itemView;
|
||||
ImageView followingIcon = itemView.findViewById(R.id.following_icon);
|
||||
ImageView followerIcon = itemView.findViewById(R.id.follower_icon);
|
||||
@ -43,14 +44,13 @@ public class UserHolder extends ViewHolder {
|
||||
verifyIcon = itemView.findViewById(R.id.useritem_verified);
|
||||
lockedIcon = itemView.findViewById(R.id.useritem_locked);
|
||||
delete = itemView.findViewById(R.id.useritem_del_user);
|
||||
|
||||
// set view icons
|
||||
followerIcon.setImageResource(R.drawable.follower);
|
||||
followingIcon.setImageResource(R.drawable.following);
|
||||
verifyIcon.setImageResource(R.drawable.verify);
|
||||
lockedIcon.setImageResource(R.drawable.lock);
|
||||
delete.setImageResource(R.drawable.cross);
|
||||
|
||||
GlobalSettings settings = GlobalSettings.getInstance(parent.getContext());
|
||||
// theme views
|
||||
background.setCardBackgroundColor(settings.getCardColor());
|
||||
followerIcon.setColorFilter(settings.getIconColor(), SRC_IN);
|
||||
followingIcon.setColorFilter(settings.getIconColor(), SRC_IN);
|
||||
|
@ -0,0 +1,84 @@
|
||||
package org.nuclearfog.twidda.backend;
|
||||
|
||||
import android.os.AsyncTask;
|
||||
|
||||
import androidx.annotation.Nullable;
|
||||
|
||||
import org.nuclearfog.twidda.backend.engine.EngineException;
|
||||
import org.nuclearfog.twidda.backend.engine.TwitterEngine;
|
||||
import org.nuclearfog.twidda.backend.model.Account;
|
||||
import org.nuclearfog.twidda.backend.model.User;
|
||||
import org.nuclearfog.twidda.database.AccountDatabase;
|
||||
import org.nuclearfog.twidda.fragment.AccountFragment;
|
||||
|
||||
import java.lang.ref.WeakReference;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* backend loader to get user information about user logins
|
||||
*
|
||||
* @author nuclearfog
|
||||
*/
|
||||
public class LoginLoader extends AsyncTask<Account, Void, List<Account>> {
|
||||
|
||||
@Nullable
|
||||
private EngineException err;
|
||||
private AccountDatabase database;
|
||||
private TwitterEngine mTwitter;
|
||||
private WeakReference<AccountFragment> callback;
|
||||
|
||||
/**
|
||||
*
|
||||
*/
|
||||
public LoginLoader(AccountFragment fragment) {
|
||||
super();
|
||||
callback = new WeakReference<>(fragment);
|
||||
database = AccountDatabase.getInstance(fragment.requireContext());
|
||||
mTwitter = TwitterEngine.getInstance(fragment.requireContext());
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
protected List<Account> doInBackground(Account... param) {
|
||||
try {
|
||||
// remove account if parameter is set
|
||||
if (param != null && param.length > 0) {
|
||||
database.removeLogin(param[0].getId());
|
||||
}
|
||||
// get registered users
|
||||
List<Account> result = database.getLogins();
|
||||
// download user information
|
||||
if (!result.isEmpty()) {
|
||||
// get all user IDs
|
||||
long[] ids = new long[result.size()];
|
||||
for (int i = 0; i < ids.length; i++) {
|
||||
ids[i] = result.get(i).getId();
|
||||
}
|
||||
// get user information
|
||||
List<User> users = mTwitter.getUsers(ids);
|
||||
for (int i = 0; i < users.size(); i++) {
|
||||
result.get(i).attachUser(users.get(i));
|
||||
}
|
||||
}
|
||||
return result;
|
||||
} catch (EngineException err) {
|
||||
this.err = err;
|
||||
} catch (Exception err) {
|
||||
err.printStackTrace();
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
protected void onPostExecute(List<Account> accounts) {
|
||||
AccountFragment fragment = callback.get();
|
||||
if (fragment != null) {
|
||||
if (accounts != null) {
|
||||
fragment.onSuccess(accounts);
|
||||
} else {
|
||||
fragment.onError(err);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
@ -7,6 +7,8 @@ import androidx.annotation.Nullable;
|
||||
import org.nuclearfog.twidda.activity.LoginActivity;
|
||||
import org.nuclearfog.twidda.backend.engine.EngineException;
|
||||
import org.nuclearfog.twidda.backend.engine.TwitterEngine;
|
||||
import org.nuclearfog.twidda.database.AccountDatabase;
|
||||
import org.nuclearfog.twidda.database.GlobalSettings;
|
||||
|
||||
import java.lang.ref.WeakReference;
|
||||
|
||||
@ -21,25 +23,36 @@ public class Registration extends AsyncTask<String, Void, String> {
|
||||
@Nullable
|
||||
private EngineException twException;
|
||||
private WeakReference<LoginActivity> callback;
|
||||
private AccountDatabase accountDB;
|
||||
private TwitterEngine mTwitter;
|
||||
private GlobalSettings settings;
|
||||
|
||||
/**
|
||||
* Login to twitter with PIN
|
||||
* Account to twitter with PIN
|
||||
*
|
||||
* @param callback Activity Context
|
||||
* @param activity Activity Context
|
||||
*/
|
||||
public Registration(LoginActivity callback) {
|
||||
public Registration(LoginActivity activity) {
|
||||
super();
|
||||
this.callback = new WeakReference<>(callback);
|
||||
mTwitter = TwitterEngine.getInstance(callback);
|
||||
this.callback = new WeakReference<>(activity);
|
||||
mTwitter = TwitterEngine.getInstance(activity);
|
||||
accountDB = AccountDatabase.getInstance(activity);
|
||||
settings = GlobalSettings.getInstance(activity);
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
protected String doInBackground(String... param) {
|
||||
try {
|
||||
// check if we need to backup current session
|
||||
if (settings.isLoggedIn() && !accountDB.exists(settings.getCurrentUserId())) {
|
||||
String[] tokens = settings.getCurrentUserAccessToken();
|
||||
accountDB.setLogin(settings.getCurrentUserId(), tokens[0], tokens[1]);
|
||||
}
|
||||
// no PIN means we need to request a token to login
|
||||
if (param.length == 0)
|
||||
return mTwitter.request();
|
||||
// login with pin
|
||||
mTwitter.initialize(param[0]);
|
||||
return "";
|
||||
} catch (EngineException twException) {
|
||||
|
@ -19,6 +19,7 @@ import org.nuclearfog.twidda.backend.model.TrendLocation;
|
||||
import org.nuclearfog.twidda.backend.model.Tweet;
|
||||
import org.nuclearfog.twidda.backend.model.TwitterList;
|
||||
import org.nuclearfog.twidda.backend.model.User;
|
||||
import org.nuclearfog.twidda.database.AccountDatabase;
|
||||
import org.nuclearfog.twidda.database.GlobalSettings;
|
||||
|
||||
import java.io.File;
|
||||
@ -27,6 +28,8 @@ import java.io.FileNotFoundException;
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.net.URL;
|
||||
import java.util.ArrayList;
|
||||
import java.util.HashMap;
|
||||
import java.util.LinkedList;
|
||||
import java.util.List;
|
||||
|
||||
@ -58,14 +61,15 @@ import twitter4j.conf.ConfigurationBuilder;
|
||||
@Obfuscate
|
||||
public class TwitterEngine {
|
||||
|
||||
private GlobalSettings settings;
|
||||
private static final TwitterEngine mTwitter = new TwitterEngine();
|
||||
|
||||
private Twitter twitter;
|
||||
@Nullable
|
||||
private RequestToken reqToken;
|
||||
@Nullable
|
||||
private AccessToken aToken;
|
||||
private GlobalSettings settings;
|
||||
private AccountDatabase accountDB;
|
||||
private Twitter twitter;
|
||||
|
||||
private boolean isInitialized = false;
|
||||
|
||||
@ -113,6 +117,7 @@ public class TwitterEngine {
|
||||
public static TwitterEngine getInstance(Context context) {
|
||||
if (!mTwitter.isInitialized) {
|
||||
mTwitter.settings = GlobalSettings.getInstance(context);
|
||||
mTwitter.accountDB = AccountDatabase.getInstance(context);
|
||||
if (mTwitter.settings.isLoggedIn()) {
|
||||
String[] keys = mTwitter.settings.getCurrentUserAccessToken();
|
||||
mTwitter.aToken = new AccessToken(keys[0], keys[1]);
|
||||
@ -163,6 +168,7 @@ public class TwitterEngine {
|
||||
aToken = new AccessToken(key1, key2);
|
||||
initTwitter();
|
||||
settings.setConnection(key1, key2, twitter.getId());
|
||||
accountDB.setLogin(twitter.getId(), key1, key2);
|
||||
} else {
|
||||
throw new EngineException(EngineException.InternalErrorType.TOKENNOTSET);
|
||||
}
|
||||
@ -415,6 +421,22 @@ public class TwitterEngine {
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* get a list of users
|
||||
*
|
||||
* @param users user IDs
|
||||
* @return list of users
|
||||
* @throws EngineException if Access is unavailable
|
||||
*/
|
||||
public List<User> getUsers(long[] users) throws EngineException {
|
||||
try {
|
||||
// todo add paging system
|
||||
return convertUserList(twitter.lookupUsers(users));
|
||||
} catch (Exception err) {
|
||||
throw new EngineException(err);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Get User
|
||||
*
|
||||
@ -784,14 +806,40 @@ public class TwitterEngine {
|
||||
try {
|
||||
DirectMessageList dmList;
|
||||
int load = settings.getListSize();
|
||||
if (cursor != null)
|
||||
if (cursor != null) {
|
||||
dmList = twitter.getDirectMessages(load, cursor);
|
||||
else
|
||||
} else {
|
||||
dmList = twitter.getDirectMessages(load);
|
||||
}
|
||||
MessageList result = new MessageList(cursor, dmList.getNextCursor());
|
||||
HashMap<Long, User> userMap = new HashMap<Long, User>();
|
||||
|
||||
for (DirectMessage dm : dmList) {
|
||||
try {
|
||||
result.add(getMessage(dm));
|
||||
// get sender of the message
|
||||
User sender;
|
||||
if (userMap.containsKey(dm.getSenderId())) {
|
||||
// recycle user information
|
||||
sender = userMap.get(dm.getSenderId());
|
||||
} else {
|
||||
// download new user information
|
||||
sender = getUser(dm.getSenderId());
|
||||
userMap.put(dm.getSenderId(), sender);
|
||||
|
||||
}
|
||||
// get receiver of the message
|
||||
User receiver;
|
||||
if (userMap.containsKey(dm.getRecipientId())) {
|
||||
// recycle user information
|
||||
receiver = userMap.get(dm.getRecipientId());
|
||||
} else {
|
||||
// download new user information
|
||||
receiver = getUser(dm.getRecipientId());
|
||||
userMap.put(dm.getRecipientId(), receiver);
|
||||
}
|
||||
// build message and add to list
|
||||
Message message = new Message(dm, sender, receiver);
|
||||
result.add(message);
|
||||
} catch (EngineException err) {
|
||||
// ignore messages from suspended/deleted users
|
||||
}
|
||||
@ -1144,7 +1192,8 @@ public class TwitterEngine {
|
||||
* @return User
|
||||
*/
|
||||
private List<User> convertUserList(List<twitter4j.User> users) throws TwitterException {
|
||||
List<User> result = new LinkedList<>();
|
||||
ArrayList<User> result = new ArrayList<>();
|
||||
result.ensureCapacity(users.size());
|
||||
for (twitter4j.User user : users) {
|
||||
User item = new User(user, twitter.getId());
|
||||
result.add(item);
|
||||
@ -1159,28 +1208,10 @@ public class TwitterEngine {
|
||||
* @return TwitterStatus
|
||||
*/
|
||||
private List<Tweet> convertStatusList(List<Status> statuses) throws TwitterException {
|
||||
List<Tweet> result = new LinkedList<>();
|
||||
ArrayList<Tweet> result = new ArrayList<>();
|
||||
result.ensureCapacity(statuses.size());
|
||||
for (Status status : statuses)
|
||||
result.add(new Tweet(status, twitter.getId()));
|
||||
return result;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param dm Twitter4J direct message
|
||||
* @return dm item
|
||||
* @throws EngineException if Access is unavailable
|
||||
*/
|
||||
private Message getMessage(DirectMessage dm) throws EngineException {
|
||||
try {
|
||||
twitter4j.User receiver;
|
||||
twitter4j.User sender = twitter.showUser(dm.getSenderId());
|
||||
if (dm.getSenderId() != dm.getRecipientId())
|
||||
receiver = twitter.showUser(dm.getRecipientId());
|
||||
else
|
||||
receiver = sender;
|
||||
return new Message(dm, twitter.getId(), sender, receiver);
|
||||
} catch (Exception err) {
|
||||
throw new EngineException(err);
|
||||
}
|
||||
}
|
||||
}
|
@ -0,0 +1,82 @@
|
||||
package org.nuclearfog.twidda.backend.model;
|
||||
|
||||
import androidx.annotation.Nullable;
|
||||
|
||||
/**
|
||||
* container class for user login information
|
||||
*
|
||||
* @author nuclearfog
|
||||
*/
|
||||
public class Account {
|
||||
|
||||
/**
|
||||
* id of the user
|
||||
*/
|
||||
private final long userId;
|
||||
|
||||
/**
|
||||
* date of the first login
|
||||
*/
|
||||
private final long loginDate;
|
||||
|
||||
/**
|
||||
* access tokens of the login
|
||||
*/
|
||||
private final String key1, key2;
|
||||
|
||||
private User user;
|
||||
|
||||
|
||||
public Account(long userId, long loginDate, String key1, String key2) {
|
||||
this.userId = userId;
|
||||
this.loginDate = loginDate;
|
||||
this.key1 = key1;
|
||||
this.key2 = key2;
|
||||
}
|
||||
|
||||
/**
|
||||
* get ID of the user
|
||||
*
|
||||
* @return user ID
|
||||
*/
|
||||
public long getId() {
|
||||
return userId;
|
||||
}
|
||||
|
||||
/**
|
||||
* get date of creation
|
||||
*
|
||||
* @return date as long
|
||||
*/
|
||||
public long getLoginDate() {
|
||||
return loginDate;
|
||||
}
|
||||
|
||||
/**
|
||||
* get attached user information
|
||||
*
|
||||
* @return user
|
||||
*/
|
||||
@Nullable
|
||||
public User getUser() {
|
||||
return user;
|
||||
}
|
||||
|
||||
/**
|
||||
* attach user information
|
||||
*
|
||||
* @param user user
|
||||
*/
|
||||
public void attachUser(User user) {
|
||||
this.user = user;
|
||||
}
|
||||
|
||||
/**
|
||||
* get access tokens
|
||||
*
|
||||
* @return array with two access tokens
|
||||
*/
|
||||
public String[] getKeys() {
|
||||
return new String[]{key1, key2};
|
||||
}
|
||||
}
|
@ -25,9 +25,9 @@ public class Message {
|
||||
* @param sender sender user
|
||||
* @param receiver receiver user
|
||||
*/
|
||||
public Message(DirectMessage dm, long twitterId, twitter4j.User sender, twitter4j.User receiver) {
|
||||
this.sender = new User(sender, twitterId);
|
||||
this.receiver = new User(receiver, twitterId);
|
||||
public Message(DirectMessage dm, User sender, User receiver) {
|
||||
this.sender = sender;
|
||||
this.receiver = receiver;
|
||||
messageId = dm.getId();
|
||||
time = dm.getCreatedAt().getTime();
|
||||
setMessageText(dm);
|
||||
|
@ -176,7 +176,7 @@ public class User implements Serializable {
|
||||
}
|
||||
|
||||
/**
|
||||
* get Profile image_add link
|
||||
* get profile image link
|
||||
*
|
||||
* @return link
|
||||
*/
|
||||
@ -185,7 +185,7 @@ public class User implements Serializable {
|
||||
}
|
||||
|
||||
/**
|
||||
* get banner image_add link
|
||||
* get banner image link
|
||||
*
|
||||
* @return link
|
||||
*/
|
||||
|
@ -0,0 +1,140 @@
|
||||
package org.nuclearfog.twidda.database;
|
||||
|
||||
import android.content.ContentValues;
|
||||
import android.content.Context;
|
||||
import android.database.Cursor;
|
||||
import android.database.sqlite.SQLiteDatabase;
|
||||
|
||||
import org.nuclearfog.twidda.backend.model.Account;
|
||||
import org.nuclearfog.twidda.database.DatabaseAdapter.LoginTable;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
import static android.database.sqlite.SQLiteDatabase.CONFLICT_REPLACE;
|
||||
|
||||
/**
|
||||
* this database stores multi user logins
|
||||
*
|
||||
* @author nuclearfog
|
||||
*/
|
||||
public class AccountDatabase {
|
||||
|
||||
/**
|
||||
* projection of the columns with fixed order
|
||||
*/
|
||||
private static final String[] PROJECTION = {
|
||||
LoginTable.ID,
|
||||
LoginTable.KEY1,
|
||||
LoginTable.KEY2,
|
||||
LoginTable.DATE
|
||||
};
|
||||
|
||||
/**
|
||||
*
|
||||
*/
|
||||
private static final String ACCOUNT_SELECTION = LoginTable.ID + "=?";
|
||||
|
||||
/**
|
||||
* default sort order of the entries
|
||||
* sort by date of creation, starting with the latest entry
|
||||
*/
|
||||
private static final String SORT_BY_CREATION = LoginTable.DATE + " DESC";
|
||||
|
||||
/**
|
||||
* singleton instance
|
||||
*/
|
||||
private static final AccountDatabase INSTANCE = new AccountDatabase();
|
||||
|
||||
|
||||
private DatabaseAdapter dataHelper;
|
||||
|
||||
|
||||
private AccountDatabase() {
|
||||
}
|
||||
|
||||
/**
|
||||
* get singleton instance
|
||||
*
|
||||
* @return instance
|
||||
*/
|
||||
public static AccountDatabase getInstance(Context context) {
|
||||
if (INSTANCE.dataHelper == null)
|
||||
INSTANCE.dataHelper = DatabaseAdapter.getInstance(context.getApplicationContext());
|
||||
return INSTANCE;
|
||||
}
|
||||
|
||||
/**
|
||||
* register user login
|
||||
*
|
||||
* @param id User ID
|
||||
* @param key1 access token 1
|
||||
* @param key2 access token 2
|
||||
*/
|
||||
public void setLogin(long id, String key1, String key2) {
|
||||
ContentValues values = new ContentValues(4);
|
||||
|
||||
values.put(LoginTable.ID, id);
|
||||
values.put(LoginTable.KEY1, key1);
|
||||
values.put(LoginTable.KEY2, key2);
|
||||
values.put(LoginTable.DATE, System.currentTimeMillis());
|
||||
|
||||
SQLiteDatabase db = dataHelper.getDatabase();
|
||||
db.beginTransaction();
|
||||
db.insertWithOnConflict(LoginTable.NAME, "", values, CONFLICT_REPLACE);
|
||||
db.setTransactionSuccessful();
|
||||
db.endTransaction();
|
||||
}
|
||||
|
||||
/**
|
||||
* get all user logins
|
||||
*
|
||||
* @return list of all logins
|
||||
*/
|
||||
public List<Account> getLogins() {
|
||||
ArrayList<Account> result = new ArrayList<>();
|
||||
|
||||
SQLiteDatabase db = dataHelper.getDatabase();
|
||||
Cursor cursor = db.query(LoginTable.NAME, PROJECTION, null, null, null, null, SORT_BY_CREATION);
|
||||
if (cursor.moveToFirst()) {
|
||||
result.ensureCapacity(cursor.getCount());
|
||||
do {
|
||||
long id = cursor.getLong(0);
|
||||
String key1 = cursor.getString(1);
|
||||
String key2 = cursor.getString(2);
|
||||
long date = cursor.getLong(3);
|
||||
Account account = new Account(id, date, key1, key2);
|
||||
result.add(account);
|
||||
} while (cursor.moveToNext());
|
||||
}
|
||||
cursor.close();
|
||||
return result;
|
||||
}
|
||||
|
||||
/**
|
||||
* remove login information from storage
|
||||
*
|
||||
* @param id account ID to remove
|
||||
*/
|
||||
public void removeLogin(long id) {
|
||||
String[] args = {Long.toString(id)};
|
||||
|
||||
SQLiteDatabase db = dataHelper.getDatabase();
|
||||
db.delete(LoginTable.NAME, ACCOUNT_SELECTION, args);
|
||||
}
|
||||
|
||||
/**
|
||||
* check if user exists
|
||||
*
|
||||
* @param id User ID
|
||||
* @return true if user was found
|
||||
*/
|
||||
public boolean exists(long id) {
|
||||
String[] args = {Long.toString(id)};
|
||||
SQLiteDatabase db = dataHelper.getDatabase();
|
||||
Cursor cursor = db.query(LoginTable.NAME, null, ACCOUNT_SELECTION, args, null, null, null, "1");
|
||||
boolean found = cursor.moveToFirst();
|
||||
cursor.close();
|
||||
return found;
|
||||
}
|
||||
}
|
@ -19,22 +19,15 @@ import java.util.regex.Pattern;
|
||||
|
||||
import static android.database.sqlite.SQLiteDatabase.CONFLICT_IGNORE;
|
||||
import static android.database.sqlite.SQLiteDatabase.CONFLICT_REPLACE;
|
||||
import static org.nuclearfog.twidda.database.DatabaseAdapter.ANSWER_QUERY;
|
||||
import static org.nuclearfog.twidda.backend.model.Tweet.MediaType.GIF;
|
||||
import static org.nuclearfog.twidda.backend.model.Tweet.MediaType.IMAGE;
|
||||
import static org.nuclearfog.twidda.backend.model.Tweet.MediaType.VIDEO;
|
||||
import static org.nuclearfog.twidda.database.DatabaseAdapter.FavoriteTable;
|
||||
import static org.nuclearfog.twidda.database.DatabaseAdapter.HOME_QUERY;
|
||||
import static org.nuclearfog.twidda.database.DatabaseAdapter.MENTION_QUERY;
|
||||
import static org.nuclearfog.twidda.database.DatabaseAdapter.MESSAGE_QUERY;
|
||||
import static org.nuclearfog.twidda.database.DatabaseAdapter.MessageTable;
|
||||
import static org.nuclearfog.twidda.database.DatabaseAdapter.SINGLE_TWEET_QUERY;
|
||||
import static org.nuclearfog.twidda.database.DatabaseAdapter.STATUS_EXIST_QUERY;
|
||||
import static org.nuclearfog.twidda.database.DatabaseAdapter.TREND_QUERY;
|
||||
import static org.nuclearfog.twidda.database.DatabaseAdapter.TWEETFLAG_QUERY;
|
||||
import static org.nuclearfog.twidda.database.DatabaseAdapter.TrendTable;
|
||||
import static org.nuclearfog.twidda.database.DatabaseAdapter.TweetRegisterTable;
|
||||
import static org.nuclearfog.twidda.database.DatabaseAdapter.TweetTable;
|
||||
import static org.nuclearfog.twidda.database.DatabaseAdapter.USERFAVORIT_QUERY;
|
||||
import static org.nuclearfog.twidda.database.DatabaseAdapter.USERFLAG_QUERY;
|
||||
import static org.nuclearfog.twidda.database.DatabaseAdapter.USERTWEET_QUERY;
|
||||
import static org.nuclearfog.twidda.database.DatabaseAdapter.USER_QUERY;
|
||||
import static org.nuclearfog.twidda.database.DatabaseAdapter.UserRegisterTable;
|
||||
import static org.nuclearfog.twidda.database.DatabaseAdapter.UserTable;
|
||||
|
||||
/**
|
||||
@ -45,27 +38,100 @@ import static org.nuclearfog.twidda.database.DatabaseAdapter.UserTable;
|
||||
*/
|
||||
public class AppDatabase {
|
||||
|
||||
// Tweet flags
|
||||
// Tweet status bits
|
||||
private static final int FAV_MASK = 1; // tweet is favored by user
|
||||
private static final int RTW_MASK = 1 << 1; // tweet is retweeted by user
|
||||
private static final int HOM_MASK = 1 << 2; // tweet is from home timeline
|
||||
private static final int MEN_MASK = 1 << 3; // tweet is from mention timeline
|
||||
private static final int UTW_MASK = 1 << 4; // tweet is from an users timeline
|
||||
private static final int RPL_MASK = 1 << 5; // tweet is from a reply timeline
|
||||
|
||||
// Media content flags
|
||||
private static final int MEDIA_IMAGE_MASK = 1 << 6; // tweet contains images
|
||||
private static final int MEDIA_VIDEO_MASK = 2 << 6; // tweet contains a video
|
||||
private static final int MEDIA_ANGIF_MASK = 3 << 6; // tweet contains an animation
|
||||
private static final int MEDIA_SENS_MASK = 1 << 8; // tweet contains sensitive media
|
||||
|
||||
// user flags
|
||||
// user status bits
|
||||
private static final int VER_MASK = 1; // user is verified
|
||||
private static final int LCK_MASK = 1 << 1; // user is private
|
||||
private static final int FRQ_MASK = 1 << 2; // a follow request is pending
|
||||
private static final int EXCL_USR = 1 << 3; // user excluded from mention timeline
|
||||
private static final int DEF_IMG = 1 << 4; // user has a default profile image
|
||||
|
||||
/**
|
||||
* query to create tweet table with user and register columns
|
||||
*/
|
||||
private static final String TWEET_TABLE = TweetTable.NAME
|
||||
+ " INNER JOIN " + UserTable.NAME
|
||||
+ " ON " + TweetTable.NAME + "." + TweetTable.USER + "=" + UserTable.NAME + "." + UserTable.ID
|
||||
+ " INNER JOIN " + UserRegisterTable.NAME
|
||||
+ " ON " + TweetTable.NAME + "." + TweetTable.USER + "=" + UserRegisterTable.NAME + "." + UserRegisterTable.ID
|
||||
+ " INNER JOIN " + TweetRegisterTable.NAME
|
||||
+ " ON " + TweetTable.NAME + "." + TweetTable.ID + "=" + TweetRegisterTable.NAME + "." + TweetRegisterTable.ID;
|
||||
|
||||
/**
|
||||
* query to get user information
|
||||
*/
|
||||
private static final String USER_TABLE = "SELECT * FROM " + UserTable.NAME
|
||||
+ " INNER JOIN " + UserRegisterTable.NAME
|
||||
+ " ON " + UserTable.NAME + "." + UserTable.ID + "=" + UserRegisterTable.NAME + "." + UserRegisterTable.ID
|
||||
+ " WHERE " + UserTable.NAME + "." + UserTable.ID + "=? LIMIT 1";
|
||||
|
||||
/**
|
||||
* SQL query to get home timeline tweets
|
||||
*/
|
||||
static final String HOME_QUERY = "SELECT * FROM " + TWEET_TABLE
|
||||
+ " WHERE " + TweetRegisterTable.NAME + "." + TweetRegisterTable.REGISTER + "&" + HOM_MASK + " IS NOT 0"
|
||||
+ " AND " + TweetRegisterTable.NAME + "." + TweetRegisterTable.OWNER + "=?"
|
||||
+ " ORDER BY " + TweetTable.ID
|
||||
+ " DESC LIMIT ?";
|
||||
|
||||
/**
|
||||
* SQL query to get mention timeline
|
||||
*/
|
||||
static final String MENTION_QUERY = "SELECT * FROM " + TWEET_TABLE
|
||||
+ " WHERE " + TweetRegisterTable.NAME + "." + TweetRegisterTable.REGISTER + "&" + MEN_MASK + " IS NOT 0"
|
||||
+ " AND " + UserRegisterTable.NAME + "." + UserRegisterTable.REGISTER + "&" + EXCL_USR + " IS 0"
|
||||
+ " AND " + TweetRegisterTable.NAME + "." + TweetRegisterTable.OWNER + "=?"
|
||||
+ " ORDER BY " + TweetTable.ID
|
||||
+ " DESC LIMIT ?";
|
||||
|
||||
/**
|
||||
* SQL query to get tweets of an user
|
||||
*/
|
||||
static final String USERTWEET_QUERY = "SELECT * FROM " + TWEET_TABLE
|
||||
+ " WHERE " + TweetRegisterTable.NAME + "." + TweetRegisterTable.REGISTER + "&" + UTW_MASK + " IS NOT 0"
|
||||
+ " AND " + TweetRegisterTable.NAME + "." + TweetRegisterTable.OWNER + "=?"
|
||||
+ " AND " + TweetTable.NAME + "." + TweetTable.USER + "=?"
|
||||
+ " ORDER BY " + TweetTable.ID
|
||||
+ " DESC LIMIT ?";
|
||||
|
||||
/**
|
||||
* SQL query to get tweets favored by an user
|
||||
*/
|
||||
static final String USERFAVORIT_QUERY = "SELECT * FROM " + TWEET_TABLE
|
||||
+ " INNER JOIN " + FavoriteTable.NAME
|
||||
+ " ON " + TweetTable.NAME + "." + TweetTable.ID + "=" + FavoriteTable.NAME + "." + FavoriteTable.TWEETID
|
||||
+ " WHERE " + FavoriteTable.NAME + "." + FavoriteTable.FAVORITEDBY + "=?"
|
||||
+ " AND " + TweetRegisterTable.NAME + "." + TweetRegisterTable.OWNER + "=?"
|
||||
+ " ORDER BY " + TweetTable.ID
|
||||
+ " DESC LIMIT ?";
|
||||
|
||||
/**
|
||||
* SQL query to get a single tweet specified by an ID
|
||||
*/
|
||||
static final String SINGLE_TWEET_QUERY = "SELECT * FROM " + TWEET_TABLE
|
||||
+ " WHERE " + TweetTable.NAME + "." + TweetTable.ID + "=? LIMIT 1";
|
||||
|
||||
/**
|
||||
* SQL query to get replies of a tweet specified by a reply ID
|
||||
*/
|
||||
static final String ANSWER_QUERY = "SELECT * FROM " + TWEET_TABLE
|
||||
+ " WHERE " + TweetTable.NAME + "." + TweetTable.REPLYTWEET + "=?"
|
||||
+ " AND " + TweetRegisterTable.NAME + "." + TweetRegisterTable.OWNER + "=?"
|
||||
+ " AND " + TweetRegisterTable.NAME + "." + TweetRegisterTable.REGISTER + "&" + RPL_MASK + " IS NOT 0"
|
||||
+ " AND " + UserRegisterTable.NAME + "." + UserRegisterTable.REGISTER + "&" + EXCL_USR + " IS 0"
|
||||
+ " ORDER BY " + TweetTable.ID + " DESC LIMIT ?";
|
||||
|
||||
/**
|
||||
* select tweet entries from favorite table matching tweet ID
|
||||
* this tweet can be favored by multiple users
|
||||
@ -95,12 +161,37 @@ public class AppDatabase {
|
||||
/**
|
||||
* select tweet from tweet table matching tweet ID
|
||||
*/
|
||||
private static final String TWEET_SELECT = TweetTable.TABLE + "." + TweetTable.ID + "=?";
|
||||
private static final String TWEET_SELECT = TweetTable.NAME + "." + TweetTable.ID + "=?";
|
||||
|
||||
/**
|
||||
* select user from user table matching user ID
|
||||
*/
|
||||
private static final String USER_SELECT = UserTable.TABLE + "." + UserTable.ID + "=?";
|
||||
private static final String USER_SELECT = UserTable.NAME + "." + UserTable.ID + "=?";
|
||||
|
||||
/**
|
||||
* selection to get tweet register
|
||||
*/
|
||||
private static final String TWEET_REG_SELECT = TweetRegisterTable.ID + "=? AND " + TweetRegisterTable.OWNER + "=?";
|
||||
|
||||
/**
|
||||
* selection to get user register
|
||||
*/
|
||||
private static final String USER_REG_SELECT = UserRegisterTable.ID + "=? AND " + UserRegisterTable.OWNER + "=?";
|
||||
|
||||
/**
|
||||
* default message order by date
|
||||
*/
|
||||
private static final String MESSAGE_ORDER = MessageTable.SINCE + " DESC";
|
||||
|
||||
/**
|
||||
* default order for trend rows
|
||||
*/
|
||||
private static final String TREND_ORDER = TrendTable.INDEX + " ASC";
|
||||
|
||||
/**
|
||||
* limit for accessing a single row
|
||||
*/
|
||||
private static final String SINGLE_ITEM = "1";
|
||||
|
||||
/**
|
||||
* limit of database entries
|
||||
@ -112,13 +203,16 @@ public class AppDatabase {
|
||||
*/
|
||||
private final long homeId;
|
||||
|
||||
private DatabaseAdapter dataHelper;
|
||||
/**
|
||||
* adapter for the database backend
|
||||
*/
|
||||
private DatabaseAdapter adapter;
|
||||
|
||||
/**
|
||||
* initialize database
|
||||
*/
|
||||
public AppDatabase(Context context) {
|
||||
dataHelper = DatabaseAdapter.getInstance(context);
|
||||
adapter = DatabaseAdapter.getInstance(context);
|
||||
GlobalSettings settings = GlobalSettings.getInstance(context);
|
||||
homeId = settings.getCurrentUserId();
|
||||
limit = settings.getListSize();
|
||||
@ -208,14 +302,14 @@ public class AppDatabase {
|
||||
public void storeTrends(List<Trend> trends, int woeId) {
|
||||
String[] args = {Integer.toString(woeId)};
|
||||
SQLiteDatabase db = getDbWrite();
|
||||
db.delete(TrendTable.TABLE, TREND_SELECT, args);
|
||||
db.delete(TrendTable.NAME, TREND_SELECT, args);
|
||||
for (Trend trend : trends) {
|
||||
ContentValues trendColumn = new ContentValues(4);
|
||||
trendColumn.put(TrendTable.ID, woeId);
|
||||
trendColumn.put(TrendTable.VOL, trend.getRange());
|
||||
trendColumn.put(TrendTable.TREND, trend.getName());
|
||||
trendColumn.put(TrendTable.INDEX, trend.getRank());
|
||||
db.insert(TrendTable.TABLE, null, trendColumn);
|
||||
db.insert(TrendTable.NAME, null, trendColumn);
|
||||
}
|
||||
commit(db);
|
||||
}
|
||||
@ -252,7 +346,7 @@ public class AppDatabase {
|
||||
* @return tweet list
|
||||
*/
|
||||
public List<Tweet> getHomeTimeline() {
|
||||
String[] args = {Integer.toString(HOM_MASK), Integer.toString(limit)};
|
||||
String[] args = {Long.toString(homeId), Integer.toString(limit)};
|
||||
|
||||
SQLiteDatabase db = getDbRead();
|
||||
List<Tweet> tweetList = new LinkedList<>();
|
||||
@ -273,7 +367,9 @@ public class AppDatabase {
|
||||
* @return tweet list
|
||||
*/
|
||||
public List<Tweet> getMentions() {
|
||||
String[] args = {Integer.toString(MEN_MASK), Integer.toString(EXCL_USR), Integer.toString(limit)};
|
||||
String[] args = {
|
||||
Long.toString(homeId), Integer.toString(limit)
|
||||
};
|
||||
|
||||
SQLiteDatabase db = getDbRead();
|
||||
List<Tweet> tweetList = new LinkedList<>();
|
||||
@ -295,7 +391,10 @@ public class AppDatabase {
|
||||
* @return Tweet list of user tweets
|
||||
*/
|
||||
public List<Tweet> getUserTweets(long userID) {
|
||||
String[] args = {Integer.toString(UTW_MASK), Long.toString(userID), Integer.toString(limit)};
|
||||
String[] args = {
|
||||
Long.toString(homeId), Long.toString(userID),
|
||||
Integer.toString(limit)
|
||||
};
|
||||
|
||||
SQLiteDatabase db = getDbRead();
|
||||
List<Tweet> tweetList = new LinkedList<>();
|
||||
@ -317,7 +416,10 @@ public class AppDatabase {
|
||||
* @return favored tweets by user
|
||||
*/
|
||||
public List<Tweet> getUserFavorites(long ownerID) {
|
||||
String[] args = {Long.toString(ownerID), Integer.toString(limit)};
|
||||
String[] args = {
|
||||
Long.toString(ownerID), Long.toString(homeId),
|
||||
Integer.toString(limit)
|
||||
};
|
||||
|
||||
SQLiteDatabase db = getDbRead();
|
||||
List<Tweet> tweetList = new LinkedList<>();
|
||||
@ -370,8 +472,10 @@ public class AppDatabase {
|
||||
* @return list of tweet answers
|
||||
*/
|
||||
public List<Tweet> getAnswers(long tweetId) {
|
||||
String[] args = {Long.toString(tweetId), Integer.toString(RPL_MASK),
|
||||
Integer.toString(EXCL_USR), Integer.toString(limit)};
|
||||
String[] args = {
|
||||
Long.toString(tweetId), Long.toString(homeId),
|
||||
Integer.toString(limit)
|
||||
};
|
||||
|
||||
SQLiteDatabase db = getDbRead();
|
||||
List<Tweet> tweetList = new LinkedList<>();
|
||||
@ -408,8 +512,8 @@ public class AppDatabase {
|
||||
String[] args = {Long.toString(tweetId)};
|
||||
|
||||
SQLiteDatabase db = getDbWrite();
|
||||
db.delete(TweetTable.TABLE, TWEET_SELECT, args);
|
||||
db.delete(FavoriteTable.TABLE, FAVORITE_SELECT_TWEET, args);
|
||||
db.delete(TweetTable.NAME, TWEET_SELECT, args);
|
||||
db.delete(FavoriteTable.NAME, FAVORITE_SELECT_TWEET, args);
|
||||
commit(db);
|
||||
}
|
||||
|
||||
@ -423,15 +527,16 @@ public class AppDatabase {
|
||||
if (tweet.getEmbeddedTweet() != null)
|
||||
tweetId = tweet.getEmbeddedTweet().getId();
|
||||
String[] delArgs = {Long.toString(tweetId), Long.toString(homeId)};
|
||||
String[] updateArgs = {Long.toString(tweetId)};
|
||||
String[] updateArgs = {Long.toString(tweetId), Long.toString(homeId)};
|
||||
|
||||
SQLiteDatabase db = getDbWrite();
|
||||
int flags = getTweetFlags(db, tweetId);
|
||||
flags &= ~FAV_MASK;
|
||||
// get tweet register
|
||||
ContentValues status = new ContentValues(1);
|
||||
status.put(TweetTable.REGISTER, flags);
|
||||
db.delete(FavoriteTable.TABLE, FAVORITE_SELECT, delArgs);
|
||||
db.update(TweetTable.TABLE, status, TWEET_SELECT, updateArgs);
|
||||
int flags = getTweetFlags(db, tweetId) & ~FAV_MASK; // unset favorite flag
|
||||
status.put(TweetRegisterTable.REGISTER, flags);
|
||||
// update database
|
||||
db.update(TweetRegisterTable.NAME, status, TWEET_REG_SELECT, updateArgs);
|
||||
db.delete(FavoriteTable.NAME, FAVORITE_SELECT, delArgs);
|
||||
commit(db);
|
||||
}
|
||||
|
||||
@ -458,7 +563,7 @@ public class AppDatabase {
|
||||
String[] args = {Integer.toString(woeId)};
|
||||
|
||||
SQLiteDatabase db = getDbRead();
|
||||
Cursor cursor = db.rawQuery(TREND_QUERY, args);
|
||||
Cursor cursor = db.query(TrendTable.NAME, null, TREND_SELECT, args, null, null, TREND_ORDER);
|
||||
|
||||
List<Trend> trends = new LinkedList<>();
|
||||
if (cursor.moveToFirst()) {
|
||||
@ -484,11 +589,11 @@ public class AppDatabase {
|
||||
* @return list of direct messages
|
||||
*/
|
||||
public MessageList getMessages() {
|
||||
String[] args = {Integer.toString(limit)};
|
||||
String count = Integer.toString(limit);
|
||||
// TODO get next cursor from database
|
||||
MessageList result = new MessageList(null, null);
|
||||
SQLiteDatabase db = getDbRead();
|
||||
Cursor cursor = db.rawQuery(MESSAGE_QUERY, args);
|
||||
Cursor cursor = db.query(MessageTable.TABLE, null, MESSAGE_SELECT, null, null, null, MESSAGE_ORDER, count);
|
||||
if (cursor.moveToFirst()) {
|
||||
// get indexes
|
||||
int idxSender = cursor.getColumnIndexOrThrow(MessageTable.SENDER);
|
||||
@ -531,18 +636,18 @@ public class AppDatabase {
|
||||
* @param mute true remove user tweets from mention results
|
||||
*/
|
||||
public void muteUser(long id, boolean mute) {
|
||||
String[] args = {Long.toString(id)};
|
||||
String[] args = {Long.toString(id), Long.toString(homeId)};
|
||||
|
||||
SQLiteDatabase db = getDbWrite();
|
||||
int flags = getUserFlags(db, id);
|
||||
if (mute)
|
||||
if (mute) {
|
||||
flags |= EXCL_USR;
|
||||
else
|
||||
} else {
|
||||
flags &= ~EXCL_USR;
|
||||
|
||||
ContentValues userColumn = new ContentValues(1);
|
||||
userColumn.put(UserTable.REGISTER, flags);
|
||||
db.update(UserTable.TABLE, userColumn, USER_SELECT, args);
|
||||
}
|
||||
ContentValues registerColumn = new ContentValues(1);
|
||||
registerColumn.put(UserRegisterTable.REGISTER, flags);
|
||||
db.update(UserRegisterTable.NAME, registerColumn, USER_REG_SELECT, args);
|
||||
commit(db);
|
||||
}
|
||||
|
||||
@ -554,37 +659,37 @@ public class AppDatabase {
|
||||
*/
|
||||
private Tweet getStatus(Cursor cursor) {
|
||||
long time = cursor.getLong(cursor.getColumnIndexOrThrow(TweetTable.SINCE));
|
||||
String tweettext = cursor.getString(cursor.getColumnIndexOrThrow(TweetTable.TWEET));
|
||||
String text = cursor.getString(cursor.getColumnIndexOrThrow(TweetTable.TWEET));
|
||||
int retweet = cursor.getInt(cursor.getColumnIndexOrThrow(TweetTable.RETWEET));
|
||||
int favorit = cursor.getInt(cursor.getColumnIndexOrThrow(TweetTable.FAVORITE));
|
||||
int favorite = cursor.getInt(cursor.getColumnIndexOrThrow(TweetTable.FAVORITE));
|
||||
long tweetId = cursor.getLong(cursor.getColumnIndexOrThrow(TweetTable.ID));
|
||||
long retweetId = cursor.getLong(cursor.getColumnIndexOrThrow(TweetTable.RETWEETID));
|
||||
String replyname = cursor.getString(cursor.getColumnIndexOrThrow(TweetTable.REPLYNAME));
|
||||
String replyName = cursor.getString(cursor.getColumnIndexOrThrow(TweetTable.REPLYNAME));
|
||||
long replyStatusId = cursor.getLong(cursor.getColumnIndexOrThrow(TweetTable.REPLYTWEET));
|
||||
long retweeterId = cursor.getLong(cursor.getColumnIndexOrThrow(TweetTable.RETWEETUSER));
|
||||
String source = cursor.getString(cursor.getColumnIndexOrThrow(TweetTable.SOURCE));
|
||||
String medialinks = cursor.getString(cursor.getColumnIndexOrThrow(TweetTable.MEDIA));
|
||||
String links = cursor.getString(cursor.getColumnIndexOrThrow(TweetTable.MEDIA));
|
||||
String place = cursor.getString(cursor.getColumnIndexOrThrow(TweetTable.PLACE));
|
||||
String geo = cursor.getString(cursor.getColumnIndexOrThrow(TweetTable.COORDINATE));
|
||||
long replyUserId = cursor.getLong(cursor.getColumnIndexOrThrow(TweetTable.REPLYUSER));
|
||||
int statusregister = cursor.getInt(cursor.getColumnIndexOrThrow(TweetTable.REGISTER));
|
||||
boolean favorited = (statusregister & FAV_MASK) != 0;
|
||||
boolean retweeted = (statusregister & RTW_MASK) != 0;
|
||||
boolean sensitive = (statusregister & MEDIA_SENS_MASK) != 0;
|
||||
String[] medias = parseMedia(medialinks);
|
||||
int tweetRegister = cursor.getInt(cursor.getColumnIndexOrThrow(TweetRegisterTable.REGISTER));
|
||||
boolean favorited = (tweetRegister & FAV_MASK) != 0;
|
||||
boolean retweeted = (tweetRegister & RTW_MASK) != 0;
|
||||
boolean sensitive = (tweetRegister & MEDIA_SENS_MASK) != 0;
|
||||
String[] medias = parseMedia(links);
|
||||
// get media type
|
||||
Tweet.MediaType mediaType = Tweet.MediaType.NONE;
|
||||
if ((statusregister & MEDIA_ANGIF_MASK) == MEDIA_ANGIF_MASK)
|
||||
mediaType = Tweet.MediaType.GIF;
|
||||
else if ((statusregister & MEDIA_IMAGE_MASK) == MEDIA_IMAGE_MASK)
|
||||
mediaType = Tweet.MediaType.IMAGE;
|
||||
else if ((statusregister & MEDIA_VIDEO_MASK) == MEDIA_VIDEO_MASK)
|
||||
if ((tweetRegister & MEDIA_ANGIF_MASK) == MEDIA_ANGIF_MASK)
|
||||
mediaType = GIF;
|
||||
else if ((tweetRegister & MEDIA_IMAGE_MASK) == MEDIA_IMAGE_MASK)
|
||||
mediaType = IMAGE;
|
||||
else if ((tweetRegister & MEDIA_VIDEO_MASK) == MEDIA_VIDEO_MASK)
|
||||
mediaType = Tweet.MediaType.VIDEO;
|
||||
User user = getUser(cursor);
|
||||
Tweet embeddedTweet = null;
|
||||
if (retweetId > 1)
|
||||
embeddedTweet = getStatus(retweetId);
|
||||
return new Tweet(tweetId, retweet, favorit, user, tweettext, time, replyname, replyUserId, medias,
|
||||
return new Tweet(tweetId, retweet, favorite, user, text, time, replyName, replyUserId, medias,
|
||||
mediaType, source, replyStatusId, embeddedTweet, retweeterId, retweeted, favorited, sensitive, place, geo);
|
||||
}
|
||||
|
||||
@ -598,7 +703,8 @@ public class AppDatabase {
|
||||
@Nullable
|
||||
private User getUser(long userId, SQLiteDatabase db) {
|
||||
String[] args = {Long.toString(userId)};
|
||||
Cursor cursor = db.rawQuery(USER_QUERY, args);
|
||||
|
||||
Cursor cursor = db.rawQuery(USER_TABLE, args);
|
||||
|
||||
User user = null;
|
||||
if (cursor.moveToFirst())
|
||||
@ -616,8 +722,7 @@ public class AppDatabase {
|
||||
private User getUser(Cursor cursor) {
|
||||
long userId = cursor.getLong(cursor.getColumnIndexOrThrow(UserTable.ID));
|
||||
String username = cursor.getString(cursor.getColumnIndexOrThrow(UserTable.USERNAME));
|
||||
String screenname = cursor.getString(cursor.getColumnIndexOrThrow(UserTable.SCREENNAME));
|
||||
int userRegister = cursor.getInt(cursor.getColumnIndexOrThrow(UserTable.REGISTER));
|
||||
String screenName = cursor.getString(cursor.getColumnIndexOrThrow(UserTable.SCREENNAME));
|
||||
String profileImg = cursor.getString(cursor.getColumnIndexOrThrow(UserTable.IMAGE));
|
||||
String bio = cursor.getString(cursor.getColumnIndexOrThrow(UserTable.DESCRIPTION));
|
||||
String link = cursor.getString(cursor.getColumnIndexOrThrow(UserTable.LINK));
|
||||
@ -628,12 +733,13 @@ public class AppDatabase {
|
||||
int follower = cursor.getInt(cursor.getColumnIndexOrThrow(UserTable.FOLLOWER));
|
||||
int tCount = cursor.getInt(cursor.getColumnIndexOrThrow(UserTable.TWEETS));
|
||||
int fCount = cursor.getInt(cursor.getColumnIndexOrThrow(UserTable.FAVORS));
|
||||
int userRegister = cursor.getInt(cursor.getColumnIndexOrThrow(UserRegisterTable.REGISTER));
|
||||
boolean isCurrentUser = homeId == userId;
|
||||
boolean isVerified = (userRegister & VER_MASK) != 0;
|
||||
boolean isLocked = (userRegister & LCK_MASK) != 0;
|
||||
boolean isReq = (userRegister & FRQ_MASK) != 0;
|
||||
boolean defaultImg = (userRegister & DEF_IMG) != 0;
|
||||
return new User(userId, username, screenname, profileImg, bio, location, isCurrentUser, isVerified,
|
||||
return new User(userId, username, screenName, profileImg, bio, location, isCurrentUser, isVerified,
|
||||
isLocked, isReq, defaultImg, link, banner, createdAt, following, follower, tCount, fCount);
|
||||
}
|
||||
|
||||
@ -645,7 +751,8 @@ public class AppDatabase {
|
||||
* @param mode SQLITE mode {@link SQLiteDatabase#CONFLICT_IGNORE} or {@link SQLiteDatabase#CONFLICT_REPLACE}
|
||||
*/
|
||||
private void storeUser(User user, SQLiteDatabase db, int mode) {
|
||||
ContentValues userColumn = new ContentValues(14);
|
||||
ContentValues userRegister = new ContentValues(3);
|
||||
ContentValues userColumn = new ContentValues(13);
|
||||
int flags = getUserFlags(db, user.getId());
|
||||
if (user.isVerified())
|
||||
flags |= VER_MASK;
|
||||
@ -668,7 +775,6 @@ public class AppDatabase {
|
||||
userColumn.put(UserTable.USERNAME, user.getUsername());
|
||||
userColumn.put(UserTable.SCREENNAME, user.getScreenname());
|
||||
userColumn.put(UserTable.IMAGE, user.getImageLink());
|
||||
userColumn.put(UserTable.REGISTER, flags);
|
||||
userColumn.put(UserTable.DESCRIPTION, user.getBio());
|
||||
userColumn.put(UserTable.LINK, user.getLink());
|
||||
userColumn.put(UserTable.LOCATION, user.getLocation());
|
||||
@ -679,7 +785,12 @@ public class AppDatabase {
|
||||
userColumn.put(UserTable.TWEETS, user.getTweetCount());
|
||||
userColumn.put(UserTable.FAVORS, user.getFavorCount());
|
||||
|
||||
db.insertWithOnConflict(UserTable.TABLE, null, userColumn, mode);
|
||||
userRegister.put(UserRegisterTable.ID, user.getId());
|
||||
userRegister.put(UserRegisterTable.OWNER, homeId);
|
||||
userRegister.put(UserRegisterTable.REGISTER, flags);
|
||||
|
||||
db.insertWithOnConflict(UserTable.NAME, null, userColumn, mode);
|
||||
db.insertWithOnConflict(UserRegisterTable.NAME, null, userRegister, mode);
|
||||
}
|
||||
|
||||
|
||||
@ -691,11 +802,11 @@ public class AppDatabase {
|
||||
* @param db SQLite database
|
||||
*/
|
||||
private void storeStatus(Tweet tweet, int statusRegister, SQLiteDatabase db) {
|
||||
ContentValues status = new ContentValues(17);
|
||||
ContentValues register = new ContentValues(3);
|
||||
ContentValues status = new ContentValues(16);
|
||||
User user = tweet.getUser();
|
||||
Tweet rtStat = tweet.getEmbeddedTweet();
|
||||
long rtId = -1L;
|
||||
|
||||
if (rtStat != null) {
|
||||
storeStatus(rtStat, 0, db);
|
||||
rtId = rtStat.getId();
|
||||
@ -716,21 +827,14 @@ public class AppDatabase {
|
||||
} else {
|
||||
statusRegister &= ~MEDIA_SENS_MASK;
|
||||
}
|
||||
switch (tweet.getMediaType()) {
|
||||
case IMAGE:
|
||||
statusRegister |= MEDIA_IMAGE_MASK;
|
||||
break;
|
||||
|
||||
case VIDEO:
|
||||
statusRegister |= MEDIA_VIDEO_MASK;
|
||||
break;
|
||||
|
||||
case GIF:
|
||||
statusRegister |= MEDIA_ANGIF_MASK;
|
||||
break;
|
||||
if (tweet.getMediaType() == IMAGE) {
|
||||
statusRegister |= MEDIA_IMAGE_MASK;
|
||||
} else if (tweet.getMediaType() == VIDEO) {
|
||||
statusRegister |= MEDIA_VIDEO_MASK;
|
||||
} else if (tweet.getMediaType() == GIF) {
|
||||
statusRegister |= MEDIA_ANGIF_MASK;
|
||||
}
|
||||
status.put(TweetTable.MEDIA, getMediaLinks(tweet));
|
||||
status.put(TweetTable.REGISTER, statusRegister);
|
||||
status.put(TweetTable.ID, tweet.getId());
|
||||
status.put(TweetTable.USER, user.getId());
|
||||
status.put(TweetTable.SINCE, tweet.getTime());
|
||||
@ -746,8 +850,14 @@ public class AppDatabase {
|
||||
status.put(TweetTable.COORDINATE, tweet.getLocationCoordinates());
|
||||
status.put(TweetTable.REPLYUSER, tweet.getReplyUserId());
|
||||
status.put(TweetTable.REPLYNAME, tweet.getReplyName());
|
||||
|
||||
register.put(TweetRegisterTable.ID, tweet.getId());
|
||||
register.put(TweetRegisterTable.OWNER, homeId);
|
||||
register.put(TweetRegisterTable.REGISTER, statusRegister);
|
||||
|
||||
storeUser(user, db, CONFLICT_IGNORE);
|
||||
db.insertWithOnConflict(TweetTable.TABLE, null, status, CONFLICT_REPLACE);
|
||||
db.insertWithOnConflict(TweetTable.NAME, null, status, CONFLICT_REPLACE);
|
||||
db.insertWithOnConflict(TweetRegisterTable.NAME, null, register, CONFLICT_REPLACE);
|
||||
}
|
||||
|
||||
/**
|
||||
@ -758,26 +868,31 @@ public class AppDatabase {
|
||||
*/
|
||||
private void updateStatus(Tweet tweet, SQLiteDatabase db) {
|
||||
String[] tweetIdArg = {Long.toString(tweet.getId())};
|
||||
String[] tweetRegArg = {Long.toString(tweet.getId()), Long.toString(homeId)};
|
||||
String[] userIdArg = {Long.toString(tweet.getUser().getId())};
|
||||
|
||||
ContentValues statColumn = new ContentValues(7);
|
||||
ContentValues tweetColumn = new ContentValues(6);
|
||||
ContentValues tweetRegColumn = new ContentValues(3);
|
||||
ContentValues userColumn = new ContentValues(9);
|
||||
int flags = getTweetFlags(db, tweet.getId());
|
||||
int register = getTweetFlags(db, tweet.getId());
|
||||
if (tweet.retweeted())
|
||||
flags |= RTW_MASK;
|
||||
register |= RTW_MASK;
|
||||
else
|
||||
flags &= ~RTW_MASK;
|
||||
register &= ~RTW_MASK;
|
||||
if (tweet.favored())
|
||||
flags |= FAV_MASK;
|
||||
register |= FAV_MASK;
|
||||
else
|
||||
flags &= ~FAV_MASK;
|
||||
statColumn.put(TweetTable.TWEET, tweet.getTweet());
|
||||
statColumn.put(TweetTable.RETWEET, tweet.getRetweetCount());
|
||||
statColumn.put(TweetTable.FAVORITE, tweet.getFavoriteCount());
|
||||
statColumn.put(TweetTable.RETWEETUSER, tweet.getMyRetweetId());
|
||||
statColumn.put(TweetTable.REPLYNAME, tweet.getReplyName());
|
||||
statColumn.put(TweetTable.REGISTER, flags);
|
||||
statColumn.put(TweetTable.MEDIA, getMediaLinks(tweet));
|
||||
register &= ~FAV_MASK;
|
||||
tweetColumn.put(TweetTable.TWEET, tweet.getTweet());
|
||||
tweetColumn.put(TweetTable.RETWEET, tweet.getRetweetCount());
|
||||
tweetColumn.put(TweetTable.FAVORITE, tweet.getFavoriteCount());
|
||||
tweetColumn.put(TweetTable.RETWEETUSER, tweet.getMyRetweetId());
|
||||
tweetColumn.put(TweetTable.REPLYNAME, tweet.getReplyName());
|
||||
tweetColumn.put(TweetTable.MEDIA, getMediaLinks(tweet));
|
||||
|
||||
tweetRegColumn.put(TweetRegisterTable.ID, tweet.getId());
|
||||
tweetRegColumn.put(TweetRegisterTable.OWNER, homeId);
|
||||
tweetRegColumn.put(TweetRegisterTable.REGISTER, register);
|
||||
|
||||
User user = tweet.getUser();
|
||||
userColumn.put(UserTable.USERNAME, user.getUsername());
|
||||
@ -790,8 +905,9 @@ public class AppDatabase {
|
||||
userColumn.put(UserTable.FRIENDS, user.getFollowing());
|
||||
userColumn.put(UserTable.FOLLOWER, user.getFollower());
|
||||
|
||||
db.update(TweetTable.TABLE, statColumn, TWEET_SELECT, tweetIdArg);
|
||||
db.update(UserTable.TABLE, userColumn, USER_SELECT, userIdArg);
|
||||
db.update(TweetTable.NAME, tweetColumn, TWEET_SELECT, tweetIdArg);
|
||||
db.update(TweetRegisterTable.NAME, tweetRegColumn, TWEET_REG_SELECT, tweetRegArg);
|
||||
db.update(UserTable.NAME, userColumn, USER_SELECT, userIdArg);
|
||||
}
|
||||
|
||||
/**
|
||||
@ -805,7 +921,7 @@ public class AppDatabase {
|
||||
ContentValues favTable = new ContentValues(2);
|
||||
favTable.put(FavoriteTable.TWEETID, tweetId);
|
||||
favTable.put(FavoriteTable.FAVORITEDBY, ownerId);
|
||||
db.insertWithOnConflict(FavoriteTable.TABLE, null, favTable, CONFLICT_REPLACE);
|
||||
db.insertWithOnConflict(FavoriteTable.NAME, null, favTable, CONFLICT_REPLACE);
|
||||
}
|
||||
|
||||
/**
|
||||
@ -816,7 +932,7 @@ public class AppDatabase {
|
||||
*/
|
||||
private void removeOldFavorites(SQLiteDatabase db, long userId) {
|
||||
String[] delArgs = {Long.toString(userId)};
|
||||
db.delete(FavoriteTable.TABLE, FAVORITE_SELECT_OWNER, delArgs);
|
||||
db.delete(FavoriteTable.NAME, FAVORITE_SELECT_OWNER, delArgs);
|
||||
}
|
||||
|
||||
/**
|
||||
@ -845,14 +961,13 @@ public class AppDatabase {
|
||||
* @return tweet flags
|
||||
*/
|
||||
private int getTweetFlags(SQLiteDatabase db, long tweetID) {
|
||||
String[] args = {Long.toString(tweetID)};
|
||||
String[] columns = {TweetRegisterTable.REGISTER};
|
||||
String[] args = {Long.toString(tweetID), Long.toString(homeId)};
|
||||
|
||||
Cursor c = db.rawQuery(TWEETFLAG_QUERY, args);
|
||||
Cursor c = db.query(TweetRegisterTable.NAME, columns, TWEET_REG_SELECT, args, null, null, null, SINGLE_ITEM);
|
||||
int result = 0;
|
||||
if (c.moveToFirst()) {
|
||||
int pos = c.getColumnIndexOrThrow(TweetTable.REGISTER);
|
||||
result = c.getInt(pos);
|
||||
}
|
||||
if (c.moveToFirst())
|
||||
result = c.getInt(0);
|
||||
c.close();
|
||||
return result;
|
||||
}
|
||||
@ -865,14 +980,13 @@ public class AppDatabase {
|
||||
* @return user flags
|
||||
*/
|
||||
private int getUserFlags(SQLiteDatabase db, long userID) {
|
||||
String[] args = {Long.toString(userID)};
|
||||
String[] columns = {UserRegisterTable.REGISTER};
|
||||
String[] args = {Long.toString(userID), Long.toString(homeId)};
|
||||
|
||||
Cursor c = db.rawQuery(USERFLAG_QUERY, args);
|
||||
Cursor c = db.query(UserRegisterTable.NAME, columns, USER_REG_SELECT, args, null, null, null, SINGLE_ITEM);
|
||||
int result = 0;
|
||||
if (c.moveToFirst()) {
|
||||
int pos = c.getColumnIndexOrThrow(UserTable.REGISTER);
|
||||
result = c.getInt(pos);
|
||||
}
|
||||
if (c.moveToFirst())
|
||||
result = c.getInt(0);
|
||||
c.close();
|
||||
return result;
|
||||
}
|
||||
@ -887,7 +1001,7 @@ public class AppDatabase {
|
||||
private boolean containStatus(long id, SQLiteDatabase db) {
|
||||
String[] args = {Long.toString(id)};
|
||||
|
||||
Cursor c = db.rawQuery(STATUS_EXIST_QUERY, args);
|
||||
Cursor c = db.query(TweetTable.NAME, null, TWEET_SELECT, args, null, null, SINGLE_ITEM);
|
||||
boolean result = c.moveToFirst();
|
||||
c.close();
|
||||
return result;
|
||||
@ -899,7 +1013,7 @@ public class AppDatabase {
|
||||
* @return SQLite instance
|
||||
*/
|
||||
private synchronized SQLiteDatabase getDbRead() {
|
||||
return dataHelper.getDatabase();
|
||||
return adapter.getDatabase();
|
||||
}
|
||||
|
||||
/**
|
||||
@ -908,7 +1022,7 @@ public class AppDatabase {
|
||||
* @return SQLite instance
|
||||
*/
|
||||
private synchronized SQLiteDatabase getDbWrite() {
|
||||
SQLiteDatabase db = dataHelper.getDatabase();
|
||||
SQLiteDatabase db = adapter.getDatabase();
|
||||
db.beginTransaction();
|
||||
return db;
|
||||
}
|
||||
|
@ -23,7 +23,7 @@ public class DatabaseAdapter {
|
||||
* SQL query to create a table for user information
|
||||
*/
|
||||
private static final String TABLE_USER = "CREATE TABLE IF NOT EXISTS "
|
||||
+ UserTable.TABLE + "("
|
||||
+ UserTable.NAME + "("
|
||||
+ UserTable.ID + " INTEGER PRIMARY KEY,"
|
||||
+ UserTable.USERNAME + " TEXT,"
|
||||
+ UserTable.SCREENNAME + " TEXT,"
|
||||
@ -32,7 +32,6 @@ public class DatabaseAdapter {
|
||||
+ UserTable.DESCRIPTION + " TEXT,"
|
||||
+ UserTable.LOCATION + " TEXT,"
|
||||
+ UserTable.LINK + " TEXT,"
|
||||
+ UserTable.REGISTER + " INTEGER,"
|
||||
+ UserTable.SINCE + " INTEGER,"
|
||||
+ UserTable.FRIENDS + " INTEGER,"
|
||||
+ UserTable.FOLLOWER + " INTEGER,"
|
||||
@ -43,7 +42,7 @@ public class DatabaseAdapter {
|
||||
* SQL query to create a table for tweet information
|
||||
*/
|
||||
private static final String TABLE_TWEET = "CREATE TABLE IF NOT EXISTS "
|
||||
+ TweetTable.TABLE + "("
|
||||
+ TweetTable.NAME + "("
|
||||
+ TweetTable.ID + " INTEGER PRIMARY KEY,"
|
||||
+ TweetTable.USER + " INTEGER,"
|
||||
+ TweetTable.RETWEETID + " INTEGER,"
|
||||
@ -56,30 +55,29 @@ public class DatabaseAdapter {
|
||||
+ TweetTable.MEDIA + " TEXT,"
|
||||
+ TweetTable.RETWEET + " INTEGER,"
|
||||
+ TweetTable.FAVORITE + " INTEGER,"
|
||||
+ TweetTable.REGISTER + " INTEGER,"
|
||||
+ TweetTable.SOURCE + " TEXT,"
|
||||
+ TweetTable.PLACE + " TEXT,"
|
||||
+ TweetTable.COORDINATE + " TEXT,"
|
||||
+ "FOREIGN KEY(" + TweetTable.USER + ")"
|
||||
+ "REFERENCES " + UserTable.TABLE + "(" + UserTable.ID + "));";
|
||||
+ "REFERENCES " + UserTable.NAME + "(" + UserTable.ID + "));";
|
||||
|
||||
/**
|
||||
* SQL query to create a table for favorite tweets
|
||||
*/
|
||||
private static final String TABLE_FAVORS = "CREATE TABLE IF NOT EXISTS "
|
||||
+ FavoriteTable.TABLE + "("
|
||||
+ FavoriteTable.NAME + "("
|
||||
+ FavoriteTable.FAVORITEDBY + " INTEGER,"
|
||||
+ FavoriteTable.TWEETID + " INTEGER,"
|
||||
+ "FOREIGN KEY(" + FavoriteTable.FAVORITEDBY + ")"
|
||||
+ "REFERENCES " + UserTable.TABLE + "(" + UserTable.ID + "),"
|
||||
+ "REFERENCES " + UserTable.NAME + "(" + UserTable.ID + "),"
|
||||
+ "FOREIGN KEY(" + FavoriteTable.TWEETID + ")"
|
||||
+ "REFERENCES " + TweetTable.TABLE + "(" + TweetTable.ID + "));";
|
||||
+ "REFERENCES " + TweetTable.NAME + "(" + TweetTable.ID + "));";
|
||||
|
||||
/**
|
||||
* SQL query to create a table for trend information
|
||||
*/
|
||||
private static final String TABLE_TRENDS = "CREATE TABLE IF NOT EXISTS "
|
||||
+ TrendTable.TABLE + "("
|
||||
+ TrendTable.NAME + "("
|
||||
+ TrendTable.ID + " INTEGER,"
|
||||
+ TrendTable.INDEX + " INTEGER,"
|
||||
+ TrendTable.VOL + " INTEGER,"
|
||||
@ -96,142 +94,64 @@ public class DatabaseAdapter {
|
||||
+ MessageTable.RECEIVER + " INTEGER,"
|
||||
+ MessageTable.MESSAGE + " TEXT);";
|
||||
|
||||
/**
|
||||
*
|
||||
*/
|
||||
private static final String TABLE_TWEET_REGISTER = "CREATE TABLE IF NOT EXISTS "
|
||||
+ TweetRegisterTable.NAME + "("
|
||||
+ TweetRegisterTable.ID + " INTEGER PRIMARY KEY,"
|
||||
+ TweetRegisterTable.OWNER + " INTEGER,"
|
||||
+ TweetRegisterTable.REGISTER + " INTEGER);";
|
||||
|
||||
/**
|
||||
*
|
||||
*/
|
||||
private static final String TABLE_USER_REGISTER = "CREATE TABLE IF NOT EXISTS "
|
||||
+ UserRegisterTable.NAME + "("
|
||||
+ UserRegisterTable.ID + " INTEGER PRIMARY KEY,"
|
||||
+ UserRegisterTable.OWNER + " INTEGER,"
|
||||
+ UserRegisterTable.REGISTER + " INTEGER);";
|
||||
|
||||
/**
|
||||
* SQL query to create a table for user logins
|
||||
*/
|
||||
private static final String TABLE_LOGINS = "CREATE TABLE IF NOT EXISTS "
|
||||
+ LoginTable.NAME + "("
|
||||
+ LoginTable.ID + " INTEGER PRIMARY KEY,"
|
||||
+ LoginTable.DATE + " INTEGER,"
|
||||
+ LoginTable.KEY1 + " TEXT,"
|
||||
+ LoginTable.KEY2 + " TEXT);";
|
||||
|
||||
/**
|
||||
* index for tweet table
|
||||
*/
|
||||
private static final String INDX_TWEET = "CREATE INDEX IF NOT EXISTS idx_tweet"
|
||||
+ " ON " + TweetTable.TABLE + "(" + TweetTable.USER + "," + TweetTable.REGISTER + ");";
|
||||
|
||||
/**
|
||||
* index for favorite table
|
||||
*/
|
||||
private static final String INDX_FAVOR = "CREATE INDEX IF NOT EXISTS idx_favor"
|
||||
+ " ON " + FavoriteTable.TABLE + "(" + FavoriteTable.FAVORITEDBY + "," + FavoriteTable.TWEETID + ");";
|
||||
+ " ON " + TweetTable.NAME + "(" + TweetTable.USER + ");";
|
||||
|
||||
/**
|
||||
* index for trend table
|
||||
*/
|
||||
private static final String INDX_TREND = "CREATE INDEX IF NOT EXISTS idx_trend"
|
||||
+ " ON " + TrendTable.TABLE + "(" + TrendTable.ID + ");";
|
||||
+ " ON " + TrendTable.NAME + "(" + TrendTable.ID + ");";
|
||||
|
||||
/**
|
||||
* update for the tweet table
|
||||
*/
|
||||
private static final String TABLE_TWEET_ADD_PLACE = "ALTER TABLE " + TweetTable.TABLE
|
||||
private static final String TABLE_TWEET_ADD_PLACE = "ALTER TABLE " + TweetTable.NAME
|
||||
+ " ADD COLUMN " + TweetTable.PLACE + " TEXT";
|
||||
|
||||
/**
|
||||
* update for the tweet table
|
||||
*/
|
||||
private static final String TABLE_TWEET_ADD_GEO = "ALTER TABLE " + TweetTable.TABLE
|
||||
private static final String TABLE_TWEET_ADD_GEO = "ALTER TABLE " + TweetTable.NAME
|
||||
+ " ADD COLUMN " + TweetTable.COORDINATE + " TEXT";
|
||||
|
||||
/**
|
||||
* update for the trend table
|
||||
*/
|
||||
private static final String TABLE_TREND_ADD_VOL = "ALTER TABLE " + TrendTable.TABLE
|
||||
private static final String TABLE_TREND_ADD_VOL = "ALTER TABLE " + TrendTable.NAME
|
||||
+ " ADD COLUMN " + TrendTable.VOL + " INTEGER";
|
||||
|
||||
/**
|
||||
*
|
||||
*/
|
||||
private static final String USERTWEET_TABLE = TweetTable.TABLE
|
||||
+ " INNER JOIN " + UserTable.TABLE
|
||||
+ " ON " + TweetTable.TABLE + "." + TweetTable.USER + "=" + UserTable.TABLE + "." + UserTable.ID;
|
||||
|
||||
/**
|
||||
* SQL query to get home timeline tweets
|
||||
*/
|
||||
static final String HOME_QUERY = "SELECT * FROM " + USERTWEET_TABLE
|
||||
+ " WHERE " + TweetTable.REGISTER + "&? IS NOT 0"
|
||||
+ " ORDER BY " + TweetTable.ID
|
||||
+ " DESC LIMIT ?";
|
||||
|
||||
/**
|
||||
* SQL query to get mention timeline
|
||||
*/
|
||||
static final String MENTION_QUERY = "SELECT * FROM " + USERTWEET_TABLE
|
||||
+ " WHERE " + TweetTable.REGISTER + "&? IS NOT 0"
|
||||
+ " AND " + UserTable.REGISTER + "&? IS 0"
|
||||
+ " ORDER BY " + TweetTable.ID
|
||||
+ " DESC LIMIT ?";
|
||||
|
||||
/**
|
||||
* SQL query to get tweets of an user
|
||||
*/
|
||||
static final String USERTWEET_QUERY = "SELECT * FROM " + USERTWEET_TABLE
|
||||
+ " WHERE " + TweetTable.REGISTER + "&? IS NOT 0"
|
||||
+ " AND " + TweetTable.TABLE + "." + TweetTable.USER + "=?"
|
||||
+ " ORDER BY " + TweetTable.ID
|
||||
+ " DESC LIMIT ?";
|
||||
|
||||
/**
|
||||
* SQL query to get tweets favored by an user
|
||||
*/
|
||||
static final String USERFAVORIT_QUERY = "SELECT * FROM " + USERTWEET_TABLE
|
||||
+ " INNER JOIN " + FavoriteTable.TABLE
|
||||
+ " ON " + TweetTable.TABLE + "." + TweetTable.ID + "=" + FavoriteTable.TABLE + "." + FavoriteTable.TWEETID
|
||||
+ " WHERE " + FavoriteTable.FAVORITEDBY + "=?"
|
||||
+ " ORDER BY " + TweetTable.ID
|
||||
+ " DESC LIMIT ?";
|
||||
|
||||
/**
|
||||
* SQL query to get a single tweet specified by an ID
|
||||
*/
|
||||
static final String SINGLE_TWEET_QUERY = "SELECT * FROM " + USERTWEET_TABLE
|
||||
+ " WHERE " + TweetTable.TABLE + "." + TweetTable.ID + "=? LIMIT 1";
|
||||
|
||||
/**
|
||||
* SQL query to get replies of a tweet specified by a reply ID
|
||||
*/
|
||||
static final String ANSWER_QUERY = "SELECT * FROM " + USERTWEET_TABLE
|
||||
+ " WHERE " + TweetTable.TABLE + "." + TweetTable.REPLYTWEET + "=?"
|
||||
+ " AND " + TweetTable.REGISTER + "&? IS NOT 0"
|
||||
+ " AND " + UserTable.REGISTER + "&? IS 0"
|
||||
+ " ORDER BY " + TweetTable.ID + " DESC LIMIT ?";
|
||||
|
||||
/**
|
||||
* SQL query to get locale based trends
|
||||
*/
|
||||
static final String TREND_QUERY = "SELECT * FROM " + TrendTable.TABLE
|
||||
+ " WHERE " + TrendTable.ID + "=?"
|
||||
+ " ORDER BY " + TrendTable.INDEX + " ASC";
|
||||
|
||||
/**
|
||||
* SQL query to get direct messages
|
||||
*/
|
||||
static final String MESSAGE_QUERY = "SELECT * FROM " + MessageTable.TABLE
|
||||
+ " ORDER BY " + MessageTable.ID + " DESC "
|
||||
+ "LIMIT ?";
|
||||
|
||||
/**
|
||||
* SQL query to get user information
|
||||
*/
|
||||
static final String USER_QUERY = "SELECT * FROM " + UserTable.TABLE
|
||||
+ " WHERE " + UserTable.ID + "=?"
|
||||
+ " LIMIT 1";
|
||||
|
||||
/**
|
||||
* SQL query to get a status register for a tweet
|
||||
*/
|
||||
static final String TWEETFLAG_QUERY = "SELECT " + TweetTable.REGISTER + " FROM " + TweetTable.TABLE
|
||||
+ " WHERE " + TweetTable.ID + "=?"
|
||||
+ " LIMIT 1;";
|
||||
|
||||
/**
|
||||
* SQL query to get a status register of an user
|
||||
*/
|
||||
static final String USERFLAG_QUERY = "SELECT " + UserTable.REGISTER + " FROM " + UserTable.TABLE
|
||||
+ " WHERE " + UserTable.ID + "=?"
|
||||
+ " LIMIT 1;";
|
||||
|
||||
/**
|
||||
* SQL query to check if a status exists in database
|
||||
*/
|
||||
static final String STATUS_EXIST_QUERY = "SELECT * FROM " + TweetTable.TABLE
|
||||
+ " WHERE " + TweetTable.ID + "=?"
|
||||
+ " LIMIT 1;";
|
||||
|
||||
/**
|
||||
* singleton instance
|
||||
*/
|
||||
@ -313,9 +233,11 @@ public class DatabaseAdapter {
|
||||
db.execSQL(TABLE_FAVORS);
|
||||
db.execSQL(TABLE_TRENDS);
|
||||
db.execSQL(TABLE_MESSAGES);
|
||||
db.execSQL(TABLE_LOGINS);
|
||||
db.execSQL(INDX_TWEET);
|
||||
db.execSQL(INDX_FAVOR);
|
||||
db.execSQL(INDX_TREND);
|
||||
db.execSQL(TABLE_TWEET_REGISTER);
|
||||
db.execSQL(TABLE_USER_REGISTER);
|
||||
/// Database just created? set current version
|
||||
if (db.getVersion() == 0) {
|
||||
db.setVersion(LATEST_VERSION);
|
||||
@ -326,66 +248,179 @@ public class DatabaseAdapter {
|
||||
* table for user information
|
||||
*/
|
||||
public interface UserTable {
|
||||
// table name
|
||||
String TABLE = "user";
|
||||
// user information
|
||||
|
||||
/**
|
||||
* table name
|
||||
*/
|
||||
String NAME = "user";
|
||||
|
||||
/**
|
||||
* ID of the user
|
||||
*/
|
||||
String ID = "userID";
|
||||
|
||||
/**
|
||||
* user name
|
||||
*/
|
||||
String USERNAME = "username";
|
||||
|
||||
/**
|
||||
* screen name (starting with @)
|
||||
*/
|
||||
String SCREENNAME = "scrname";
|
||||
|
||||
/**
|
||||
* description (bio) of the user
|
||||
*/
|
||||
String DESCRIPTION = "bio";
|
||||
|
||||
/**
|
||||
* location attached to profile
|
||||
*/
|
||||
String LOCATION = "location";
|
||||
|
||||
/**
|
||||
* link attached to profile
|
||||
*/
|
||||
String LINK = "link";
|
||||
|
||||
/**
|
||||
* date of account creation
|
||||
*/
|
||||
String SINCE = "createdAt";
|
||||
// image links
|
||||
|
||||
/**
|
||||
* link to the original profile image
|
||||
*/
|
||||
String IMAGE = "pbLink";
|
||||
|
||||
/**
|
||||
* link to the original banner image
|
||||
*/
|
||||
String BANNER = "banner";
|
||||
// connections
|
||||
|
||||
/**
|
||||
* following count
|
||||
*/
|
||||
String FRIENDS = "following";
|
||||
|
||||
/**
|
||||
* follower count
|
||||
*/
|
||||
String FOLLOWER = "follower";
|
||||
// tweet count of the user
|
||||
|
||||
/**
|
||||
* count of tweets written/retweeted by user
|
||||
*/
|
||||
String TWEETS = "tweetCount";
|
||||
|
||||
/**
|
||||
* count of the tweets favored by the user
|
||||
*/
|
||||
String FAVORS = "favorCount";
|
||||
// integer register containing status bits
|
||||
String REGISTER = "userregister";
|
||||
}
|
||||
|
||||
/**
|
||||
* table for all tweets
|
||||
*/
|
||||
public interface TweetTable {
|
||||
// table name
|
||||
String TABLE = "tweet";
|
||||
// tweet information
|
||||
/**
|
||||
* table name
|
||||
*/
|
||||
String NAME = "tweet";
|
||||
|
||||
/**
|
||||
* ID of the tweet
|
||||
*/
|
||||
String ID = "tweetID";
|
||||
|
||||
/**
|
||||
* ID of the author
|
||||
*/
|
||||
String USER = "userID";
|
||||
|
||||
/**
|
||||
* tweet text
|
||||
*/
|
||||
String TWEET = "tweet";
|
||||
|
||||
/**
|
||||
* media links attached to the tweet
|
||||
*/
|
||||
String MEDIA = "media";
|
||||
|
||||
/**
|
||||
* retweet count
|
||||
*/
|
||||
String RETWEET = "retweet";
|
||||
|
||||
/**
|
||||
* favorite count
|
||||
*/
|
||||
String FAVORITE = "favorite";
|
||||
|
||||
/**
|
||||
* timestamp of the tweet
|
||||
*/
|
||||
String SINCE = "time";
|
||||
|
||||
/**
|
||||
* API source of the tweet
|
||||
*/
|
||||
String SOURCE = "source";
|
||||
// tweet location
|
||||
|
||||
/**
|
||||
* place name of the tweet
|
||||
*/
|
||||
String PLACE = "place";
|
||||
|
||||
/**
|
||||
* GPS coordinate of the tweet
|
||||
*/
|
||||
String COORDINATE = "geo";
|
||||
// information about the replied tweet
|
||||
|
||||
/**
|
||||
* ID of the re plied tweet
|
||||
*/
|
||||
String REPLYTWEET = "replyID";
|
||||
|
||||
/**
|
||||
* ID of the replied user
|
||||
*/
|
||||
String REPLYUSER = "replyUserID";
|
||||
|
||||
/**
|
||||
* name of the replied user
|
||||
*/
|
||||
String REPLYNAME = "replyname";
|
||||
// information about the retweeter
|
||||
|
||||
/**
|
||||
* ID of the embedded (retweeted) status
|
||||
*/
|
||||
String RETWEETID = "retweetID";
|
||||
|
||||
/**
|
||||
* ID of the
|
||||
*/
|
||||
String RETWEETUSER = "retweeterID";
|
||||
// register containing status bits
|
||||
String REGISTER = "statusregister";
|
||||
}
|
||||
|
||||
/**
|
||||
* table for favored tweets of an user
|
||||
*/
|
||||
public interface FavoriteTable {
|
||||
// table name
|
||||
String TABLE = "favorit";
|
||||
//
|
||||
/**
|
||||
* table name
|
||||
*/
|
||||
String NAME = "favorit";
|
||||
|
||||
/**
|
||||
* ID of the tweet
|
||||
*/
|
||||
String TWEETID = "tweetID";
|
||||
/**
|
||||
* ID of the user of this favored tweet
|
||||
*/
|
||||
String FAVORITEDBY = "ownerID";
|
||||
}
|
||||
|
||||
@ -393,12 +428,29 @@ public class DatabaseAdapter {
|
||||
* table for twitter trends
|
||||
*/
|
||||
public interface TrendTable {
|
||||
// tale name
|
||||
String TABLE = "trend";
|
||||
// trend information
|
||||
/**
|
||||
* table name
|
||||
*/
|
||||
String NAME = "trend";
|
||||
|
||||
/**
|
||||
* ID of the trend location
|
||||
*/
|
||||
String ID = "woeID";
|
||||
|
||||
/**
|
||||
* rank of the trend
|
||||
*/
|
||||
String INDEX = "trendpos";
|
||||
|
||||
/**
|
||||
* popularity count
|
||||
*/
|
||||
String VOL = "vol";
|
||||
|
||||
/**
|
||||
* name of the trend
|
||||
*/
|
||||
String TREND = "trendname";
|
||||
}
|
||||
|
||||
@ -406,13 +458,121 @@ public class DatabaseAdapter {
|
||||
* Table for direct messages
|
||||
*/
|
||||
public interface MessageTable {
|
||||
// table name
|
||||
/**
|
||||
* table name
|
||||
*/
|
||||
String TABLE = "message";
|
||||
// message information
|
||||
|
||||
/**
|
||||
* ID of the message
|
||||
*/
|
||||
String ID = "messageID";
|
||||
|
||||
/**
|
||||
* date of the message
|
||||
*/
|
||||
String SINCE = "time";
|
||||
|
||||
/**
|
||||
* User ID of the sender
|
||||
*/
|
||||
String SENDER = "senderID";
|
||||
|
||||
/**
|
||||
* User ID of the receiver
|
||||
*/
|
||||
String RECEIVER = "receiverID";
|
||||
|
||||
/**
|
||||
* message text
|
||||
*/
|
||||
String MESSAGE = "message";
|
||||
}
|
||||
|
||||
/**
|
||||
* Table for multi user login information
|
||||
*/
|
||||
public interface LoginTable {
|
||||
/**
|
||||
* SQL table name
|
||||
*/
|
||||
String NAME = "login";
|
||||
|
||||
/**
|
||||
* ID of the user
|
||||
*/
|
||||
String ID = "userID";
|
||||
|
||||
/**
|
||||
* date of login
|
||||
*/
|
||||
String DATE = "date";
|
||||
|
||||
/**
|
||||
* primary oauth access token
|
||||
*/
|
||||
String KEY1 = "auth_key1";
|
||||
|
||||
/**
|
||||
* second oauth access token
|
||||
*/
|
||||
String KEY2 = "auth_key2";
|
||||
}
|
||||
|
||||
/**
|
||||
* table for tweet register
|
||||
* <p>
|
||||
* a register contains status flags (status bits) of a tweet
|
||||
* every flag stands for a status like retweeted or favored
|
||||
* the idea is to save space by putting boolean rows into a single integer row
|
||||
* <p>
|
||||
* to avoid conflicts between multi users,
|
||||
* every login has its own status registers
|
||||
*/
|
||||
public interface TweetRegisterTable {
|
||||
/**
|
||||
* SQL table name
|
||||
*/
|
||||
String NAME = "tweetFlags";
|
||||
|
||||
/**
|
||||
* ID of the user this register references to
|
||||
*/
|
||||
String ID = "tweetID";
|
||||
|
||||
/**
|
||||
* ID of the current user accessing the database
|
||||
*/
|
||||
String OWNER = "ownerID";
|
||||
|
||||
/**
|
||||
* Register with status bits
|
||||
*/
|
||||
String REGISTER = "tweetRegister";
|
||||
}
|
||||
|
||||
/**
|
||||
* table for user register
|
||||
*/
|
||||
public interface UserRegisterTable {
|
||||
/**
|
||||
* SQL table name
|
||||
*/
|
||||
String NAME = "userFlags";
|
||||
|
||||
/**
|
||||
* ID of the user this register references to
|
||||
*/
|
||||
String ID = "userID";
|
||||
|
||||
/**
|
||||
* ID of the current user accessing the database
|
||||
*/
|
||||
String OWNER = "ownerID";
|
||||
|
||||
/**
|
||||
* Register with status bits
|
||||
*/
|
||||
String REGISTER = "userRegister";
|
||||
}
|
||||
}
|
@ -15,6 +15,7 @@ import static android.content.Context.MODE_PRIVATE;
|
||||
import static android.graphics.Typeface.DEFAULT;
|
||||
import static android.graphics.Typeface.MONOSPACE;
|
||||
import static android.graphics.Typeface.NORMAL;
|
||||
import static android.graphics.Typeface.SANS_SERIF;
|
||||
import static android.graphics.Typeface.SERIF;
|
||||
|
||||
/**
|
||||
@ -44,17 +45,27 @@ public class GlobalSettings {
|
||||
*/
|
||||
public static final String BANNER_IMG_MID_RES = "/600x200";
|
||||
|
||||
/**
|
||||
* custom android font
|
||||
*/
|
||||
private static final Typeface SANS_SERIF_THIN = Typeface.create("sans-serif-thin", NORMAL);
|
||||
|
||||
/**
|
||||
* custom font families from android system
|
||||
*/
|
||||
public static final Typeface[] FONTS = {DEFAULT, MONOSPACE, SERIF, Typeface.create("sans-serif-thin", NORMAL)};
|
||||
public static final Typeface[] FONTS = {DEFAULT, MONOSPACE, SERIF, SANS_SERIF, SANS_SERIF_THIN};
|
||||
|
||||
/**
|
||||
* names of the font types {@link #FONTS}
|
||||
*/
|
||||
public static final String[] FONT_NAMES = {"Default", "Monospace", "Serif", "sans-serif-thin"};
|
||||
public static final String[] FONT_NAMES = {"Default", "Monospace", "Serif", "Sans-Serif", "sans-serif-thin"};
|
||||
|
||||
// Setting names stored in SharedPreference
|
||||
/**
|
||||
* singleton instance
|
||||
*/
|
||||
private static final GlobalSettings ourInstance = new GlobalSettings();
|
||||
|
||||
// App preference names
|
||||
private static final String BACKGROUND_COLOR = "background_color";
|
||||
private static final String HIGHLIGHT_COLOR = "highlight_color";
|
||||
private static final String FONT_COLOR = "font_color";
|
||||
@ -67,10 +78,6 @@ public class GlobalSettings {
|
||||
private static final String IMAGE_QUALITY = "image_hq";
|
||||
private static final String ANSWER_LOAD = "answer_load";
|
||||
private static final String PROFILE_OVERLAP = "profile_toolbar_overlap";
|
||||
private static final String LOGGED_IN = "login";
|
||||
private static final String AUTH_KEY1 = "key1";
|
||||
private static final String AUTH_KEY2 = "key2";
|
||||
private static final String USER_ID = "userID";
|
||||
private static final String PROXY_SET = "proxy_enabled";
|
||||
private static final String AUTH_SET = "proxy_auth_set";
|
||||
private static final String PROXY_ADDR = "proxy_addr";
|
||||
@ -84,25 +91,29 @@ public class GlobalSettings {
|
||||
private static final String CUSTOM_CONSUMER_KEY_1 = "api_key1";
|
||||
private static final String CUSTOM_CONSUMER_KEY_2 = "api_key2";
|
||||
|
||||
// login specific preference names
|
||||
private static final String LOGGED_IN = "login";
|
||||
private static final String CURRENT_ID = "userID";
|
||||
private static final String CURRENT_AUTH_KEY1 = "key1";
|
||||
private static final String CURRENT_AUTH_KEY2 = "key2";
|
||||
|
||||
// file name of the preferences
|
||||
private static final String APP_SETTINGS = "settings";
|
||||
|
||||
// Default App settings
|
||||
@IntRange(from = 0, to = 3)
|
||||
@IntRange(from = 0, to = 4)
|
||||
private static final int DEFAULT_FONT_INDEX = 0;
|
||||
@IntRange(from = 0, to = 100)
|
||||
private static final int DEFAULT_LIST_SIZE = 20;
|
||||
private static final int DEFAULT_BACKGROUND_COLOR = 0xff0f114a;
|
||||
private static final int DEFAULT_HIGHLIGHT_COLOR = 0xffff00ff;
|
||||
private static final int DEFAULT_FONT_COLOR = 0xffffffff;
|
||||
private static final int DEFAULT_FONT_COLOR = Color.WHITE;
|
||||
private static final int DEFAULT_POPUP_COLOR = 0xff19aae8;
|
||||
private static final int DEFAULT_CARD_COLOR = 0x40000000;
|
||||
private static final int DEFAULT_ICON_COLOR = Color.WHITE;
|
||||
private static final int DEFAULT_LOCATION_WOEID = 1;
|
||||
private static final int DEFAULT_LOCATION_ID = 1;
|
||||
private static final String DEFAULT_LOCATION_NAME = "Worldwide";
|
||||
|
||||
private static final GlobalSettings ourInstance = new GlobalSettings();
|
||||
|
||||
private SharedPreferences settings;
|
||||
private TrendLocation location;
|
||||
private String api_key1, api_key2;
|
||||
@ -696,9 +707,9 @@ public class GlobalSettings {
|
||||
|
||||
Editor e = settings.edit();
|
||||
e.putBoolean(LOGGED_IN, true);
|
||||
e.putLong(USER_ID, userId);
|
||||
e.putString(AUTH_KEY1, key1);
|
||||
e.putString(AUTH_KEY2, key2);
|
||||
e.putLong(CURRENT_ID, userId);
|
||||
e.putString(CURRENT_AUTH_KEY1, key1);
|
||||
e.putString(CURRENT_AUTH_KEY2, key2);
|
||||
e.apply();
|
||||
}
|
||||
|
||||
@ -773,17 +784,18 @@ public class GlobalSettings {
|
||||
toolbarOverlap = settings.getBoolean(PROFILE_OVERLAP, true);
|
||||
linkPreview = settings.getBoolean(LINK_PREVIEW, false);
|
||||
customAPIKey = settings.getBoolean(CUSTOM_CONSUMER_KEY_SET, false);
|
||||
api_key1 = settings.getString(CUSTOM_CONSUMER_KEY_1, "");
|
||||
api_key2 = settings.getString(CUSTOM_CONSUMER_KEY_2, "");
|
||||
auth_key1 = settings.getString(AUTH_KEY1, "");
|
||||
auth_key2 = settings.getString(AUTH_KEY2, "");
|
||||
proxyHost = settings.getString(PROXY_ADDR, "");
|
||||
proxyPort = settings.getString(PROXY_PORT, "");
|
||||
proxyUser = settings.getString(PROXY_USER, "");
|
||||
proxyPass = settings.getString(PROXY_PASS, "");
|
||||
userId = settings.getLong(USER_ID, 0);
|
||||
String place = settings.getString(TREND_LOC, DEFAULT_LOCATION_NAME);
|
||||
int woeId = settings.getInt(TREND_ID, DEFAULT_LOCATION_WOEID);
|
||||
int woeId = settings.getInt(TREND_ID, DEFAULT_LOCATION_ID);
|
||||
location = new TrendLocation(place, woeId);
|
||||
|
||||
api_key1 = settings.getString(CUSTOM_CONSUMER_KEY_1, "");
|
||||
api_key2 = settings.getString(CUSTOM_CONSUMER_KEY_2, "");
|
||||
auth_key1 = settings.getString(CURRENT_AUTH_KEY1, "");
|
||||
auth_key2 = settings.getString(CURRENT_AUTH_KEY2, "");
|
||||
userId = settings.getLong(CURRENT_ID, 0);
|
||||
}
|
||||
}
|
@ -22,6 +22,7 @@ public class ConfirmDialog extends AlertDialog implements OnClickListener {
|
||||
WRONG_PROXY,
|
||||
DEL_DATABASE,
|
||||
APP_LOG_OUT,
|
||||
REMOVE_ACCOUNT,
|
||||
TWEET_DELETE,
|
||||
TWEET_EDITOR_LEAVE,
|
||||
TWEET_EDITOR_ERROR,
|
||||
@ -143,6 +144,12 @@ public class ConfirmDialog extends AlertDialog implements OnClickListener {
|
||||
case LIST_DELETE:
|
||||
message = c.getString(R.string.confirm_delete_list);
|
||||
break;
|
||||
|
||||
case REMOVE_ACCOUNT:
|
||||
message = c.getString(R.string.confirm_remove_account);
|
||||
posButton = c.getString(R.string.dialog_button_ok);
|
||||
negButton = c.getString(R.string.dialog_button_cancel);
|
||||
break;
|
||||
}
|
||||
setTitle(title);
|
||||
setMessage(message);
|
||||
|
@ -80,6 +80,7 @@ public class LinkDialog extends Dialog implements LinkPreviewCallback, OnClickLi
|
||||
public void dismiss() {
|
||||
super.dismiss();
|
||||
textCrawler.cancel();
|
||||
Picasso.get().cancelRequest(preview);
|
||||
}
|
||||
|
||||
|
||||
|
@ -0,0 +1,132 @@
|
||||
package org.nuclearfog.twidda.fragment;
|
||||
|
||||
import androidx.annotation.Nullable;
|
||||
import androidx.appcompat.app.AlertDialog;
|
||||
|
||||
import org.nuclearfog.twidda.adapter.AccountAdapter;
|
||||
import org.nuclearfog.twidda.adapter.AccountAdapter.OnLoginClickListener;
|
||||
import org.nuclearfog.twidda.backend.LoginLoader;
|
||||
import org.nuclearfog.twidda.backend.engine.EngineException;
|
||||
import org.nuclearfog.twidda.backend.model.Account;
|
||||
import org.nuclearfog.twidda.backend.utils.ErrorHandler;
|
||||
import org.nuclearfog.twidda.database.GlobalSettings;
|
||||
import org.nuclearfog.twidda.dialog.ConfirmDialog;
|
||||
import org.nuclearfog.twidda.dialog.ConfirmDialog.OnConfirmListener;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
import static android.os.AsyncTask.Status.RUNNING;
|
||||
import static org.nuclearfog.twidda.activity.AccountActivity.RET_ACCOUNT_CHANGE;
|
||||
import static org.nuclearfog.twidda.dialog.ConfirmDialog.DialogType;
|
||||
|
||||
|
||||
/**
|
||||
* fragment class of the account manager
|
||||
* all registered accounts are listed here
|
||||
*
|
||||
* @author nuclearfog
|
||||
*/
|
||||
public class AccountFragment extends ListFragment implements OnLoginClickListener, OnConfirmListener {
|
||||
|
||||
@Nullable
|
||||
private LoginLoader loginTask;
|
||||
private GlobalSettings settings;
|
||||
private AccountAdapter adapter;
|
||||
private AlertDialog dialog;
|
||||
private Account selection;
|
||||
|
||||
|
||||
@Override
|
||||
protected void onCreate() {
|
||||
dialog = new ConfirmDialog(requireContext(), DialogType.REMOVE_ACCOUNT, this);
|
||||
settings = GlobalSettings.getInstance(requireContext());
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public void onStart() {
|
||||
super.onStart();
|
||||
if (loginTask == null) {
|
||||
setRefresh(true);
|
||||
loginTask = new LoginLoader(this);
|
||||
loginTask.execute();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public void onDestroy() {
|
||||
if (loginTask != null && loginTask.getStatus() == RUNNING)
|
||||
loginTask.cancel(true);
|
||||
super.onDestroy();
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
protected void onReload() {
|
||||
if (loginTask == null || loginTask.getStatus() != RUNNING)
|
||||
loginTask = new LoginLoader(this);
|
||||
loginTask.execute();
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
protected void onReset() {
|
||||
adapter.clear();
|
||||
loginTask = new LoginLoader(this);
|
||||
loginTask.execute();
|
||||
setRefresh(true);
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
protected AccountAdapter initAdapter() {
|
||||
adapter = new AccountAdapter(settings, this);
|
||||
return adapter;
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public void onLoginClick(Account account) {
|
||||
// set new account
|
||||
String[] token = account.getKeys();
|
||||
settings.setConnection(token[0], token[1], account.getId());
|
||||
// finish activity and return to parent activity
|
||||
requireActivity().setResult(RET_ACCOUNT_CHANGE);
|
||||
requireActivity().finish();
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public void onDeleteClick(Account account) {
|
||||
if (!dialog.isShowing()) {
|
||||
selection = account;
|
||||
dialog.show();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public void onConfirm(DialogType type) {
|
||||
loginTask = new LoginLoader(this);
|
||||
loginTask.execute(selection);
|
||||
}
|
||||
|
||||
/**
|
||||
* called from {@link LoginLoader}
|
||||
*
|
||||
* @param result login information
|
||||
*/
|
||||
public void onSuccess(List<Account> result) {
|
||||
adapter.setData(result);
|
||||
setRefresh(false);
|
||||
}
|
||||
|
||||
/**
|
||||
* called from {@link LoginLoader} when an error occurs
|
||||
*/
|
||||
public void onError(EngineException err) {
|
||||
ErrorHandler.handleFailure(requireContext(), err);
|
||||
setRefresh(false);
|
||||
}
|
||||
}
|
@ -11,6 +11,7 @@ import androidx.fragment.app.Fragment;
|
||||
import androidx.recyclerview.widget.LinearLayoutManager;
|
||||
import androidx.recyclerview.widget.RecyclerView;
|
||||
import androidx.recyclerview.widget.RecyclerView.Adapter;
|
||||
import androidx.recyclerview.widget.RecyclerView.ViewHolder;
|
||||
import androidx.swiperefreshlayout.widget.SwipeRefreshLayout;
|
||||
import androidx.swiperefreshlayout.widget.SwipeRefreshLayout.OnRefreshListener;
|
||||
|
||||
@ -130,5 +131,5 @@ public abstract class ListFragment extends Fragment implements OnRefreshListener
|
||||
*
|
||||
* @return adapter for the recycler view list
|
||||
*/
|
||||
protected abstract Adapter<RecyclerView.ViewHolder> initAdapter();
|
||||
protected abstract Adapter<? extends ViewHolder> initAdapter();
|
||||
}
|
@ -61,7 +61,7 @@ public class TrendFragment extends ListFragment implements TrendClickListener {
|
||||
|
||||
@Override
|
||||
protected TrendAdapter initAdapter() {
|
||||
adapter = new TrendAdapter(this);
|
||||
adapter = new TrendAdapter(settings, this);
|
||||
return adapter;
|
||||
}
|
||||
|
||||
|
21
app/src/main/res/drawable/switch_account.xml
Normal file
21
app/src/main/res/drawable/switch_account.xml
Normal file
@ -0,0 +1,21 @@
|
||||
<vector xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:height="24dp"
|
||||
android:width="24dp"
|
||||
android:viewportHeight="490.067"
|
||||
android:viewportWidth="490.067">
|
||||
<path
|
||||
android:fillColor="#FFFFFFFF"
|
||||
android:pathData="M178.414,467.038c4.889,-27.122 16.416,-52.318 33.127,-73.795c-3.246,-3.229 -6.609,-6.334 -10.211,-9.164c-4.908,-3.884 -9.164,-8.431 -12.795,-13.421c-17.025,15.069 -37.912,24.081 -60.545,24.081c-22.631,0 -43.518,-9.012 -60.539,-24.081c-3.631,4.982 -7.875,9.522 -12.789,13.421c-22,17.324 -37.877,42.337 -43.154,71.603l-2.231,12.456c-0.973,5.427 0.508,11.017 4.051,15.247c3.541,4.24 8.779,6.682 14.301,6.682h152.525C177.785,482.715 177.018,474.878 178.414,467.038z" />
|
||||
<path
|
||||
android:fillColor="#FFFFFFFF"
|
||||
android:pathData="M430.906,389.95c-4.061,-3.195 -7.611,-6.874 -10.92,-10.75c-20.691,19.073 -46.271,30.512 -74.031,30.512c-27.771,0 -53.348,-11.439 -74.049,-30.494c-3.297,3.858 -6.84,7.53 -10.9,10.732c-25.5,20.078 -43.877,49.043 -49.982,82.962c-0.76,4.253 0.404,8.623 3.178,11.931c2.768,3.31 6.869,5.225 11.189,5.225h7.807h233.291c4.32,0 8.422,-1.915 11.184,-5.225c2.779,-3.308 3.941,-7.678 3.184,-11.931C474.725,438.993 456.377,410.028 430.906,389.95z" />
|
||||
<path
|
||||
android:fillColor="#FFFFFFFF"
|
||||
android:pathData="M255.035,256.895c0,66.111 40.736,119.685 90.92,119.685c50.178,0 90.873,-53.573 90.873,-119.685c0,-66.079 -40.695,-119.652 -90.873,-119.652C295.772,137.242 255.035,190.815 255.035,256.895z" />
|
||||
<path
|
||||
android:fillColor="#FFFFFFFF"
|
||||
android:pathData="M127.99,361.606c38.68,0 70.018,-41.27 70.018,-92.148c0,-50.904 -31.338,-92.166 -70.018,-92.166c-38.625,0 -69.996,41.262 -69.996,92.166C57.994,320.337 89.365,361.606 127.99,361.606z" />
|
||||
<path
|
||||
android:fillColor="#FFFFFFFF"
|
||||
android:pathData="M109.848,111.877l76.213,0.048c6.994,0.01 13.266,-4.221 15.934,-10.637c2.668,-6.446 1.191,-13.864 -3.752,-18.798l-16.426,-16.43c19.813,-10.677 42.082,-16.364 65.232,-16.364c36.814,0 71.43,14.334 97.459,40.364c4.853,4.854 11.209,7.28 17.568,7.28c6.355,0 12.717,-2.427 17.57,-7.28c9.707,-9.698 9.707,-25.431 0,-35.139C344.233,19.501 297.139,0 247.049,0c-36.545,0 -71.439,10.49 -101.434,29.862L122.02,6.268c-4.928,-4.934 -12.326,-6.408 -18.816,-3.747c-6.42,2.662 -10.609,8.925 -10.609,15.937v76.19C92.594,104.145 100.324,111.877 109.848,111.877z" />
|
||||
</vector>
|
79
app/src/main/res/layout/item_login.xml
Normal file
79
app/src/main/res/layout/item_login.xml
Normal file
@ -0,0 +1,79 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<androidx.cardview.widget.CardView xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
xmlns:app="http://schemas.android.com/apk/res-auto"
|
||||
style="@style/CardViewStyle"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content">
|
||||
|
||||
<androidx.constraintlayout.widget.ConstraintLayout
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:padding="@dimen/login_layout_padding">
|
||||
|
||||
<ImageView
|
||||
android:id="@+id/item_login_image"
|
||||
android:layout_width="@dimen/login_image_size"
|
||||
android:layout_height="@dimen/login_image_size"
|
||||
android:layout_marginEnd="@dimen/login_layout_padding"
|
||||
android:layout_marginRight="@dimen/login_layout_padding"
|
||||
app:layout_constraintStart_toStartOf="parent"
|
||||
app:layout_constraintTop_toTopOf="parent"
|
||||
app:layout_constraintBottom_toBottomOf="parent"
|
||||
app:layout_constraintEnd_toStartOf="@+id/item_login_image_barrier" />
|
||||
|
||||
<androidx.constraintlayout.widget.Barrier
|
||||
android:id="@+id/item_login_image_barrier"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
app:barrierDirection="start"
|
||||
app:constraint_referenced_ids="item_login_username,item_login_screenname,item_login_createdAt" />
|
||||
|
||||
<TextView
|
||||
android:id="@+id/item_login_username"
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="wrap_content"
|
||||
android:textSize="@dimen/login_name_textsize"
|
||||
app:layout_constraintStart_toEndOf="@id/item_login_image_barrier"
|
||||
app:layout_constraintTop_toTopOf="parent"
|
||||
app:layout_constraintEnd_toStartOf="@id/item_login_button_barrier" />
|
||||
|
||||
<TextView
|
||||
android:id="@+id/item_login_screenname"
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="wrap_content"
|
||||
android:textSize="@dimen/login_name_textsize"
|
||||
app:layout_constraintStart_toEndOf="@id/item_login_image_barrier"
|
||||
app:layout_constraintTop_toBottomOf="@id/item_login_username"
|
||||
app:layout_constraintBottom_toTopOf="@id/item_login_createdAt"
|
||||
app:layout_constraintEnd_toStartOf="@id/item_login_button_barrier" />
|
||||
|
||||
<TextView
|
||||
android:id="@+id/item_login_createdAt"
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="wrap_content"
|
||||
app:layout_constraintStart_toEndOf="@id/item_login_image_barrier"
|
||||
app:layout_constraintTop_toBottomOf="@id/item_login_screenname"
|
||||
app:layout_constraintEnd_toStartOf="@id/item_login_button_barrier" />
|
||||
|
||||
<androidx.constraintlayout.widget.Barrier
|
||||
android:id="@+id/item_login_button_barrier"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
app:barrierDirection="end"
|
||||
app:constraint_referenced_ids="item_login_username,item_login_screenname,item_login_createdAt" />
|
||||
|
||||
<ImageButton
|
||||
android:id="@+id/item_login_remove"
|
||||
android:layout_width="@dimen/login_cross_size"
|
||||
android:layout_height="@dimen/login_cross_size"
|
||||
android:layout_marginStart="@dimen/login_layout_padding"
|
||||
android:layout_marginLeft="@dimen/login_layout_padding"
|
||||
app:layout_constraintStart_toEndOf="@+id/item_login_button_barrier"
|
||||
app:layout_constraintTop_toTopOf="parent"
|
||||
app:layout_constraintBottom_toBottomOf="parent"
|
||||
app:layout_constraintEnd_toEndOf="parent"
|
||||
style="@style/RoundButton" />
|
||||
|
||||
</androidx.constraintlayout.widget.ConstraintLayout>
|
||||
|
||||
</androidx.cardview.widget.CardView>
|
@ -1,19 +1,20 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:id="@+id/dm_layout"
|
||||
android:id="@+id/fragment_root"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
android:fitsSystemWindows="true"
|
||||
android:orientation="vertical">
|
||||
android:orientation="vertical"
|
||||
android:fitsSystemWindows="true">
|
||||
|
||||
<androidx.appcompat.widget.Toolbar
|
||||
android:id="@+id/dm_toolbar"
|
||||
android:id="@+id/fragment_toolbar"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="@dimen/dmpage_toolbar_height" />
|
||||
|
||||
<androidx.viewpager.widget.ViewPager
|
||||
android:id="@+id/dm_pager"
|
||||
<androidx.fragment.app.FragmentContainerView
|
||||
android:id="@+id/fragment_container"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent" />
|
||||
android:layout_height="0dp"
|
||||
android:layout_weight="1" />
|
||||
|
||||
</LinearLayout>
|
@ -274,7 +274,7 @@
|
||||
app:layout_constraintHorizontal_weight="1"
|
||||
app:layout_constraintStart_toStartOf="parent"
|
||||
app:layout_constraintTop_toTopOf="parent"
|
||||
app:layout_constraintBottom_toTopOf="@id/tweet_pager" />
|
||||
app:layout_constraintBottom_toTopOf="@id/tweet_reply_fragment" />
|
||||
|
||||
<Button
|
||||
android:id="@+id/tweet_retweet"
|
||||
@ -290,7 +290,7 @@
|
||||
app:layout_constraintHorizontal_weight="1"
|
||||
app:layout_constraintStart_toEndOf="@+id/tweet_answer"
|
||||
app:layout_constraintTop_toTopOf="parent"
|
||||
app:layout_constraintBottom_toTopOf="@id/tweet_pager" />
|
||||
app:layout_constraintBottom_toTopOf="@id/tweet_reply_fragment" />
|
||||
|
||||
<Button
|
||||
android:id="@+id/tweet_favorite"
|
||||
@ -306,10 +306,10 @@
|
||||
app:layout_constraintHorizontal_weight="1"
|
||||
app:layout_constraintStart_toEndOf="@+id/tweet_retweet"
|
||||
app:layout_constraintTop_toTopOf="parent"
|
||||
app:layout_constraintBottom_toTopOf="@id/tweet_pager" />
|
||||
app:layout_constraintBottom_toTopOf="@id/tweet_reply_fragment" />
|
||||
|
||||
<androidx.viewpager.widget.ViewPager
|
||||
android:id="@+id/tweet_pager"
|
||||
<androidx.fragment.app.FragmentContainerView
|
||||
android:id="@+id/tweet_reply_fragment"
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="0dp"
|
||||
app:layout_constraintBottom_toBottomOf="parent"
|
||||
|
@ -1,19 +0,0 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:id="@+id/user_view"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
android:fitsSystemWindows="true"
|
||||
android:orientation="vertical">
|
||||
|
||||
<androidx.appcompat.widget.Toolbar
|
||||
android:id="@+id/user_toolbar"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="@dimen/userlistpage_toolbar_height" />
|
||||
|
||||
<androidx.viewpager.widget.ViewPager
|
||||
android:id="@+id/user_pager"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent" />
|
||||
|
||||
</LinearLayout>
|
11
app/src/main/res/menu/accounts.xml
Normal file
11
app/src/main/res/menu/accounts.xml
Normal file
@ -0,0 +1,11 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<menu xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
xmlns:app="http://schemas.android.com/apk/res-auto">
|
||||
|
||||
<item
|
||||
android:id="@+id/action_add_account"
|
||||
android:icon="@drawable/add_user"
|
||||
android:title="@string/menu_switch_account"
|
||||
app:showAsAction="always" />
|
||||
|
||||
</menu>
|
@ -22,6 +22,14 @@
|
||||
android:visible="false"
|
||||
app:actionViewClass="androidx.appcompat.widget.SearchView"
|
||||
app:showAsAction="ifRoom|collapseActionView" />
|
||||
|
||||
<item
|
||||
android:id="@+id/action_account"
|
||||
android:icon="@drawable/switch_account"
|
||||
android:title="@string/menu_open_home_profile"
|
||||
android:visible="false"
|
||||
app:showAsAction="ifRoom" />
|
||||
|
||||
<item
|
||||
android:id="@+id/action_settings"
|
||||
android:icon="@drawable/setting"
|
||||
|
@ -2,6 +2,12 @@
|
||||
<menu xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
xmlns:app="http://schemas.android.com/apk/res-auto">
|
||||
|
||||
<item
|
||||
android:id="@+id/login_select_account"
|
||||
android:icon="@drawable/switch_account"
|
||||
android:title="@string/menu_open_home_profile"
|
||||
app:showAsAction="ifRoom" />
|
||||
|
||||
<item
|
||||
android:id="@+id/login_setting"
|
||||
android:icon="@drawable/setting"
|
||||
|
@ -9,7 +9,7 @@
|
||||
app:showAsAction="always" />
|
||||
<item
|
||||
android:id="@+id/profile_follow"
|
||||
android:icon="@drawable/follow"
|
||||
android:icon="@drawable/add_user"
|
||||
android:title="@string/menu_follow_user"
|
||||
android:visible="false"
|
||||
app:showAsAction="ifRoom" />
|
||||
|
@ -4,7 +4,7 @@
|
||||
|
||||
<item
|
||||
android:id="@+id/menu_list_add_user"
|
||||
android:icon="@drawable/follow"
|
||||
android:icon="@drawable/add_user"
|
||||
android:title="@string/menu_add_user"
|
||||
android:visible="false"
|
||||
app:actionViewClass="androidx.appcompat.widget.SearchView"
|
||||
|
@ -11,7 +11,7 @@
|
||||
<string name="profile_image">Profilbild</string>
|
||||
<string name="title_settings">Einstellungen</string>
|
||||
<string name="settings_image">Bilder laden</string>
|
||||
<string name="settings_clear_data">App Daten löschen</string>
|
||||
<string name="settings_clear_data">Daten löschen</string>
|
||||
<string name="toolbar_userlist_retweet">Tweet retweetet von</string>
|
||||
<string name="settings_background">Hintergrund</string>
|
||||
<string name="confirm_delete_tweet">Tweet löschen?</string>
|
||||
@ -199,4 +199,6 @@
|
||||
<string name="dialog_link_image_preview">Linkvorschau Bild</string>
|
||||
<string name="dialog_link_close">Linkvorschau schließen</string>
|
||||
<string name="settings_toggle_link_preview">Linkvorschau aktivieren</string>
|
||||
<string name="confirm_remove_account">Account aus der Liste entfernen?</string>
|
||||
<string name="menu_switch_account">Account auswählen</string>
|
||||
</resources>
|
@ -165,7 +165,6 @@
|
||||
<!--dimens of item_image_load.xml-->
|
||||
|
||||
<!--dimens of page_userlist.xml-->
|
||||
<dimen name="userlistpage_toolbar_height">@dimen/toolbar_height</dimen>
|
||||
|
||||
<!--dimens of page_search.xml-->
|
||||
<dimen name="searchpage_toolbar_height">@dimen/toolbar_height</dimen>
|
||||
@ -210,4 +209,10 @@
|
||||
<dimen name="dialog_linkpreview_margin">4dp</dimen>
|
||||
<dimen name="dialog_linkpreview_padding">5dp</dimen>
|
||||
|
||||
<!--dimens of item_login.xml-->
|
||||
<dimen name="login_name_textsize">16sp</dimen>
|
||||
<dimen name="login_layout_padding">8dp</dimen>
|
||||
<dimen name="login_cross_size">36dp</dimen>
|
||||
<dimen name="login_image_size">64dp</dimen>
|
||||
|
||||
</resources>
|
@ -222,5 +222,8 @@
|
||||
<string name="dialog_button_ok">OK</string>
|
||||
<string name="dialog_link_image_preview">Link preview image</string>
|
||||
<string name="dialog_link_close">close link preview</string>
|
||||
<string name="account_page" translatable="false">Accounts</string>
|
||||
<string name="confirm_remove_account">Remove account from list?</string>
|
||||
<string name="menu_switch_account">select account</string>
|
||||
|
||||
</resources>
|
Loading…
x
Reference in New Issue
Block a user