refactor: 用 Kotlin

This commit is contained in:
GoFly233 2020-08-11 16:07:45 +08:00 committed by HuanChengFly
parent 1d15d51726
commit 5f1ed3197d
9 changed files with 752 additions and 827 deletions

View File

@ -13,4 +13,6 @@
## 说明
**本软件及源码仅供学习交流使用,严禁用于商业用途。**
本软件已停止功能性更新。
~~本软件已停止功能性更新。~~
自 2020/8/11 起,本软件单方面由 [GoFly233](https://github.com/GoFly233) 继续开发。

View File

@ -69,7 +69,7 @@ android {
}
compileSdkVersion 29
defaultConfig {
applicationId "com.huanchengfly.tieba.post"
applicationId "top.goforce.tieba.post"
minSdkVersion 21
targetSdkVersion 29
versionCode applicationVersionCode
@ -110,7 +110,7 @@ dependencies {
kapt "com.android.support:support-annotations:28.0.0"
//AndroidX
implementation 'androidx.appcompat:appcompat:1.1.0'
implementation 'androidx.appcompat:appcompat:1.2.0'
implementation 'androidx.constraintlayout:constraintlayout:2.0.0-rc1'
implementation 'androidx.preference:preference:1.1.1'
implementation 'androidx.legacy:legacy-support-v4:1.0.0'
@ -120,6 +120,9 @@ dependencies {
//Test
testImplementation 'junit:junit:4.13'
androidTestImplementation 'androidx.test:core:1.2.0'
androidTestImplementation 'androidx.test.ext:junit:1.1.1'
androidTestImplementation 'androidx.test:rules:1.2.0'
androidTestImplementation 'androidx.test:runner:1.2.0'
androidTestImplementation 'androidx.test.espresso:espresso-core:3.2.0'

View File

@ -1,10 +1,7 @@
package com.huanchengfly.tieba.post;
import android.content.Context;
import androidx.test.InstrumentationRegistry;
import androidx.test.runner.AndroidJUnit4;
import androidx.test.core.app.ApplicationProvider;
import org.junit.Test;
import org.junit.runner.RunWith;
@ -15,12 +12,12 @@ import static org.junit.Assert.assertEquals;
*
* @see <a href="http://d.android.com/tools/testing">Testing documentation</a>
*/
@RunWith(AndroidJUnit4.class)
@RunWith(androidx.test.ext.junit.runners.AndroidJUnit4.class)
public class ExampleInstrumentedTest {
@Test
public void useAppContext() {
// Context of the app under test.
Context appContext = InstrumentationRegistry.getTargetContext();
Context appContext = ApplicationProvider.getApplicationContext();
assertEquals("com.huanchengfly.tieba.post", appContext.getPackageName());
}

View File

@ -1,556 +0,0 @@
package com.huanchengfly.tieba.post;
import android.annotation.SuppressLint;
import android.app.Activity;
import android.app.job.JobInfo;
import android.app.job.JobScheduler;
import android.content.BroadcastReceiver;
import android.content.ComponentName;
import android.content.Context;
import android.content.Intent;
import android.graphics.Typeface;
import android.os.Bundle;
import android.os.Handler;
import android.text.SpannableStringBuilder;
import android.text.Spanned;
import android.text.TextUtils;
import android.text.style.ForegroundColorSpan;
import android.text.style.StyleSpan;
import android.util.Log;
import android.view.LayoutInflater;
import android.view.Menu;
import android.view.MenuItem;
import android.view.View;
import android.widget.FrameLayout;
import android.widget.TextView;
import android.widget.Toast;
import androidx.annotation.NonNull;
import androidx.appcompat.app.AlertDialog;
import androidx.viewpager.widget.ViewPager;
import com.google.android.material.bottomnavigation.BottomNavigationItemView;
import com.google.android.material.bottomnavigation.BottomNavigationMenuView;
import com.google.android.material.bottomnavigation.BottomNavigationView;
import com.google.android.material.snackbar.Snackbar;
import com.huanchengfly.tieba.api.Error;
import com.huanchengfly.tieba.api.LiteApi;
import com.huanchengfly.tieba.api.interfaces.CommonAPICallback;
import com.huanchengfly.tieba.api.interfaces.CommonCallback;
import com.huanchengfly.tieba.api.models.ChangelogBean;
import com.huanchengfly.tieba.api.models.NewUpdateBean;
import com.huanchengfly.tieba.post.activities.NewIntroActivity;
import com.huanchengfly.tieba.post.activities.UpdateInfoActivity;
import com.huanchengfly.tieba.post.activities.base.BaseActivity;
import com.huanchengfly.tieba.post.adapters.MainSearchAdapter;
import com.huanchengfly.tieba.post.adapters.ViewPagerAdapter;
import com.huanchengfly.tieba.post.base.BaseApplication;
import com.huanchengfly.tieba.post.fragments.BaseFragment;
import com.huanchengfly.tieba.post.fragments.ForumListFragment;
import com.huanchengfly.tieba.post.fragments.MessageFragment;
import com.huanchengfly.tieba.post.fragments.MyInfoFragment;
import com.huanchengfly.tieba.post.fragments.PersonalizedFeedFragment;
import com.huanchengfly.tieba.post.interfaces.Refreshable;
import com.huanchengfly.tieba.post.models.MyInfoBean;
import com.huanchengfly.tieba.post.models.database.SearchHistory;
import com.huanchengfly.tieba.post.services.NotifyJobService;
import com.huanchengfly.tieba.post.utils.AccountUtil;
import com.huanchengfly.tieba.post.utils.DialogUtil;
import com.huanchengfly.tieba.post.utils.DisplayUtil;
import com.huanchengfly.tieba.post.utils.HandleBackUtil;
import com.huanchengfly.tieba.post.utils.JobServiceUtil;
import com.huanchengfly.tieba.post.utils.NavigationHelper;
import com.huanchengfly.tieba.post.utils.ReceiverUtil;
import com.huanchengfly.tieba.post.utils.SharedPreferencesUtil;
import com.huanchengfly.tieba.post.utils.ThemeUtil;
import com.huanchengfly.tieba.post.utils.TiebaUtil;
import com.huanchengfly.tieba.post.utils.Util;
import com.huanchengfly.tieba.post.utils.VersionUtil;
import com.huanchengfly.tieba.widgets.MyViewPager;
import com.huanchengfly.tieba.widgets.theme.TintToolbar;
import com.lapism.searchview.Search;
import com.lapism.searchview.widget.SearchView;
import java.util.List;
import static com.huanchengfly.tieba.post.utils.ThemeUtil.THEME_TRANSLUCENT;
public class MainActivity extends BaseActivity implements BottomNavigationView.OnNavigationItemSelectedListener, MainSearchAdapter.OnSearchItemClickListener, BottomNavigationView.OnNavigationItemReselectedListener {
public static final String TAG = "MainActivity";
public static final String SP_SHOULD_SHOW_SNACKBAR = "should_show_snackbar";
private static Handler handler = new Handler();
public ViewPagerAdapter mAdapter = new ViewPagerAdapter(getSupportFragmentManager());
private TintToolbar mToolbar;
private MyViewPager mViewPager;
private BottomNavigationView mBottomNavigationView;
private BottomNavigationMenuView menuView;
private SearchView mSearchView;
private long lastTime = 0;
private NavigationHelper navigationHelper;
private boolean hideExplore;
private TextView badgeTextView;
private BroadcastReceiver newMessageReceiver = new NewMessageReceiver();
private BroadcastReceiver accountSwitchReceiver = new AccountSwitchReceiver();
private FrameLayout appbar;
private MainSearchAdapter mSearchAdapter;
@Override
public void onResume() {
String reason = ThemeUtil.getSharedPreferences(this).getString(ThemeUtil.SP_SWITCH_REASON, null);
boolean followSystemNight = SharedPreferencesUtil.get(this, SharedPreferencesUtil.SP_SETTINGS)
.getBoolean("follow_system_night", false) && !TextUtils.equals(reason, ThemeUtil.REASON_MANUALLY);
if (followSystemNight) {
if (BaseApplication.isSystemNight() && !ThemeUtil.isNightMode(this)) {
SharedPreferencesUtil.put(ThemeUtil.getSharedPreferences(this), SP_SHOULD_SHOW_SNACKBAR, true);
ThemeUtil.switchToNightMode(this, ThemeUtil.REASON_FOLLOW_SYSTEM, false);
} else if (!BaseApplication.isSystemNight() && ThemeUtil.isNightMode(this) && TextUtils.equals(reason, ThemeUtil.REASON_FOLLOW_SYSTEM)) {
SharedPreferencesUtil.put(ThemeUtil.getSharedPreferences(this), SP_SHOULD_SHOW_SNACKBAR, true);
ThemeUtil.switchFromNightMode(this, ThemeUtil.REASON_FOLLOW_SYSTEM, false);
}
}
super.onResume();
refreshSearchView();
ThemeUtil.setTranslucentThemeBackground(findViewById(R.id.background));
if (THEME_TRANSLUCENT.equals(ThemeUtil.getTheme(this))) {
mBottomNavigationView.setElevation(0f);
} else {
mBottomNavigationView.setElevation(DisplayUtil.dp2px(this, 4));
}
}
@Override
public void onNavigationItemReselected(@NonNull MenuItem item) {
BaseFragment fragment = mAdapter.getCurrentFragment();
if (fragment instanceof Refreshable) {
((Refreshable) fragment).onRefresh();
}
}
public void openSearch() {
mSearchView.open(null);
}
@Override
public boolean onNavigationItemSelected(@NonNull MenuItem item) {
switch (item.getItemId()) {
case R.id.navbar_home:
mViewPager.setCurrentItem(0, false);
return true;
case R.id.navbar_explore:
if (!hideExplore) {
mViewPager.setCurrentItem(1, false);
}
return true;
case R.id.navbar_msg:
mViewPager.setCurrentItem(hideExplore ? 1 : 2, false);
return true;
case R.id.navbar_user:
mViewPager.setCurrentItem(hideExplore ? 2 : 3, false);
return true;
}
return false;
}
protected void findView() {
appbar = (FrameLayout) findViewById(R.id.appbar);
mToolbar = (TintToolbar) findViewById(R.id.toolbar);
mSearchView = (SearchView) findViewById(R.id.toolbar_search_view);
mBottomNavigationView = (BottomNavigationView) findViewById(R.id.navbar);
menuView = (BottomNavigationMenuView) mBottomNavigationView.getChildAt(0);
mViewPager = (MyViewPager) findViewById(R.id.mViewPager);
/*
int[][] states = new int[2][];
states[0] = new int[] { android.R.attr.state_checked };
states[1] = new int[] {};
int color = Util.getColorByStyle(this, R.styleable.Theme_colorAccent, R.color.colorAccent);
mBottomNavigationView.setItemIconTintList(new ColorStateList(states, new int[]{color, getLighterColor(color, 0.2f)}));
mBottomNavigationView.setItemTextColor(new ColorStateList(states, new int[]{color, getLighterColor(color, 0.2f)}));
mBottomNavigationView.setLabelVisibilityMode(LabelVisibilityMode.LABEL_VISIBILITY_AUTO);
*/
}
protected void initView() {
mSearchAdapter = new MainSearchAdapter(this);
mSearchAdapter.setOnSearchItemClickListener(this);
mSearchView.setAdapter(mSearchAdapter);
BottomNavigationItemView itemView = (BottomNavigationItemView) menuView.getChildAt(hideExplore ? 1 : 2);
View badge = LayoutInflater.from(MainActivity.this).inflate(R.layout.layout_badge, menuView, false);
itemView.addView(badge);
badgeTextView = badge.findViewById(R.id.tv_msg_count);
navigationHelper = NavigationHelper.newInstance(this);
setSupportActionBar(mToolbar);
hideExplore = getSharedPreferences("settings", MODE_PRIVATE).getBoolean("hideExplore", false);
if (hideExplore) {
mBottomNavigationView.getMenu().removeItem(R.id.navbar_explore);
}
ForumListFragment fragmentHome = new ForumListFragment();
mAdapter.addFragment(fragmentHome);
if (!hideExplore) {
PersonalizedFeedFragment personalizedFeedFragment = new PersonalizedFeedFragment();
mAdapter.addFragment(personalizedFeedFragment);
}
MessageFragment messageFragment = MessageFragment.newInstance(MessageFragment.TYPE_REPLY_ME);
mAdapter.addFragment(messageFragment);
MyInfoFragment fragmentMine = new MyInfoFragment();
mAdapter.addFragment(fragmentMine);
mViewPager.setCanScroll(false);
mViewPager.setAdapter(mAdapter);
mViewPager.setOffscreenPageLimit(mAdapter.getCount());
refreshSearchView();
}
@Override
public void refreshGlobal(Activity activity) {
super.refreshGlobal(activity);
refreshSearchView();
}
protected void refreshSearchView() {
if (mSearchView == null) {
return;
}
mSearchAdapter.refreshData();
mSearchView.setTheme(ThemeUtil.isNightMode(this) || THEME_TRANSLUCENT.equals(ThemeUtil.getTheme(this)) ? Search.Theme.DARK : Search.Theme.LIGHT);
}
protected void initListener() {
mBottomNavigationView.setOnNavigationItemSelectedListener(this);
mBottomNavigationView.setOnNavigationItemReselectedListener(this);
mSearchView.setOnQueryTextListener(new Search.OnQueryTextListener() {
@Override
public void onQueryTextChange(CharSequence newText) {
}
@Override
public boolean onQueryTextSubmit(CharSequence key) {
startActivity(new Intent(MainActivity.this, SearchActivity.class)
.putExtra(SearchActivity.EXTRA_KEYWORD, key.toString()));
new SearchHistory(key.toString())
.saveOrUpdate("content = ?", key.toString());
return true;
}
});
mViewPager.addOnPageChangeListener(new ViewPager.OnPageChangeListener() {
@Override
public void onPageScrolled(int position, float positionOffset, int positionOffsetPixels) {
}
@SuppressLint("RestrictedApi")
@Override
public void onPageSelected(int position) {
BaseFragment baseFragment = mAdapter.getItem(position);
appbar.setVisibility(baseFragment.hasOwnAppbar() ? View.GONE : View.VISIBLE);
mBottomNavigationView.getMenu().getItem(position).setChecked(true);
mToolbar.setTitle(mBottomNavigationView.getMenu().getItem(position).getTitle());
if (position == (hideExplore ? 1 : 2)) {
badgeTextView.setVisibility(View.GONE);
}
}
@Override
public void onPageScrollStateChanged(int state) {
}
});
}
@SuppressLint("ApplySharedPref")
protected void clearSwitchReason() {
if (TextUtils.equals(ThemeUtil.getSharedPreferences(this).getString(ThemeUtil.SP_SWITCH_REASON, null), ThemeUtil.REASON_MANUALLY)) {
ThemeUtil.getSharedPreferences(this).edit().remove(ThemeUtil.SP_SWITCH_REASON).commit();
}
}
protected boolean shouldShowSwitchSnackbar() {
return ThemeUtil.getSharedPreferences(this).getBoolean(SP_SHOULD_SHOW_SNACKBAR, false);
}
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setSwipeBackEnable(false);
setContentView(R.layout.activity_main);
ThemeUtil.setTranslucentThemeBackground(findViewById(R.id.background));
findView();
initView();
initListener();
if (!SharedPreferencesUtil.get(SharedPreferencesUtil.SP_APP_DATA).getBoolean("notice_dialog", false)) {
showDialog(DialogUtil.build(this)
.setTitle(R.string.title_dialog_notice)
.setMessage(R.string.message_dialog_notice)
.setPositiveButton(R.string.button_sure_default, (dialog, which) -> SharedPreferencesUtil.put(this, SharedPreferencesUtil.SP_APP_DATA, "notice_dialog", true))
.setCancelable(false)
.create());
}
if (savedInstanceState == null) {
clearSwitchReason();
}
if (shouldShowSwitchSnackbar()) {
Util.createSnackbar(mViewPager, ThemeUtil.isNightMode(this) ? R.string.snackbar_auto_switch_to_night : R.string.snackbar_auto_switch_from_night, Snackbar.LENGTH_SHORT)
.show();
SharedPreferencesUtil.put(ThemeUtil.getSharedPreferences(this), SP_SHOULD_SHOW_SNACKBAR, false);
}
handler.postDelayed(() -> {
checkUpdate();
try {
TiebaUtil.initAutoSign(this);
} catch (Exception e) {
e.printStackTrace();
}
if (AccountUtil.isLoggedIn(this) && AccountUtil.getCookie(this) == null) {
showDialog(DialogUtil.build(this)
.setTitle(R.string.title_dialog_update_stoken)
.setMessage(R.string.message_dialog_update_stoken)
.setPositiveButton(R.string.button_sure_default, (dialog, which) -> startActivity(UpdateInfoActivity.newIntent(this, UpdateInfoActivity.ACTION_UPDATE_LOGIN_INFO)))
.setCancelable(false)
.create());
}
AccountUtil.updateUserInfo(this, new CommonCallback<MyInfoBean>() {
@Override
public void onSuccess(MyInfoBean data) {
}
@Override
public void onFailure(int code, String error) {
if (code == Error.ERROR_LOGGED_IN_EXPIRED) {
showDialog(DialogUtil.build(MainActivity.this)
.setTitle(R.string.title_dialog_logged_in_expired)
.setMessage(R.string.message_dialog_logged_in_expired)
.setPositiveButton(R.string.button_ok, (dialog, which) -> {
navigationHelper.navigationByData(NavigationHelper.ACTION_LOGIN);
})
.setCancelable(false)
.create());
}
}
});
}, 1000);
if (BaseApplication.isFirstRun()) {
startActivity(new Intent(this, NewIntroActivity.class));
} else if (!AccountUtil.isLoggedIn(this)) {
navigationHelper.navigationByData(NavigationHelper.ACTION_LOGIN);
}
/*
handler.postDelayed(() -> {
try {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.Q) {
String relativePath = Environment.DIRECTORY_PICTURES + File.separator + "Tieba Lite" + File.separator + "shareTemp";
String where = MediaStore.Images.Media.RELATIVE_PATH + " like \"" + relativePath + "%" + "\"";
int i = getContentResolver().delete(MediaStore.Images.Media.EXTERNAL_CONTENT_URI, where, null);
} else {
if (AndPermission.hasPermissions(this, Permission.Group.STORAGE)) {
File shareTemp = new File(Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_PICTURES).getAbsoluteFile(), "Tieba Lite" + File.separator + "shareTemp");
if (shareTemp.exists() && shareTemp.delete()) {
FileUtil.deleteAllFiles(shareTemp);
}
}
}
} catch (Exception e) {
e.printStackTrace();
}
}, 100);
*/
}
@Override
public void recreate() {
super.recreate();
Log.i(TAG, "recreate: ");
}
@Override
protected void onStart() {
super.onStart();
registerReceiver(newMessageReceiver, ReceiverUtil.createIntentFilter(NotifyJobService.ACTION_NEW_MESSAGE));
registerReceiver(accountSwitchReceiver, ReceiverUtil.createIntentFilter(AccountUtil.ACTION_SWITCH_ACCOUNT));
try {
startService(new Intent(this, NotifyJobService.class));
JobInfo.Builder builder = new JobInfo.Builder(JobServiceUtil.getJobId(this), new ComponentName(this, NotifyJobService.class))
.setPersisted(true)
.setPeriodic(30 * 60 * 1000L)
.setRequiredNetworkType(JobInfo.NETWORK_TYPE_ANY);
JobScheduler jobScheduler = (JobScheduler) getSystemService(Context.JOB_SCHEDULER_SERVICE);
if (jobScheduler != null) jobScheduler.schedule(builder.build());
} catch (Exception ignored) {
}
}
@Override
protected void onStop() {
try {
stopService(new Intent(this, NotifyJobService.class));
} catch (Exception ignored) {
}
unregisterReceiver(newMessageReceiver);
unregisterReceiver(accountSwitchReceiver);
super.onStop();
}
private void checkUpdate() {
int oldVersion = SharedPreferencesUtil.get(this, SharedPreferencesUtil.SP_APP_DATA).getInt("version", -1);
if (oldVersion < VersionUtil.getVersionCode(this)) {
LiteApi.getInstance().changelog(new CommonAPICallback<ChangelogBean>() {
@Override
public void onSuccess(ChangelogBean data) {
SharedPreferencesUtil.get(MainActivity.this, SharedPreferencesUtil.SP_APP_DATA)
.edit()
.putInt("version", VersionUtil.getVersionCode(MainActivity.this))
.apply();
if (!TextUtils.isEmpty(data.getResult())) {
showDialog(DialogUtil.build(MainActivity.this)
.setTitle(R.string.title_dialog_changelog)
.setMessage(data.getResult())
.setPositiveButton(R.string.button_ok, null)
.create());
}
}
@Override
public void onFailure(int code, String error) {
}
});
}
LiteApi.getInstance().newCheckUpdate(new CommonAPICallback<NewUpdateBean>() {
@Override
public void onSuccess(NewUpdateBean data) {
if (data.isHasUpdate()) {
boolean cancelable = data.getResult().isCancelable();
boolean ignored = SharedPreferencesUtil.get(MainActivity.this, SharedPreferencesUtil.SP_IGNORE_VERSIONS)
.getBoolean(data.getResult().getVersionName() + "_" + data.getResult().getVersionCode(), false);
if (ignored && cancelable) {
return;
}
SpannableStringBuilder builder = new SpannableStringBuilder();
if (data.getResult().getVersionType() == 1) {
String betaTip = getString(R.string.tip_beta_version);
builder.append(betaTip, new ForegroundColorSpan(getResources().getColor(R.color.red)), Spanned.SPAN_EXCLUSIVE_EXCLUSIVE);
builder.setSpan(new StyleSpan(Typeface.BOLD), 0, betaTip.length(), Spanned.SPAN_EXCLUSIVE_EXCLUSIVE);
}
for (String content : data.getResult().getUpdateContent()) {
builder.append(content);
builder.append("\n");
}
AlertDialog.Builder dialogBuilder = DialogUtil.build(MainActivity.this)
.setTitle(getString(R.string.title_dialog_update, data.getResult().getVersionName()))
.setMessage(builder)
.setPositiveButton(R.string.button_go_to_download, (dialog, which) -> {
VersionUtil.showDownloadDialog(MainActivity.this, data.getResult());
})
.setCancelable(cancelable);
if (cancelable) {
dialogBuilder.setNegativeButton(R.string.button_next_time, null);
dialogBuilder.setNeutralButton(R.string.button_ignore_this_version, (dialog, which) -> SharedPreferencesUtil.get(MainActivity.this, SharedPreferencesUtil.SP_IGNORE_VERSIONS)
.edit()
.putBoolean(data.getResult().getVersionName() + "_" + data.getResult().getVersionCode(), true)
.apply());
}
showDialog(dialogBuilder.create());
}
}
@Override
public void onFailure(int code, String error) {
}
});
}
@Override
public boolean onCreateOptionsMenu(Menu menu) {
getMenuInflater().inflate(R.menu.toolbar_menu, menu);
return super.onCreateOptionsMenu(menu);
}
@Override
public boolean onOptionsItemSelected(MenuItem item) {
switch (item.getItemId()) {
case R.id.menu_sign:
TiebaUtil.startSign(MainActivity.this);
return true;
case R.id.action_search:
mSearchView.open(item);
return true;
}
return super.onOptionsItemSelected(item);
}
@Override
public void onBackPressed() {
if (mSearchView.isOpen()) {
mSearchView.close();
} else {
if (!HandleBackUtil.handleBackPress(this)) {
exit();
}
}
}
public void exit(boolean isDouble) {
if (!isDouble || System.currentTimeMillis() - lastTime < 2000) {
exitApplication();
} else {
lastTime = System.currentTimeMillis();
Toast.makeText(this, R.string.toast_double_key_exit, Toast.LENGTH_SHORT).show();
}
}
public void exit() {
exit(true);
}
@Override
public void setTitle(String newTitle) {
mToolbar.setTitle(newTitle);
}
@Override
public void onSearchItemClick(int position, CharSequence content) {
startActivity(new Intent(MainActivity.this, SearchActivity.class)
.putExtra(SearchActivity.EXTRA_KEYWORD, content.toString()));
new SearchHistory(content.toString())
.saveOrUpdate("content = ?", content.toString());
refreshSearchView();
}
private class NewMessageReceiver extends BroadcastReceiver {
@SuppressLint("RestrictedApi")
@Override
public void onReceive(Context context, Intent intent) {
try {
String action = intent.getAction();
if (action != null && action.equals(NotifyJobService.ACTION_NEW_MESSAGE)) {
String channel = intent.getStringExtra("channel");
int count = intent.getIntExtra("count", 0);
if (channel != null && channel.equals(NotifyJobService.CHANNEL_TOTAL) && badgeTextView != null) {
badgeTextView.setText(String.valueOf(count));
if (count > 0) {
badgeTextView.setVisibility(View.VISIBLE);
}
}
}
} catch (Exception ignored) {
}
}
}
private class AccountSwitchReceiver extends BroadcastReceiver {
@Override
public void onReceive(Context context, Intent intent) {
String action = intent.getAction();
if (action != null && action.equals(AccountUtil.ACTION_SWITCH_ACCOUNT)) {
if (mAdapter == null) {
return;
}
List<BaseFragment> fragments = mAdapter.getFragments();
for (BaseFragment fragment : fragments) {
if (fragment != null) {
try {
fragment.onAccountSwitch();
} catch (Exception e) {
e.printStackTrace();
}
}
}
}
}
}
}

View File

@ -0,0 +1,509 @@
package com.huanchengfly.tieba.post
import android.annotation.SuppressLint
import android.app.Activity
import android.app.job.JobInfo
import android.app.job.JobScheduler
import android.content.*
import android.graphics.Typeface
import android.os.Bundle
import android.os.Handler
import android.text.SpannableStringBuilder
import android.text.Spanned
import android.text.TextUtils
import android.text.style.ForegroundColorSpan
import android.text.style.StyleSpan
import android.util.Log
import android.view.LayoutInflater
import android.view.Menu
import android.view.MenuItem
import android.view.View
import android.widget.FrameLayout
import android.widget.TextView
import android.widget.Toast
import androidx.viewpager.widget.ViewPager.OnPageChangeListener
import com.google.android.material.bottomnavigation.BottomNavigationItemView
import com.google.android.material.bottomnavigation.BottomNavigationMenuView
import com.google.android.material.bottomnavigation.BottomNavigationView
import com.google.android.material.bottomnavigation.BottomNavigationView.OnNavigationItemReselectedListener
import com.google.android.material.snackbar.Snackbar
import com.huanchengfly.tieba.api.Error
import com.huanchengfly.tieba.api.LiteApi.Companion.instance
import com.huanchengfly.tieba.api.interfaces.CommonAPICallback
import com.huanchengfly.tieba.api.interfaces.CommonCallback
import com.huanchengfly.tieba.api.models.ChangelogBean
import com.huanchengfly.tieba.api.models.NewUpdateBean
import com.huanchengfly.tieba.post.activities.NewIntroActivity
import com.huanchengfly.tieba.post.activities.UpdateInfoActivity
import com.huanchengfly.tieba.post.activities.base.BaseActivity
import com.huanchengfly.tieba.post.adapters.MainSearchAdapter
import com.huanchengfly.tieba.post.adapters.ViewPagerAdapter
import com.huanchengfly.tieba.post.base.BaseApplication
import com.huanchengfly.tieba.post.fragments.ForumListFragment
import com.huanchengfly.tieba.post.fragments.MessageFragment
import com.huanchengfly.tieba.post.fragments.MyInfoFragment
import com.huanchengfly.tieba.post.fragments.PersonalizedFeedFragment
import com.huanchengfly.tieba.post.interfaces.Refreshable
import com.huanchengfly.tieba.post.models.MyInfoBean
import com.huanchengfly.tieba.post.models.database.SearchHistory
import com.huanchengfly.tieba.post.services.NotifyJobService
import com.huanchengfly.tieba.post.utils.*
import com.huanchengfly.tieba.widgets.MyViewPager
import com.huanchengfly.tieba.widgets.theme.TintToolbar
import com.lapism.searchview.Search
import com.lapism.searchview.widget.SearchView
open class MainActivity : BaseActivity(), BottomNavigationView.OnNavigationItemSelectedListener, MainSearchAdapter.OnSearchItemClickListener, OnNavigationItemReselectedListener {
var mAdapter: ViewPagerAdapter? = ViewPagerAdapter(supportFragmentManager)
private var mToolbar: TintToolbar? = null
private var mViewPager: MyViewPager? = null
private var mBottomNavigationView: BottomNavigationView? = null
private var menuView: BottomNavigationMenuView? = null
private var mSearchView: SearchView? = null
private var lastTime: Long = 0
private var navigationHelper: NavigationHelper? = null
private var hideExplore = false
private var badgeTextView: TextView? = null
private val newMessageReceiver: BroadcastReceiver = NewMessageReceiver()
private val accountSwitchReceiver: BroadcastReceiver = AccountSwitchReceiver()
private var appbar: FrameLayout? = null
private var mSearchAdapter: MainSearchAdapter? = null
public override fun onResume() {
val reason = ThemeUtil.getSharedPreferences(this).getString(ThemeUtil.SP_SWITCH_REASON, null)
val followSystemNight = SharedPreferencesUtil.get(this, SharedPreferencesUtil.SP_SETTINGS)
.getBoolean("follow_system_night", false) && !TextUtils.equals(reason, ThemeUtil.REASON_MANUALLY)
if (followSystemNight) {
if (BaseApplication.isSystemNight() && !ThemeUtil.isNightMode(this)) {
SharedPreferencesUtil.put(ThemeUtil.getSharedPreferences(this), SP_SHOULD_SHOW_SNACKBAR, true)
ThemeUtil.switchToNightMode(this, ThemeUtil.REASON_FOLLOW_SYSTEM, false)
} else if (!BaseApplication.isSystemNight() && ThemeUtil.isNightMode(this) && TextUtils.equals(reason, ThemeUtil.REASON_FOLLOW_SYSTEM)) {
SharedPreferencesUtil.put(ThemeUtil.getSharedPreferences(this), SP_SHOULD_SHOW_SNACKBAR, true)
ThemeUtil.switchFromNightMode(this, ThemeUtil.REASON_FOLLOW_SYSTEM, false)
}
}
super.onResume()
refreshSearchView()
ThemeUtil.setTranslucentThemeBackground(findViewById(R.id.background))
if (ThemeUtil.THEME_TRANSLUCENT == ThemeUtil.getTheme(this)) {
mBottomNavigationView!!.elevation = 0f
} else {
mBottomNavigationView!!.elevation = DisplayUtil.dp2px(this, 4f).toFloat()
}
}
override fun onNavigationItemReselected(item: MenuItem) {
val fragment = mAdapter!!.currentFragment
if (fragment is Refreshable) {
(fragment as Refreshable).onRefresh()
}
}
fun openSearch() {
mSearchView!!.open(null)
}
override fun onNavigationItemSelected(item: MenuItem): Boolean {
when (item.itemId) {
R.id.navbar_home -> {
mViewPager!!.setCurrentItem(0, false)
return true
}
R.id.navbar_explore -> {
if (!hideExplore) {
mViewPager!!.setCurrentItem(1, false)
}
return true
}
R.id.navbar_msg -> {
mViewPager!!.setCurrentItem(if (hideExplore) 1 else 2, false)
return true
}
R.id.navbar_user -> {
mViewPager!!.setCurrentItem(if (hideExplore) 2 else 3, false)
return true
}
}
return false
}
private fun findView() {
appbar = findViewById(R.id.appbar) as FrameLayout
mToolbar = findViewById(R.id.toolbar) as TintToolbar
mSearchView = findViewById(R.id.toolbar_search_view) as SearchView
mBottomNavigationView = findViewById(R.id.navbar) as BottomNavigationView
menuView = mBottomNavigationView!!.getChildAt(0) as BottomNavigationMenuView
mViewPager = findViewById(R.id.mViewPager) as MyViewPager
/*
int[][] states = new int[2][];
states[0] = new int[] { android.R.attr.state_checked };
states[1] = new int[] {};
int color = Util.getColorByStyle(this, R.styleable.Theme_colorAccent, R.color.colorAccent);
mBottomNavigationView.setItemIconTintList(new ColorStateList(states, new int[]{color, getLighterColor(color, 0.2f)}));
mBottomNavigationView.setItemTextColor(new ColorStateList(states, new int[]{color, getLighterColor(color, 0.2f)}));
mBottomNavigationView.setLabelVisibilityMode(LabelVisibilityMode.LABEL_VISIBILITY_AUTO);
*/
}
protected fun initView() {
mSearchAdapter = MainSearchAdapter(this)
mSearchAdapter!!.onSearchItemClickListener = this
mSearchView!!.adapter = mSearchAdapter
val itemView = menuView!!.getChildAt(if (hideExplore) 1 else 2) as BottomNavigationItemView
val badge = LayoutInflater.from(this@MainActivity).inflate(R.layout.layout_badge, menuView, false)
itemView.addView(badge)
badgeTextView = badge.findViewById(R.id.tv_msg_count)
navigationHelper = NavigationHelper.newInstance(this)
setSupportActionBar(mToolbar)
hideExplore = getSharedPreferences("settings", Context.MODE_PRIVATE).getBoolean("hideExplore", false)
if (hideExplore) {
mBottomNavigationView!!.menu.removeItem(R.id.navbar_explore)
}
val fragmentHome = ForumListFragment()
mAdapter!!.addFragment(fragmentHome)
if (!hideExplore) {
val personalizedFeedFragment = PersonalizedFeedFragment()
mAdapter!!.addFragment(personalizedFeedFragment)
}
val messageFragment = MessageFragment.newInstance(MessageFragment.TYPE_REPLY_ME)
mAdapter!!.addFragment(messageFragment)
val fragmentMine = MyInfoFragment()
mAdapter!!.addFragment(fragmentMine)
mViewPager!!.isCanScroll = false
mViewPager!!.adapter = mAdapter
mViewPager!!.offscreenPageLimit = mAdapter!!.count
refreshSearchView()
}
override fun refreshGlobal(activity: Activity) {
super.refreshGlobal(activity)
refreshSearchView()
}
private fun refreshSearchView() {
if (mSearchView == null) {
return
}
mSearchAdapter!!.refreshData()
mSearchView!!.theme = if (ThemeUtil.isNightMode(this) || ThemeUtil.THEME_TRANSLUCENT == ThemeUtil.getTheme(this)) Search.Theme.DARK else Search.Theme.LIGHT
}
protected fun initListener() {
mBottomNavigationView!!.setOnNavigationItemSelectedListener(this)
mBottomNavigationView!!.setOnNavigationItemReselectedListener(this)
mSearchView!!.setOnQueryTextListener(object : Search.OnQueryTextListener {
override fun onQueryTextChange(newText: CharSequence) {}
override fun onQueryTextSubmit(key: CharSequence): Boolean {
startActivity(Intent(this@MainActivity, SearchActivity::class.java)
.putExtra(SearchActivity.EXTRA_KEYWORD, key.toString()))
SearchHistory(key.toString())
.saveOrUpdate("content = ?", key.toString())
return true
}
})
mViewPager!!.addOnPageChangeListener(object : OnPageChangeListener {
override fun onPageScrolled(position: Int, positionOffset: Float, positionOffsetPixels: Int) {}
@SuppressLint("RestrictedApi")
override fun onPageSelected(position: Int) {
val baseFragment = mAdapter!!.getItem(position)
appbar!!.visibility = if (baseFragment.hasOwnAppbar()) View.GONE else View.VISIBLE
mBottomNavigationView!!.menu.getItem(position).isChecked = true
mToolbar!!.title = mBottomNavigationView!!.menu.getItem(position).title
if (position == (if (hideExplore) 1 else 2)) {
badgeTextView!!.visibility = View.GONE
}
}
override fun onPageScrollStateChanged(state: Int) {}
})
}
@SuppressLint("ApplySharedPref")
protected fun clearSwitchReason() {
if (TextUtils.equals(ThemeUtil.getSharedPreferences(this).getString(ThemeUtil.SP_SWITCH_REASON, null), ThemeUtil.REASON_MANUALLY)) {
ThemeUtil.getSharedPreferences(this).edit().remove(ThemeUtil.SP_SWITCH_REASON).commit()
}
}
protected fun shouldShowSwitchSnackbar(): Boolean {
return ThemeUtil.getSharedPreferences(this).getBoolean(SP_SHOULD_SHOW_SNACKBAR, false)
}
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setSwipeBackEnable(false)
setContentView(R.layout.activity_main)
ThemeUtil.setTranslucentThemeBackground(findViewById(R.id.background))
findView()
initView()
initListener()
if (!SharedPreferencesUtil.get(SharedPreferencesUtil.SP_APP_DATA).getBoolean("notice_dialog", false)) {
showDialog(DialogUtil.build(this)
.setTitle(R.string.title_dialog_notice)
.setMessage(R.string.message_dialog_notice)
.setPositiveButton(R.string.button_sure_default) { _: DialogInterface?,
_: Int ->
SharedPreferencesUtil.put(this, SharedPreferencesUtil.SP_APP_DATA, "notice_dialog", true)
}
.setCancelable(false)
.create())
}
if (savedInstanceState == null) {
clearSwitchReason()
}
if (shouldShowSwitchSnackbar()) {
Util.createSnackbar(mViewPager!!, if (ThemeUtil.isNightMode(this)) R.string.snackbar_auto_switch_to_night else R.string.snackbar_auto_switch_from_night, Snackbar.LENGTH_SHORT)
.show()
SharedPreferencesUtil.put(ThemeUtil.getSharedPreferences(this), SP_SHOULD_SHOW_SNACKBAR, false)
}
handler.postDelayed({
checkUpdate()
try {
TiebaUtil.initAutoSign(this)
} catch (e: Exception) {
e.printStackTrace()
}
if (AccountUtil.isLoggedIn(this) && AccountUtil.getCookie(this) == null) {
showDialog(DialogUtil.build(this)
.setTitle(R.string.title_dialog_update_stoken)
.setMessage(R.string.message_dialog_update_stoken)
.setPositiveButton(R.string.button_sure_default) { _: DialogInterface?, _: Int -> startActivity(UpdateInfoActivity.newIntent(this, UpdateInfoActivity.ACTION_UPDATE_LOGIN_INFO)) }
.setCancelable(false)
.create())
}
AccountUtil.updateUserInfo(this, object : CommonCallback<MyInfoBean?> {
override fun onSuccess(data: MyInfoBean?) {}
override fun onFailure(code: Int, error: String) {
if (code == Error.ERROR_LOGGED_IN_EXPIRED) {
showDialog(DialogUtil.build(this@MainActivity)
.setTitle(R.string.title_dialog_logged_in_expired)
.setMessage(R.string.message_dialog_logged_in_expired)
.setPositiveButton(R.string.button_ok) { _: DialogInterface?, _: Int -> navigationHelper!!.navigationByData(NavigationHelper.ACTION_LOGIN) }
.setCancelable(false)
.create())
}
}
})
}, 1000)
if (BaseApplication.isFirstRun()) {
startActivity(Intent(this, NewIntroActivity::class.java))
} else if (!AccountUtil.isLoggedIn(this)) {
navigationHelper!!.navigationByData(NavigationHelper.ACTION_LOGIN)
}
/*
handler.postDelayed(() -> {
try {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.Q) {
String relativePath = Environment.DIRECTORY_PICTURES + File.separator + "Tieba Lite" + File.separator + "shareTemp";
String where = MediaStore.Images.Media.RELATIVE_PATH + " like \"" + relativePath + "%" + "\"";
int i = getContentResolver().delete(MediaStore.Images.Media.EXTERNAL_CONTENT_URI, where, null);
} else {
if (AndPermission.hasPermissions(this, Permission.Group.STORAGE)) {
File shareTemp = new File(Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_PICTURES).getAbsoluteFile(), "Tieba Lite" + File.separator + "shareTemp");
if (shareTemp.exists() && shareTemp.delete()) {
FileUtil.deleteAllFiles(shareTemp);
}
}
}
} catch (Exception e) {
e.printStackTrace();
}
}, 100);
*/
}
override fun recreate() {
super.recreate()
Log.i(TAG, "recreate: ")
}
override fun onStart() {
super.onStart()
registerReceiver(newMessageReceiver, ReceiverUtil.createIntentFilter(NotifyJobService.ACTION_NEW_MESSAGE))
registerReceiver(accountSwitchReceiver, ReceiverUtil.createIntentFilter(AccountUtil.ACTION_SWITCH_ACCOUNT))
try {
startService(Intent(this, NotifyJobService::class.java))
val builder = JobInfo.Builder(JobServiceUtil.getJobId(this), ComponentName(this, NotifyJobService::class.java))
.setPersisted(true)
.setPeriodic(30 * 60 * 1000L)
.setRequiredNetworkType(JobInfo.NETWORK_TYPE_ANY)
val jobScheduler = getSystemService(Context.JOB_SCHEDULER_SERVICE) as JobScheduler
jobScheduler.schedule(builder.build())
} catch (ignored: Exception) {
}
}
override fun onStop() {
try {
stopService(Intent(this, NotifyJobService::class.java))
} catch (ignored: Exception) {
}
unregisterReceiver(newMessageReceiver)
unregisterReceiver(accountSwitchReceiver)
super.onStop()
}
private fun checkUpdate() {
val oldVersion = SharedPreferencesUtil.get(this, SharedPreferencesUtil.SP_APP_DATA).getInt("version", -1)
if (oldVersion < VersionUtil.getVersionCode(this)) {
instance!!.changelog(object : CommonAPICallback<ChangelogBean?> {
override fun onSuccess(data: ChangelogBean?) {
SharedPreferencesUtil.get(this@MainActivity, SharedPreferencesUtil.SP_APP_DATA)
.edit()
.putInt("version", VersionUtil.getVersionCode(this@MainActivity))
.apply()
if (data != null) {
if (!TextUtils.isEmpty(data.result)) {
showDialog(DialogUtil.build(this@MainActivity)
.setTitle(R.string.title_dialog_changelog)
.setMessage(data.result)
.setPositiveButton(R.string.button_ok, null)
.create())
}
}
}
override fun onFailure(code: Int, error: String) {}
})
}
instance!!.newCheckUpdate(object : CommonAPICallback<NewUpdateBean?> {
override fun onSuccess(data: NewUpdateBean?) {
if (data != null) {
if (data.isHasUpdate) {
val cancelable = data.result.isCancelable
val ignored = SharedPreferencesUtil.get(this@MainActivity, SharedPreferencesUtil.SP_IGNORE_VERSIONS)
.getBoolean(data.result.versionName + "_" + data.result.versionCode, false)
if (ignored && cancelable) {
return
}
val builder = SpannableStringBuilder()
if (data.result.versionType == 1) {
val betaTip = getString(R.string.tip_beta_version)
builder.append(betaTip, ForegroundColorSpan(resources.getColor(R.color.red, null)), Spanned.SPAN_EXCLUSIVE_EXCLUSIVE)
builder.setSpan(StyleSpan(Typeface.BOLD), 0, betaTip.length, Spanned.SPAN_EXCLUSIVE_EXCLUSIVE)
}
for (content in data.result.updateContent) {
builder.append(content)
builder.append("\n")
}
val dialogBuilder = DialogUtil.build(this@MainActivity)
.setTitle(getString(R.string.title_dialog_update, data.result.versionName))
.setMessage(builder)
.setPositiveButton(R.string.button_go_to_download) { _: DialogInterface?, _: Int -> VersionUtil.showDownloadDialog(this@MainActivity, data.result) }
.setCancelable(cancelable)
if (cancelable) {
dialogBuilder.setNegativeButton(R.string.button_next_time, null)
dialogBuilder.setNeutralButton(R.string.button_ignore_this_version) { _: DialogInterface?, _: Int ->
SharedPreferencesUtil.get(this@MainActivity, SharedPreferencesUtil.SP_IGNORE_VERSIONS)
.edit()
.putBoolean(data.result.versionName + "_" + data.result.versionCode, true)
.apply()
}
}
showDialog(dialogBuilder.create())
}
}
}
override fun onFailure(code: Int, error: String) {}
})
}
override fun onCreateOptionsMenu(menu: Menu): Boolean {
menuInflater.inflate(R.menu.toolbar_menu, menu)
return super.onCreateOptionsMenu(menu)
}
override fun onOptionsItemSelected(item: MenuItem): Boolean {
when (item.itemId) {
R.id.menu_sign -> {
TiebaUtil.startSign(this@MainActivity)
return true
}
R.id.action_search -> {
mSearchView!!.open(item)
return true
}
}
return super.onOptionsItemSelected(item)
}
override fun onBackPressed() {
if (mSearchView!!.isOpen) {
mSearchView!!.close()
} else {
if (!HandleBackUtil.handleBackPress(this)) {
exit()
}
}
}
@JvmOverloads
fun exit(isDouble: Boolean = true) {
if (!isDouble || System.currentTimeMillis() - lastTime < 2000) {
exitApplication()
} else {
lastTime = System.currentTimeMillis()
Toast.makeText(this, R.string.toast_double_key_exit, Toast.LENGTH_SHORT).show()
}
}
override fun setTitle(newTitle: String) {
mToolbar!!.title = newTitle
}
override fun onSearchItemClick(position: Int, content: CharSequence) {
startActivity(Intent(this@MainActivity, SearchActivity::class.java)
.putExtra(SearchActivity.EXTRA_KEYWORD, content.toString()))
SearchHistory(content.toString())
.saveOrUpdate("content = ?", content.toString())
refreshSearchView()
}
private inner class NewMessageReceiver : BroadcastReceiver() {
@SuppressLint("RestrictedApi")
override fun onReceive(context: Context, intent: Intent) {
try {
val action = intent.action
if (action != null && action == NotifyJobService.ACTION_NEW_MESSAGE) {
val channel = intent.getStringExtra("channel")
val count = intent.getIntExtra("count", 0)
if (channel != null && channel == NotifyJobService.CHANNEL_TOTAL && badgeTextView != null) {
badgeTextView!!.text = count.toString()
if (count > 0) {
badgeTextView!!.visibility = View.VISIBLE
}
}
}
} catch (ignored: Exception) {
}
}
}
private inner class AccountSwitchReceiver : BroadcastReceiver() {
override fun onReceive(context: Context, intent: Intent) {
val action = intent.action
if (action != null && action == AccountUtil.ACTION_SWITCH_ACCOUNT) {
if (mAdapter == null) {
return
}
val fragments = mAdapter!!.fragments
for (fragment in fragments) {
if (fragment != null) {
try {
fragment.onAccountSwitch()
} catch (e: Exception) {
e.printStackTrace()
}
}
}
}
}
}
companion object {
const val TAG = "MainActivity"
const val SP_SHOULD_SHOW_SNACKBAR = "should_show_snackbar"
private val handler = Handler()
}
}

View File

@ -1,234 +0,0 @@
package com.huanchengfly.tieba.post.fragments;
import android.annotation.SuppressLint;
import android.content.Intent;
import android.os.Build;
import android.os.Bundle;
import android.view.View;
import android.widget.Toast;
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import androidx.core.content.ContextCompat;
import androidx.preference.EditTextPreference;
import androidx.preference.ListPreference;
import androidx.preference.Preference;
import androidx.preference.SwitchPreference;
import com.google.android.material.snackbar.Snackbar;
import com.huanchengfly.theme.utils.ThemeUtils;
import com.huanchengfly.tieba.api.LiteApi;
import com.huanchengfly.tieba.api.interfaces.CommonAPICallback;
import com.huanchengfly.tieba.api.models.NewUpdateBean;
import com.huanchengfly.tieba.post.R;
import com.huanchengfly.tieba.post.activities.BlockListActivity;
import com.huanchengfly.tieba.post.activities.LoginActivity;
import com.huanchengfly.tieba.post.components.prefs.TimePickerPreference;
import com.huanchengfly.tieba.post.models.database.Account;
import com.huanchengfly.tieba.post.models.database.Block;
import com.huanchengfly.tieba.post.utils.AccountUtil;
import com.huanchengfly.tieba.post.utils.DialogUtil;
import com.huanchengfly.tieba.post.utils.DisplayUtil;
import com.huanchengfly.tieba.post.utils.TiebaUtil;
import com.huanchengfly.tieba.post.utils.Util;
import com.huanchengfly.tieba.post.utils.VersionUtil;
import com.huanchengfly.utils.GlideCacheUtil;
import com.lapism.searchview.database.SearchHistoryTable;
import java.util.ArrayList;
import java.util.List;
public class SettingsFragment extends PreferencesFragment {
public static final String TAG = "SettingsFragment";
private Account loginInfo;
public SettingsFragment() {
}
@Override
public void onResume() {
super.onResume();
refresh();
}
private void refresh() {
loginInfo = AccountUtil.getLoginInfo(getAttachContext());
List<Account> accounts = AccountUtil.getAllAccounts();
List<String> usernameList = new ArrayList<>();
List<String> idList = new ArrayList<>();
for (Account account : accounts) {
usernameList.add(account.getNameShow());
idList.add(String.valueOf(account.getId()));
}
ListPreference accountsPreference = findPreference("switch_account");
accountsPreference.setEntries(usernameList.toArray(new String[0]));
accountsPreference.setEntryValues(idList.toArray(new String[0]));
if (loginInfo != null) {
accountsPreference.setValue(String.valueOf(loginInfo.getId()));
accountsPreference.setSummary("已登录账号 " + loginInfo.getNameShow());
} else {
accountsPreference.setSummary("未登录");
}
}
@SuppressLint("ApplySharedPref")
@Override
public void onCreatePreferences(Bundle savedInstanceState, String rootKey) {
getPreferenceManager().setSharedPreferencesName("settings");
addPreferencesFromResource(R.xml.preferences);
ListPreference accountsPreference = findPreference("switch_account");
accountsPreference.setOnPreferenceChangeListener((preference, newValue) -> {
if (AccountUtil.switchUser(getAttachContext(), Integer.valueOf((String) newValue))) {
refresh();
Toast.makeText(getAttachContext(), R.string.toast_switch_success, Toast.LENGTH_SHORT).show();
}
return false;
});
findPreference("copy_bduss").setOnPreferenceClickListener(preference -> {
Account account = AccountUtil.getLoginInfo(getAttachContext());
if (account != null) {
TiebaUtil.copyText(getAttachContext(), account.getBduss());
}
return true;
});
findPreference("clear_search_history").setOnPreferenceClickListener(preference -> {
new SearchHistoryTable(getAttachContext()).clearDatabase();
if (getView() != null)
Util.createSnackbar(getView(), R.string.toast_clear_success, Snackbar.LENGTH_SHORT).show();
return true;
});
findPreference("exit_account").setEnabled(AccountUtil.isLoggedIn(getAttachContext()));
findPreference("exit_account").setOnPreferenceClickListener(preference -> {
DialogUtil.build(getAttachContext())
.setMessage(R.string.title_dialog_exit_account)
.setPositiveButton(R.string.button_sure_default, (dialog, which) -> {
AccountUtil.exit(getAttachContext());
refresh();
if (AccountUtil.getLoginInfo(getAttachContext()) == null) {
getAttachContext().startActivity(new Intent(getAttachContext(), LoginActivity.class));
}
})
.setNegativeButton(R.string.button_cancel, null)
.create()
.show();
return true;
});
findPreference("black_list").setOnPreferenceClickListener(preference -> {
startActivity(new Intent(getAttachContext(), BlockListActivity.class).putExtra("category", Block.CATEGORY_BLACK_LIST));
return true;
});
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.P) {
findPreference("follow_system_night").setEnabled(true);
findPreference("follow_system_night").setSummary(null);
} else {
findPreference("follow_system_night").setEnabled(false);
findPreference("follow_system_night").setSummary(R.string.summary_follow_system_night_disabled);
}
findPreference("show_top_forum_in_normal_list").setOnPreferenceChangeListener((preference, newValue) -> {
preference.setSummary(R.string.summary_show_top_forum_in_normal_list_changed);
return true;
});
findPreference("status_bar_darker").setOnPreferenceChangeListener((preference, newValue) -> {
preference.setSummary(R.string.summary_status_bar_darker_changed);
return true;
});
findPreference("hideExplore").setOnPreferenceChangeListener((preference, newValue) -> {
preference.setSummary(R.string.summary_change_need_restart);
return true;
});
findPreference("white_list").setOnPreferenceClickListener(preference -> {
startActivity(new Intent(getAttachContext(), BlockListActivity.class).putExtra("category", Block.CATEGORY_WHITE_LIST));
return true;
});
TimePickerPreference timePickerPreference = findPreference("auto_sign_time");
timePickerPreference.setOnPreferenceChangeListener((preference, newValue) -> {
preference.setSummary(getAttachContext().getString(R.string.summary_auto_sign_time, (String) newValue));
return true;
});
timePickerPreference.setSummary(getAttachContext().getString(R.string.summary_auto_sign_time, getPreferenceManager().getSharedPreferences().getString("auto_sign_time", "09:00")));
Preference clearCache = findPreference("clear_cache");
clearCache.setSummary(getAttachContext().getString(R.string.tip_cache, GlideCacheUtil.getInstance().getCacheSize(getAttachContext())));
clearCache.setOnPreferenceClickListener(preference -> {
GlideCacheUtil.getInstance().clearImageAllCache(getAttachContext());
if (getView() != null)
Util.createSnackbar(getView(), R.string.toast_clear_cache_success, Snackbar.LENGTH_SHORT).show();
preference.setSummary(getAttachContext().getString(R.string.tip_cache, "0.0B"));
return true;
});
EditTextPreference littleTaliPreference = findPreference("little_tail");
String littleTali = getPreferenceManager().getSharedPreferences().getString("little_tail", "");
if (littleTali.isEmpty()) {
littleTaliPreference.setSummary(R.string.tip_no_little_tail);
} else {
littleTaliPreference.setSummary(littleTali);
littleTaliPreference.setText(littleTali);
}
littleTaliPreference.setOnPreferenceChangeListener((preference, value) -> {
if (value instanceof String) {
String tail = (String) value;
if (tail.isEmpty()) {
littleTaliPreference.setSummary(R.string.tip_no_little_tail);
} else {
littleTaliPreference.setSummary(tail);
littleTaliPreference.setText(tail);
}
}
return true;
});
Preference aboutPreference = findPreference("about");
LiteApi.getInstance().newCheckUpdate(new CommonAPICallback<NewUpdateBean>() {
@Override
public void onSuccess(NewUpdateBean data) {
if (data.isHasUpdate()) {
aboutPreference.setSummary(getAttachContext().getString(R.string.tip_new_version, data.getResult().getVersionName()));
}
}
@Override
public void onFailure(int code, String error) {
}
});
SwitchPreference useCustomTabs = findPreference("use_custom_tabs");
useCustomTabs.setEnabled(!getPreferenceManager().getSharedPreferences().getBoolean("use_webview", true));
findPreference("use_webview").setOnPreferenceChangeListener((preference, newValue) -> {
useCustomTabs.setEnabled(!(boolean) newValue);
return true;
});
initListPreference("dark_theme", "dark");
aboutPreference.setSummary(getString(R.string.tip_about, VersionUtil.getVersionName(getAttachContext())));
refresh();
}
@Override
public void onViewCreated(@NonNull View view, @Nullable Bundle savedInstanceState) {
super.onViewCreated(view, savedInstanceState);
setDivider(ThemeUtils.tintDrawable(ContextCompat.getDrawable(getAttachContext(), R.drawable.drawable_divider_8dp), ThemeUtils.getColorByAttr(getAttachContext(), R.attr.colorDivider)));
setDividerHeight(DisplayUtil.dp2px(getAttachContext(), 8));
}
private void initSwitchPreference(String key) {
initSwitchPreference(key, false);
}
private void initSwitchPreference(SwitchPreference switchPreference) {
initSwitchPreference(switchPreference, false);
}
private void initSwitchPreference(String key, boolean defValue) {
SwitchPreference switchPreference = findPreference(key);
initSwitchPreference(switchPreference, defValue);
}
private void initSwitchPreference(SwitchPreference switchPreference, boolean defValue) {
boolean value = getPreferenceManager().getSharedPreferences().getBoolean(switchPreference.getKey(), defValue);
switchPreference.setChecked(value);
}
private void initListPreference(String key, String defValue) {
ListPreference listPreference = findPreference(key);
String value = getPreferenceManager().getSharedPreferences().getString(key, defValue);
listPreference.setValue(value);
}
}

View File

@ -0,0 +1,206 @@
package com.huanchengfly.tieba.post.fragments
import android.annotation.SuppressLint
import android.content.DialogInterface
import android.content.Intent
import android.os.Build
import android.os.Bundle
import android.view.View
import android.widget.Toast
import androidx.core.content.ContextCompat
import androidx.preference.EditTextPreference
import androidx.preference.ListPreference
import androidx.preference.Preference
import androidx.preference.SwitchPreference
import com.google.android.material.snackbar.Snackbar
import com.huanchengfly.theme.utils.ThemeUtils
import com.huanchengfly.tieba.api.LiteApi.Companion.instance
import com.huanchengfly.tieba.api.interfaces.CommonAPICallback
import com.huanchengfly.tieba.api.models.NewUpdateBean
import com.huanchengfly.tieba.post.R
import com.huanchengfly.tieba.post.activities.BlockListActivity
import com.huanchengfly.tieba.post.activities.LoginActivity
import com.huanchengfly.tieba.post.components.prefs.TimePickerPreference
import com.huanchengfly.tieba.post.models.database.Account
import com.huanchengfly.tieba.post.models.database.Block
import com.huanchengfly.tieba.post.utils.*
import com.huanchengfly.utils.GlideCacheUtil
import com.lapism.searchview.database.SearchHistoryTable
import java.util.*
class SettingsFragment : PreferencesFragment() {
private var loginInfo: Account? = null
override fun onResume() {
super.onResume()
refresh()
}
private fun refresh() {
loginInfo = AccountUtil.getLoginInfo(attachContext)
val accounts = AccountUtil.getAllAccounts()
val usernameList: MutableList<String> = ArrayList()
val idList: MutableList<String> = ArrayList()
for (account in accounts) {
usernameList.add(account.nameShow)
idList.add(account.id.toString())
}
val accountsPreference = findPreference<ListPreference>("switch_account")
accountsPreference!!.entries = usernameList.toTypedArray()
accountsPreference.entryValues = idList.toTypedArray()
if (loginInfo != null) {
accountsPreference.value = loginInfo!!.id.toString()
accountsPreference.summary = "已登录账号 " + loginInfo!!.nameShow
} else {
accountsPreference.summary = "未登录"
}
}
@SuppressLint("ApplySharedPref")
override fun onCreatePreferences(savedInstanceState: Bundle?, rootKey: String?) {
preferenceManager.sharedPreferencesName = "settings"
addPreferencesFromResource(R.xml.preferences)
val accountsPreference = findPreference<ListPreference>("switch_account")
accountsPreference!!.onPreferenceChangeListener = Preference.OnPreferenceChangeListener { _: Preference?, newValue: Any? ->
if (AccountUtil.switchUser(attachContext, Integer.valueOf((newValue as String?)!!))) {
refresh()
Toast.makeText(attachContext, R.string.toast_switch_success, Toast.LENGTH_SHORT).show()
}
false
}
findPreference<Preference>("copy_bduss")!!.onPreferenceClickListener = Preference.OnPreferenceClickListener {
val account = AccountUtil.getLoginInfo(attachContext)
if (account != null) {
TiebaUtil.copyText(attachContext, account.bduss)
}
true
}
findPreference<Preference>("clear_search_history")!!.onPreferenceClickListener = Preference.OnPreferenceClickListener {
SearchHistoryTable(attachContext).clearDatabase()
if (view != null) Util.createSnackbar(view!!, R.string.toast_clear_success, Snackbar.LENGTH_SHORT).show()
true
}
findPreference<Preference>("exit_account")!!.isEnabled = AccountUtil.isLoggedIn(attachContext)
findPreference<Preference>("exit_account")!!.onPreferenceClickListener = Preference.OnPreferenceClickListener {
DialogUtil.build(attachContext)
.setMessage(R.string.title_dialog_exit_account)
.setPositiveButton(R.string.button_sure_default) { _: DialogInterface?, _: Int ->
AccountUtil.exit(attachContext)
refresh()
if (AccountUtil.getLoginInfo(attachContext) == null) {
attachContext.startActivity(Intent(attachContext, LoginActivity::class.java))
}
}
.setNegativeButton(R.string.button_cancel, null)
.create()
.show()
true
}
findPreference<Preference>("black_list")!!.onPreferenceClickListener = Preference.OnPreferenceClickListener {
startActivity(Intent(attachContext, BlockListActivity::class.java).putExtra("category", Block.CATEGORY_BLACK_LIST))
true
}
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.P) {
findPreference<Preference>("follow_system_night")!!.isEnabled = true
findPreference<Preference>("follow_system_night")!!.summary = null
} else {
findPreference<Preference>("follow_system_night")!!.isEnabled = false
findPreference<Preference>("follow_system_night")!!.setSummary(R.string.summary_follow_system_night_disabled)
}
findPreference<Preference>("show_top_forum_in_normal_list")!!.onPreferenceChangeListener = Preference.OnPreferenceChangeListener { preference: Preference, _: Any? ->
preference.setSummary(R.string.summary_show_top_forum_in_normal_list_changed)
true
}
findPreference<Preference>("status_bar_darker")!!.onPreferenceChangeListener = Preference.OnPreferenceChangeListener { preference: Preference, _: Any? ->
preference.setSummary(R.string.summary_status_bar_darker_changed)
true
}
findPreference<Preference>("hideExplore")!!.onPreferenceChangeListener = Preference.OnPreferenceChangeListener { preference: Preference, _: Any? ->
preference.setSummary(R.string.summary_change_need_restart)
true
}
findPreference<Preference>("white_list")!!.onPreferenceClickListener = Preference.OnPreferenceClickListener {
startActivity(Intent(attachContext, BlockListActivity::class.java).putExtra("category", Block.CATEGORY_WHITE_LIST))
true
}
val timePickerPreference = findPreference<TimePickerPreference>("auto_sign_time")
timePickerPreference!!.onPreferenceChangeListener = Preference.OnPreferenceChangeListener { preference: Preference, newValue: Any? ->
preference.summary = attachContext.getString(R.string.summary_auto_sign_time, newValue as String?)
true
}
timePickerPreference.summary = attachContext.getString(R.string.summary_auto_sign_time, preferenceManager.sharedPreferences.getString("auto_sign_time", "09:00"))
val clearCache = findPreference<Preference>("clear_cache")
clearCache!!.summary = attachContext.getString(R.string.tip_cache, GlideCacheUtil.getInstance().getCacheSize(attachContext))
clearCache.onPreferenceClickListener = Preference.OnPreferenceClickListener { preference: Preference ->
GlideCacheUtil.getInstance().clearImageAllCache(attachContext)
if (view != null) Util.createSnackbar(view!!, R.string.toast_clear_cache_success, Snackbar.LENGTH_SHORT).show()
preference.summary = attachContext.getString(R.string.tip_cache, "0.0B")
true
}
val littleTaliPreference = findPreference<EditTextPreference>("little_tail")
val littleTali = preferenceManager.sharedPreferences.getString("little_tail", "")
if (littleTali!!.isEmpty()) {
littleTaliPreference!!.setSummary(R.string.tip_no_little_tail)
} else {
littleTaliPreference!!.summary = littleTali
littleTaliPreference.text = littleTali
}
littleTaliPreference.onPreferenceChangeListener = Preference.OnPreferenceChangeListener { _: Preference?, value: Any? ->
if (value is String) {
if (value.isEmpty()) {
littleTaliPreference.setSummary(R.string.tip_no_little_tail)
} else {
littleTaliPreference.summary = value
littleTaliPreference.text = value
}
}
true
}
val aboutPreference = findPreference<Preference>("about")
instance!!.newCheckUpdate(object : CommonAPICallback<NewUpdateBean?> {
override fun onSuccess(data: NewUpdateBean?) {
if (data != null) {
if (data.isHasUpdate) {
aboutPreference!!.summary = attachContext.getString(R.string.tip_new_version, data.result.versionName)
}
}
}
override fun onFailure(code: Int, error: String) {}
})
val useCustomTabs = findPreference<SwitchPreference>("use_custom_tabs")
useCustomTabs!!.isEnabled = !preferenceManager.sharedPreferences.getBoolean("use_webview", true)
findPreference<Preference>("use_webview")!!.onPreferenceChangeListener = Preference.OnPreferenceChangeListener { _: Preference?, newValue: Any? ->
useCustomTabs.isEnabled != newValue as Boolean
true
}
initListPreference("dark_theme", "dark")
aboutPreference!!.summary = getString(R.string.tip_about, VersionUtil.getVersionName(attachContext))
refresh()
}
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
super.onViewCreated(view, savedInstanceState)
setDivider(ThemeUtils.tintDrawable(ContextCompat.getDrawable(attachContext, R.drawable.drawable_divider_8dp), ThemeUtils.getColorByAttr(attachContext, R.attr.colorDivider)))
setDividerHeight(DisplayUtil.dp2px(attachContext, 8f))
}
private fun initSwitchPreference(key: String, defValue: Boolean = false) {
val switchPreference = findPreference<SwitchPreference>(key)
initSwitchPreference(switchPreference, defValue)
}
private fun initSwitchPreference(switchPreference: SwitchPreference?, defValue: Boolean = false) {
val value = preferenceManager.sharedPreferences.getBoolean(switchPreference!!.key, defValue)
switchPreference.isChecked = value
}
private fun initListPreference(key: String, defValue: String) {
val listPreference = findPreference<ListPreference>(key)
val value = preferenceManager.sharedPreferences.getString(key, defValue)
listPreference!!.value = value
}
companion object {
const val TAG = "SettingsFragment"
}
}

View File

@ -1,5 +1,4 @@
<?xml version="1.0" encoding="utf-8"?>
<!--suppress AndroidElementNotAllowed -->
<?xml version="1.0" encoding="utf-8"?><!--suppress AndroidElementNotAllowed -->
<androidx.preference.PreferenceScreen xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto">
<androidx.preference.PreferenceCategory
@ -8,15 +7,16 @@
<ListPreference
android:icon="@drawable/ic_round_account_circle"
android:key="switch_account"
android:title="@string/title_switch_account"/>
android:title="@string/title_switch_account" />
<Preference
android:icon="@drawable/ic_round_add_circle_green"
android:title="@string/title_new_account">
<intent android:targetPackage="com.huanchengfly.tieba.post" android:targetClass="com.huanchengfly.tieba.post.activities.LoginActivity" android:action="android.intent.action.VIEW" />
android:title="@string/title_new_account"
android:summary="@string/tip_account_error">
<intent
android:targetPackage="top.goforce.tieba.post"
android:targetClass="com.huanchengfly.tieba.post.activities.LoginActivity"
android:action="android.intent.action.VIEW" />
</Preference>
<Preference
android:layout="@layout/layout_preference_dense"
android:summary="@string/tip_account_error"/>
<Preference
android:icon="@drawable/ic_close_circle_red"
android:key="exit_account"
@ -25,7 +25,7 @@
android:icon="@drawable/ic_document_green"
android:key="copy_bduss"
android:title="@string/title_copy_bduss"
android:summary="@string/summary_copy_bduss"/>
android:summary="@string/summary_copy_bduss" />
<EditTextPreference
android:icon="@drawable/ic_round_more_blue"
android:key="little_tail"
@ -35,8 +35,7 @@
android:layout="@layout/layout_preference_bottom" />
</androidx.preference.PreferenceCategory>
<androidx.preference.PreferenceCategory
android:title="@string/title_block_settings">
<androidx.preference.PreferenceCategory android:title="@string/title_block_settings">
<Preference
android:icon="@drawable/ic_round_remove_circle"
android:key="black_list"
@ -50,8 +49,7 @@
android:layout="@layout/layout_preference_bottom" />
</androidx.preference.PreferenceCategory>
<androidx.preference.PreferenceCategory
android:title="@string/title_settings_read_habit">
<androidx.preference.PreferenceCategory android:title="@string/title_settings_read_habit">
<ListPreference
android:icon="@drawable/ic_round_photo_size_select_actual"
@ -110,8 +108,7 @@
android:layout="@layout/layout_preference_bottom" />
</androidx.preference.PreferenceCategory>
<androidx.preference.PreferenceCategory
android:title="@string/title_settings_custom">
<androidx.preference.PreferenceCategory android:title="@string/title_settings_custom">
<ListPreference
android:icon="@drawable/ic_round_brightness_2_green"
android:key="dark_theme"
@ -165,15 +162,14 @@
android:layout="@layout/layout_preference_bottom" />
</androidx.preference.PreferenceCategory>
<androidx.preference.PreferenceCategory
android:title="@string/title_auto_sign">
<androidx.preference.PreferenceCategory android:title="@string/title_auto_sign">
<SwitchPreference
android:icon="@drawable/ic_round_offline_pin_blue"
android:summaryOn="@string/summary_auto_sign_on"
android:summaryOff="@string/summary_auto_sign"
android:defaultValue="false"
android:key="auto_sign"
android:title="@string/title_auto_sign"/>
android:title="@string/title_auto_sign" />
<com.huanchengfly.tieba.post.components.prefs.TimePickerPreference
android:dependency="auto_sign"
@ -184,21 +180,20 @@
<Preference
android:layout="@layout/layout_preference_dense"
android:summary="@string/tip_auto_sign"/>
android:summary="@string/tip_auto_sign" />
<Preference
android:enabled="false"
android:layout="@layout/layout_preference_bottom" />
</androidx.preference.PreferenceCategory>
<androidx.preference.PreferenceCategory
android:title="@string/title_settings_about">
<androidx.preference.PreferenceCategory android:title="@string/title_settings_about">
<SwitchPreference
android:icon="@drawable/ic_round_bug_report_blue"
android:defaultValue="false"
android:key="check_beta_update"
android:title="@string/title_check_beta_update"
android:summary="@string/tip_check_beta_update"/>
android:summary="@string/tip_check_beta_update" />
<SwitchPreference
android:icon="@drawable/ic_chrome"
@ -206,7 +201,7 @@
android:key="use_webview"
android:title="@string/title_use_webview"
android:summaryOn="@string/tip_use_webview_on"
android:summaryOff="@string/tip_use_webview"/>
android:summaryOff="@string/tip_use_webview" />
<SwitchPreference
android:icon="@drawable/ic_today"
@ -214,7 +209,7 @@
android:key="use_custom_tabs"
android:title="@string/title_use_custom_tabs"
android:summaryOn="@string/tip_use_custom_tab_on"
android:summaryOff="@string/tip_use_custom_tab"/>
android:summaryOff="@string/tip_use_custom_tab" />
<Preference
android:icon="@drawable/ic_round_offline_bolt_green"
@ -230,7 +225,10 @@
android:key="about"
android:icon="@drawable/ic_round_info"
android:title="@string/title_about">
<intent android:targetPackage="com.huanchengfly.tieba.post" android:targetClass="com.huanchengfly.tieba.post.activities.AboutActivity" android:action="android.intent.action.VIEW" />
<intent
android:targetPackage="top.goforce.tieba.post"
android:targetClass="com.huanchengfly.tieba.post.activities.AboutActivity"
android:action="android.intent.action.VIEW" />
</Preference>
<Preference

View File

@ -10,7 +10,7 @@
<intent
android:action="com.huanchengfly.tieba.post.action.OKSIGN"
android:targetClass="com.huanchengfly.tieba.post.activities.OKSignActivity"
android:targetPackage="com.huanchengfly.tieba.post" />
android:targetPackage="top.goforce.tieba.post" />
</shortcut>
<shortcut
android:icon="@drawable/ic_shortcut_collect"
@ -20,7 +20,7 @@
<intent
android:action="android.intent.action.VIEW"
android:targetClass="com.huanchengfly.tieba.post.activities.UserCollectActivity"
android:targetPackage="com.huanchengfly.tieba.post" />
android:targetPackage="top.goforce.tieba.post" />
</shortcut>
<shortcut
android:icon="@drawable/ic_shortcut_message"
@ -30,6 +30,6 @@
<intent
android:action="android.intent.action.VIEW"
android:targetClass="com.huanchengfly.tieba.post.activities.MessageActivity"
android:targetPackage="com.huanchengfly.tieba.post" />
android:targetPackage="top.goforce.tieba.post" />
</shortcut>
</shortcuts>