diff --git a/app/src/main/java/com/huanchengfly/tieba/post/BaseApplication.kt b/app/src/main/java/com/huanchengfly/tieba/post/BaseApplication.kt index cb8d5c8d..66679cd6 100644 --- a/app/src/main/java/com/huanchengfly/tieba/post/BaseApplication.kt +++ b/app/src/main/java/com/huanchengfly/tieba/post/BaseApplication.kt @@ -252,14 +252,12 @@ class BaseApplication : Application() { when (attrId) { R.attr.colorPrimary -> { if (ThemeUtil.THEME_CUSTOM == theme) { - val customPrimaryColorStr = SharedPreferencesUtil.get(context, SharedPreferencesUtil.SP_SETTINGS) - .getString(ThemeUtil.SP_CUSTOM_PRIMARY_COLOR, null) + val customPrimaryColorStr = context.appPreferences.customPrimaryColor return if (customPrimaryColorStr != null) { Color.parseColor(customPrimaryColorStr) } else getColorByAttr(context, attrId, ThemeUtil.THEME_WHITE) } else if (ThemeUtil.THEME_TRANSLUCENT == theme) { - val primaryColorStr = SharedPreferencesUtil.get(context, SharedPreferencesUtil.SP_SETTINGS) - .getString(ThemeUtil.SP_TRANSLUCENT_PRIMARY_COLOR, null) + val primaryColorStr = context.appPreferences.translucentPrimaryColor return if (primaryColorStr != null) { Color.parseColor(primaryColorStr) } else getColorByAttr(context, attrId, ThemeUtil.THEME_WHITE) @@ -278,8 +276,7 @@ class BaseApplication : Application() { return context.getColorCompat(R.color.transparent) } if (ThemeUtil.THEME_CUSTOM == theme) { - val primary = SharedPreferencesUtil.get(context, SharedPreferencesUtil.SP_SETTINGS) - .getBoolean(ThemeUtil.SP_CUSTOM_TOOLBAR_PRIMARY_COLOR, true) + val primary = context.appPreferences.customToolbarPrimaryColor return if (primary) { getColorByAttr(context, R.attr.colorPrimary, theme) } else context.getColorCompat(R.color.white) diff --git a/app/src/main/java/com/huanchengfly/tieba/post/Extensions.kt b/app/src/main/java/com/huanchengfly/tieba/post/Extensions.kt index 801bddef..772ba3be 100644 --- a/app/src/main/java/com/huanchengfly/tieba/post/Extensions.kt +++ b/app/src/main/java/com/huanchengfly/tieba/post/Extensions.kt @@ -49,6 +49,10 @@ fun Context.toastShort(text: String) { Toast.makeText(this, text, Toast.LENGTH_SHORT).show() } +fun Context.toastShort(resId: Int) { + Toast.makeText(this, resId, Toast.LENGTH_SHORT).show() +} + inline fun Activity.goToActivity(pre: (Intent) -> Intent) { startActivity(pre(Intent(this, T::class.java))) } diff --git a/app/src/main/java/com/huanchengfly/tieba/post/activities/FloorActivity.kt b/app/src/main/java/com/huanchengfly/tieba/post/activities/FloorActivity.kt index 1bb8050c..18662633 100644 --- a/app/src/main/java/com/huanchengfly/tieba/post/activities/FloorActivity.kt +++ b/app/src/main/java/com/huanchengfly/tieba/post/activities/FloorActivity.kt @@ -14,10 +14,10 @@ import androidx.recyclerview.widget.RecyclerView import androidx.swiperefreshlayout.widget.SwipeRefreshLayout import butterknife.BindView import butterknife.OnClick -import com.huanchengfly.tieba.post.api.TiebaApi -import com.huanchengfly.tieba.post.api.models.SubFloorListBean import com.huanchengfly.tieba.post.R import com.huanchengfly.tieba.post.adapters.RecyclerFloorAdapter +import com.huanchengfly.tieba.post.api.TiebaApi +import com.huanchengfly.tieba.post.api.models.SubFloorListBean import com.huanchengfly.tieba.post.components.MyLinearLayoutManager import com.huanchengfly.tieba.post.components.dividers.ThreadDivider import com.huanchengfly.tieba.post.models.ReplyInfoBean @@ -156,7 +156,7 @@ class FloorActivity : BaseActivity() { dataBean!!.post!!.id, dataBean!!.post!!.floor, dataBean!!.post!!.author.nameShow, - AccountUtil.getLoginInfo(this).nameShow).setPn(pn.toString()).toString())) + AccountUtil.getLoginInfo(this)!!.nameShow).setPn(pn.toString()).toString())) } private fun refresh() { diff --git a/app/src/main/java/com/huanchengfly/tieba/post/activities/ForumActivity.kt b/app/src/main/java/com/huanchengfly/tieba/post/activities/ForumActivity.kt index 9cd51b62..382d0967 100644 --- a/app/src/main/java/com/huanchengfly/tieba/post/activities/ForumActivity.kt +++ b/app/src/main/java/com/huanchengfly/tieba/post/activities/ForumActivity.kt @@ -35,15 +35,14 @@ import com.google.android.material.floatingactionbutton.FloatingActionButton import com.google.android.material.snackbar.Snackbar import com.google.android.material.tabs.TabLayout import com.google.android.material.tabs.TabLayout.OnTabSelectedListener -import com.huanchengfly.tieba.post.ui.theme.utils.ThemeUtils +import com.huanchengfly.tieba.post.R +import com.huanchengfly.tieba.post.adapters.FragmentTabViewPagerAdapter import com.huanchengfly.tieba.post.api.ForumSortType import com.huanchengfly.tieba.post.api.TiebaApi import com.huanchengfly.tieba.post.api.models.CommonResponse import com.huanchengfly.tieba.post.api.models.ForumPageBean import com.huanchengfly.tieba.post.api.models.LikeForumResultBean import com.huanchengfly.tieba.post.api.models.SignResultBean -import com.huanchengfly.tieba.post.R -import com.huanchengfly.tieba.post.adapters.FragmentTabViewPagerAdapter import com.huanchengfly.tieba.post.fragments.ForumFragment import com.huanchengfly.tieba.post.fragments.ForumFragment.OnRefreshedListener import com.huanchengfly.tieba.post.fragments.ForumInfoFragment @@ -51,12 +50,13 @@ import com.huanchengfly.tieba.post.interfaces.Refreshable import com.huanchengfly.tieba.post.interfaces.ScrollTopable import com.huanchengfly.tieba.post.models.PhotoViewBean import com.huanchengfly.tieba.post.models.database.History +import com.huanchengfly.tieba.post.toDp +import com.huanchengfly.tieba.post.ui.theme.utils.ThemeUtils import com.huanchengfly.tieba.post.utils.* import com.huanchengfly.tieba.post.utils.preload.PreloadUtil import com.huanchengfly.tieba.post.widgets.MyViewPager import com.huanchengfly.tieba.post.widgets.theme.TintProgressBar import com.huanchengfly.tieba.post.widgets.theme.TintToolbar -import com.huanchengfly.tieba.post.toDp import com.lapism.searchview.widget.SearchView import retrofit2.Call import retrofit2.Callback @@ -151,8 +151,7 @@ class ForumActivity : BaseActivity(), View.OnClickListener, OnRefreshedListener } private fun getSortType(): ForumSortType { - val defaultSortType = SharedPreferencesUtil.get(this, SharedPreferencesUtil.SP_SETTINGS) - .getString("default_sort_type", ForumSortType.REPLY_TIME.toString())!!.toInt() + val defaultSortType = appPreferences.defaultSortType!!.toInt() return ForumSortType.valueOf(SharedPreferencesUtil.get(this, SharedPreferencesUtil.SP_SETTINGS) .getInt(forumName + "_sort_type", defaultSortType)) } diff --git a/app/src/main/java/com/huanchengfly/tieba/post/activities/MainActivity.kt b/app/src/main/java/com/huanchengfly/tieba/post/activities/MainActivity.kt index c2438738..7a28e9c5 100644 --- a/app/src/main/java/com/huanchengfly/tieba/post/activities/MainActivity.kt +++ b/app/src/main/java/com/huanchengfly/tieba/post/activities/MainActivity.kt @@ -70,8 +70,7 @@ open class MainActivity : BaseActivity(), BottomNavigationView.OnNavigationItemS 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) + val followSystemNight = appPreferences.followSystemNight if (followSystemNight) { if (BaseApplication.isSystemNight && !ThemeUtil.isNightMode(this)) { SharedPreferencesUtil.put(ThemeUtil.getSharedPreferences(this), SP_SHOULD_SHOW_SNACKBAR, true) @@ -369,7 +368,7 @@ open class MainActivity : BaseActivity(), BottomNavigationView.OnNavigationItemS instance!!.newCheckUpdate(object : CommonAPICallback { override fun onSuccess(data: NewUpdateBean?) { if (data != null) { - if (data.isHasUpdate!!) { + 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) diff --git a/app/src/main/java/com/huanchengfly/tieba/post/activities/TranslucentThemeActivity.java b/app/src/main/java/com/huanchengfly/tieba/post/activities/TranslucentThemeActivity.java deleted file mode 100644 index ed2a601c..00000000 --- a/app/src/main/java/com/huanchengfly/tieba/post/activities/TranslucentThemeActivity.java +++ /dev/null @@ -1,406 +0,0 @@ -package com.huanchengfly.tieba.post.activities; - -import android.annotation.SuppressLint; -import android.content.Intent; -import android.graphics.Bitmap; -import android.graphics.Color; -import android.graphics.drawable.BitmapDrawable; -import android.graphics.drawable.Drawable; -import android.net.Uri; -import android.os.Build; -import android.os.Bundle; -import android.text.Html; -import android.text.Spanned; -import android.view.Menu; -import android.view.MenuItem; -import android.view.View; -import android.widget.Button; -import android.widget.SeekBar; -import android.widget.TextView; -import android.widget.Toast; - -import androidx.annotation.ColorInt; -import androidx.annotation.NonNull; -import androidx.annotation.Nullable; -import androidx.appcompat.app.ActionBar; -import androidx.appcompat.widget.Toolbar; -import androidx.palette.graphics.Palette; -import androidx.recyclerview.widget.RecyclerView; - -import com.bumptech.glide.Glide; -import com.bumptech.glide.load.engine.DiskCacheStrategy; -import com.bumptech.glide.request.RequestOptions; -import com.bumptech.glide.request.target.SimpleTarget; -import com.bumptech.glide.request.transition.Transition; -import com.gyf.immersionbar.ImmersionBar; -import com.huanchengfly.tieba.post.BaseApplication; -import com.huanchengfly.tieba.post.R; -import com.huanchengfly.tieba.post.adapters.ThemeColorAdapter; -import com.huanchengfly.tieba.post.components.MyImageEngine; -import com.huanchengfly.tieba.post.components.MyLinearLayoutManager; -import com.huanchengfly.tieba.post.components.transformations.BlurTransformation; -import com.huanchengfly.tieba.post.ui.theme.utils.ThemeUtils; -import com.huanchengfly.tieba.post.utils.ImageUtil; -import com.huanchengfly.tieba.post.utils.PermissionUtil; -import com.huanchengfly.tieba.post.utils.SharedPreferencesUtil; -import com.huanchengfly.tieba.post.utils.ThemeUtil; -import com.jrummyapps.android.colorpicker.ColorPickerDialog; -import com.jrummyapps.android.colorpicker.ColorPickerDialogListener; -import com.yalantis.ucrop.UCrop; -import com.yanzhenjie.permission.Action; -import com.yanzhenjie.permission.runtime.Permission; -import com.zhihu.matisse.Matisse; -import com.zhihu.matisse.MimeType; - -import java.io.File; -import java.util.List; - -import static com.huanchengfly.tieba.post.utils.ColorUtils.getDarkerColor; -import static com.huanchengfly.tieba.post.utils.ThemeUtil.SP_TRANSLUCENT_PRIMARY_COLOR; -import static com.huanchengfly.tieba.post.utils.ThemeUtil.THEME_TRANSLUCENT; - -public class TranslucentThemeActivity extends BaseActivity implements View.OnClickListener, SeekBar.OnSeekBarChangeListener, ColorPickerDialogListener { - public static final String TAG = TranslucentThemeActivity.class.getSimpleName(); - public static final int REQUEST_CODE_CHOOSE = 2; - - private Uri mUri; - private int alpha; - private int blur; - private Palette mPalette; - private View mSelectColor; - private ThemeColorAdapter mAdapter; - private View mProgress; - - public static String toString(int alpha, int red, int green, int blue) { - String hr = Integer.toHexString(red); - String hg = Integer.toHexString(green); - String hb = Integer.toHexString(blue); - String ha = Integer.toHexString(alpha); - return "#" + fixHexString(ha) + fixHexString(hr) + fixHexString(hg) + fixHexString(hb); - } - - public static String fixHexString(String hexString) { - if (hexString.length() < 1) { - hexString = "00"; - } - if (hexString.length() == 1) { - hexString = "0" + hexString; - } - if (hexString.length() > 2) { - hexString = hexString.substring(0, 2); - } - return hexString; - } - - public static String toString(@ColorInt int color) { - return toString(Color.alpha(color), Color.red(color), Color.green(color), Color.blue(color)); - } - - @Override - protected void onActivityResult(int requestCode, int resultCode, Intent data) { - super.onActivityResult(requestCode, resultCode, data); - if (requestCode == REQUEST_CODE_CHOOSE && resultCode == RESULT_OK) { - Uri sourceUri = Matisse.obtainResult(data).get(0); - Glide.with(this) - .asDrawable() - .load(sourceUri) - .into(new SimpleTarget() { - @Override - public void onResourceReady(@NonNull Drawable resource, @Nullable Transition transition) { - Bitmap bitmap = ImageUtil.drawableToBitmap(resource); - File file = ImageUtil.bitmapToFile(bitmap, new File(getCacheDir(), "origin_background.jpg")); - Uri sourceUri = Uri.fromFile(file); - Uri destUri = Uri.fromFile(new File(getCacheDir(), "cropped_background.jpg")); - float height = (float) BaseApplication.ScreenInfo.EXACT_SCREEN_HEIGHT; - float width = (float) BaseApplication.ScreenInfo.EXACT_SCREEN_WIDTH; - UCrop.Options uCropOptions = new UCrop.Options(); - uCropOptions.setShowCropFrame(true); - uCropOptions.setShowCropGrid(true); - uCropOptions.setStatusBarColor(getDarkerColor(ThemeUtils.getColorByAttr(TranslucentThemeActivity.this, R.attr.colorPrimary))); - uCropOptions.setToolbarColor(ThemeUtils.getColorByAttr(TranslucentThemeActivity.this, R.attr.colorPrimary)); - uCropOptions.setToolbarWidgetColor(ThemeUtils.getColorByAttr(TranslucentThemeActivity.this, R.attr.colorTextOnPrimary)); - uCropOptions.setActiveWidgetColor(ThemeUtils.getColorByAttr(TranslucentThemeActivity.this, R.attr.colorAccent)); - uCropOptions.setActiveControlsWidgetColor(ThemeUtils.getColorByAttr(TranslucentThemeActivity.this, R.attr.colorAccent)); - uCropOptions.setLogoColor(ThemeUtils.getColorByAttr(TranslucentThemeActivity.this, R.attr.colorPrimary)); - uCropOptions.setCompressionFormat(Bitmap.CompressFormat.JPEG); - UCrop.of(sourceUri, destUri) - .withAspectRatio(width / height, 1) - .withOptions(uCropOptions) - .start(TranslucentThemeActivity.this); - } - }); - } else if (resultCode == RESULT_OK && requestCode == UCrop.REQUEST_CROP) { - mUri = UCrop.getOutput(data); - invalidateOptionsMenu(); - refreshBackground(); - } else if (resultCode == UCrop.RESULT_ERROR) { - final Throwable cropError = UCrop.getError(data); - cropError.printStackTrace(); - } - } - - private void refreshBackground() { - mProgress.setVisibility(View.VISIBLE); - if (mUri == null) { - findViewById(R.id.background).setBackgroundColor(Color.BLACK); - mProgress.setVisibility(View.GONE); - return; - } - RequestOptions bgOptions = RequestOptions.centerCropTransform() - .skipMemoryCache(true) - .diskCacheStrategy(DiskCacheStrategy.NONE); - if (blur > 0) { - bgOptions = bgOptions.transform(new BlurTransformation(blur)); - } - Glide.with(this) - .asDrawable() - .load(mUri) - .apply(bgOptions) - .into(new SimpleTarget() { - @Override - public void onResourceReady(@NonNull Drawable resource, @Nullable Transition transition) { - resource.setAlpha(alpha); - Bitmap bitmap = ImageUtil.drawableToBitmap(resource); - findViewById(R.id.background).setBackgroundTintList(null); - findViewById(R.id.background).setBackground(new BitmapDrawable(getResources(), bitmap)); - mPalette = Palette.from(bitmap).generate(); - mAdapter.setPalette(mPalette); - mSelectColor.setVisibility(View.VISIBLE); - mProgress.setVisibility(View.GONE); - } - }); - } - - @Override - public void refreshStatusBarColor() { - ImmersionBar.with(this) - .transparentBar() - .init(); - } - - @SuppressLint({"ApplySharedPref", "ClickableViewAccessibility"}) - @Override - protected void onCreate(Bundle savedInstanceState) { - super.onCreate(savedInstanceState); - setContentView(R.layout.activity_translucent_theme); - TextView tip = (TextView) findViewById(R.id.tip); - Spanned spanned; - if (android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.N) { - spanned = Html.fromHtml(getString(R.string.tip_translucent_theme), Html.FROM_HTML_MODE_LEGACY); - } else { - spanned = Html.fromHtml(getString(R.string.tip_translucent_theme)); - } - tip.setText(spanned); - Toolbar toolbar = (Toolbar) findViewById(R.id.toolbar); - setSupportActionBar(toolbar); - ActionBar actionBar = getSupportActionBar(); - if (actionBar != null) { - actionBar.setDisplayHomeAsUpEnabled(true); - actionBar.setTitle(R.string.title_dialog_translucent_theme); - } - alpha = SharedPreferencesUtil.get(this, SharedPreferencesUtil.SP_SETTINGS).getInt("translucent_background_alpha", 255); - blur = SharedPreferencesUtil.get(this, SharedPreferencesUtil.SP_SETTINGS).getInt("translucent_background_blur", 0); - Button customColorBtn = (Button) findViewById(R.id.custom_color); - mSelectColor = findViewById(R.id.select_color); - Button selectPicBtn = (Button) findViewById(R.id.select_pic); - mProgress = findViewById(R.id.progress); - mProgress.setOnTouchListener((view, event) -> true); - RecyclerView recyclerView = (RecyclerView) findViewById(R.id.select_color_recycler_view); - mAdapter = new ThemeColorAdapter(this); - mAdapter.setOnItemClickListener((itemView, themeColor, position, viewType) -> { - SharedPreferencesUtil.get(this, SharedPreferencesUtil.SP_SETTINGS) - .edit() - .putString(SP_TRANSLUCENT_PRIMARY_COLOR, toString(themeColor)) - .commit(); - ThemeUtils.refreshUI(this); - }); - recyclerView.setLayoutManager(new MyLinearLayoutManager(this, MyLinearLayoutManager.HORIZONTAL, false)); - recyclerView.setAdapter(mAdapter); - SeekBar alphaSeekBar = (SeekBar) findViewById(R.id.alpha); - alphaSeekBar.setProgress(alpha); - SeekBar blueSeekBar = (SeekBar) findViewById(R.id.blur); - blueSeekBar.setProgress(blur); - alphaSeekBar.setOnSeekBarChangeListener(this); - blueSeekBar.setOnSeekBarChangeListener(this); - selectPicBtn.setOnClickListener(this); - customColorBtn.setOnClickListener(this); - findViewById(R.id.background).setBackgroundColor(Color.BLACK); - mProgress.setVisibility(View.GONE); - } - - @Override - public boolean onCreateOptionsMenu(Menu menu) { - getMenuInflater().inflate(R.menu.menu_translucent_theme_toolbar, menu); - return super.onCreateOptionsMenu(menu); - } - - @SuppressLint("ApplySharedPref") - @Override - public void onColorSelected(int dialogId, int color) { - SharedPreferencesUtil.get(this, SharedPreferencesUtil.SP_SETTINGS) - .edit() - .putString(SP_TRANSLUCENT_PRIMARY_COLOR, toString(color)) - .commit(); - ThemeUtils.refreshUI(this); - } - - @Override - public void onDialogDismissed(int dialogId) { - } - - @SuppressLint("ApplySharedPref") - @Override - public boolean onOptionsItemSelected(MenuItem item) { - switch (item.getItemId()) { - case R.id.menu_finish: - SharedPreferencesUtil.put(this, SharedPreferencesUtil.SP_SETTINGS, "translucent_background_alpha", alpha); - SharedPreferencesUtil.put(this, SharedPreferencesUtil.SP_SETTINGS, "translucent_background_blur", blur); - /* - saveOriginPic(file -> savePic(file1 -> { - ThemeUtil.getSharedPreferences(this) - .edit() - .putString(ThemeUtil.SP_THEME, THEME_TRANSLUCENT) - .putString(ThemeUtil.SP_OLD_THEME, THEME_TRANSLUCENT) - .commit(); - Toast.makeText(TranslucentThemeActivity.this, R.string.toast_save_pic_success, Toast.LENGTH_SHORT).show(); - mProgress.setVisibility(View.GONE); - finish(); - })); - */ - savePic(file -> { - ThemeUtil.getSharedPreferences(this) - .edit() - .putString(ThemeUtil.SP_THEME, THEME_TRANSLUCENT) - .putString(ThemeUtil.SP_OLD_THEME, THEME_TRANSLUCENT) - .commit(); - Toast.makeText(TranslucentThemeActivity.this, R.string.toast_save_pic_success, Toast.LENGTH_SHORT).show(); - BaseApplication.setTranslucentBackground(null); - mProgress.setVisibility(View.GONE); - finish(); - }); - return true; - case R.id.select_color: - return true; - } - return super.onOptionsItemSelected(item); - } - - private void savePic(SavePicCallback callback) { - mProgress.setVisibility(View.VISIBLE); - RequestOptions bgOptions = RequestOptions.centerCropTransform() - .skipMemoryCache(true) - .diskCacheStrategy(DiskCacheStrategy.NONE); - if (blur > 0) { - bgOptions = bgOptions.transform(new BlurTransformation(blur)); - } - Glide.with(this) - .asDrawable() - .load(mUri) - .apply(bgOptions) - .into(new SimpleTarget() { - @Override - public void onResourceReady(@NonNull Drawable resource, @Nullable Transition transition) { - resource.setAlpha(alpha); - Bitmap bitmap = ImageUtil.drawableToBitmap(resource); - File file = ImageUtil.compressImage(bitmap, new File(getFilesDir(), "background.jpg")); - mPalette = Palette.from(bitmap).generate(); - SharedPreferencesUtil.put(TranslucentThemeActivity.this, - SharedPreferencesUtil.SP_SETTINGS, - ThemeUtil.SP_TRANSLUCENT_THEME_BACKGROUND_PATH, - file.getAbsolutePath()); - ThemeUtils.refreshUI(TranslucentThemeActivity.this, TranslucentThemeActivity.this); - callback.onSuccess(file); - } - }); - } - - @Override - public boolean onPrepareOptionsMenu(Menu menu) { - MenuItem finishItem = menu.findItem(R.id.menu_finish); - finishItem.setEnabled(mUri != null); - return super.onPrepareOptionsMenu(menu); - } - - private void saveOriginPic(SavePicCallback callback) { - mProgress.setVisibility(View.VISIBLE); - RequestOptions bgOptions = RequestOptions.centerCropTransform() - .skipMemoryCache(true) - .diskCacheStrategy(DiskCacheStrategy.NONE); - Glide.with(this) - .asFile() - .load(mUri) - .apply(bgOptions) - .into(new SimpleTarget() { - @Override - public void onResourceReady(@NonNull File resource, @Nullable Transition transition) { - File file = new File(getFilesDir(), "origin_background_file.jpg"); - ImageUtil.copyFile(resource, file); - SharedPreferencesUtil.put(TranslucentThemeActivity.this, - SharedPreferencesUtil.SP_SETTINGS, - "translucent_background_origin_path", - file.getAbsolutePath()); - callback.onSuccess(file); - } - }); - } - - @Override - public void onProgressChanged(SeekBar seekBar, int progress, boolean fromUser) { - } - - @Override - public void onStartTrackingTouch(SeekBar seekBar) { - } - - @Override - public void onStopTrackingTouch(SeekBar seekBar) { - switch (seekBar.getId()) { - case R.id.alpha: - alpha = seekBar.getProgress(); - break; - case R.id.blur: - blur = seekBar.getProgress(); - break; - } - refreshBackground(); - } - - @Override - public void onClick(View v) { - switch (v.getId()) { - case R.id.select_pic: - askPermission(data -> Matisse.from(this) - .choose(MimeType.ofImage()) - .theme(ThemeUtil.isNightMode(this) ? R.style.Matisse_Dracula : R.style.Matisse_Zhihu) - .imageEngine(new MyImageEngine()) - .forResult(REQUEST_CODE_CHOOSE)); - break; - case R.id.custom_color: - ColorPickerDialog primaryColorPicker = ColorPickerDialog.newBuilder() - .setDialogTitle(R.string.title_color_picker_primary) - .setDialogType(ColorPickerDialog.TYPE_CUSTOM) - .setShowAlphaSlider(true) - .setDialogId(0) - .setAllowPresets(false) - .setColor(ThemeUtils.getColorById(this, R.color.default_color_primary)) - .create(); - primaryColorPicker.setColorPickerDialogListener(this); - primaryColorPicker.show(getFragmentManager(), "ColorPicker_TranslucentThemePrimaryColor"); - break; - } - } - - private void askPermission(Action> granted) { - if (Build.VERSION.SDK_INT < Build.VERSION_CODES.Q) { - PermissionUtil.askPermission(this, granted, R.string.toast_no_permission_insert_photo, - new PermissionUtil.Permission(Permission.Group.STORAGE, getString(R.string.tip_permission_storage))); - } else { - PermissionUtil.askPermission(this, granted, R.string.toast_no_permission_insert_photo, - new PermissionUtil.Permission(Permission.READ_EXTERNAL_STORAGE, getString(R.string.tip_permission_storage))); - } - } - - public interface SavePicCallback { - void onSuccess(T t); - } -} diff --git a/app/src/main/java/com/huanchengfly/tieba/post/activities/TranslucentThemeActivity.kt b/app/src/main/java/com/huanchengfly/tieba/post/activities/TranslucentThemeActivity.kt new file mode 100644 index 00000000..41cc3072 --- /dev/null +++ b/app/src/main/java/com/huanchengfly/tieba/post/activities/TranslucentThemeActivity.kt @@ -0,0 +1,344 @@ +package com.huanchengfly.tieba.post.activities + +import android.annotation.SuppressLint +import android.app.Activity +import android.content.Intent +import android.graphics.Bitmap +import android.graphics.Color +import android.graphics.drawable.BitmapDrawable +import android.graphics.drawable.Drawable +import android.net.Uri +import android.os.Build +import android.os.Bundle +import android.view.Menu +import android.view.MenuItem +import android.view.MotionEvent +import android.view.View +import android.widget.Button +import android.widget.SeekBar +import android.widget.SeekBar.OnSeekBarChangeListener +import android.widget.TextView +import androidx.annotation.ColorInt +import androidx.appcompat.widget.Toolbar +import androidx.core.text.HtmlCompat +import androidx.palette.graphics.Palette +import androidx.recyclerview.widget.RecyclerView +import butterknife.BindView +import com.bumptech.glide.Glide +import com.bumptech.glide.load.engine.DiskCacheStrategy +import com.bumptech.glide.request.RequestOptions +import com.bumptech.glide.request.target.CustomTarget +import com.bumptech.glide.request.transition.Transition +import com.gyf.immersionbar.ImmersionBar +import com.huanchengfly.tieba.post.BaseApplication +import com.huanchengfly.tieba.post.BaseApplication.Companion.translucentBackground +import com.huanchengfly.tieba.post.R +import com.huanchengfly.tieba.post.adapters.ThemeColorAdapter +import com.huanchengfly.tieba.post.components.MyImageEngine +import com.huanchengfly.tieba.post.components.MyLinearLayoutManager +import com.huanchengfly.tieba.post.components.transformations.BlurTransformation +import com.huanchengfly.tieba.post.interfaces.OnItemClickListener +import com.huanchengfly.tieba.post.toastShort +import com.huanchengfly.tieba.post.ui.theme.utils.ThemeUtils +import com.huanchengfly.tieba.post.utils.ColorUtils +import com.huanchengfly.tieba.post.utils.ImageUtil +import com.huanchengfly.tieba.post.utils.PermissionUtil +import com.huanchengfly.tieba.post.utils.ThemeUtil +import com.jrummyapps.android.colorpicker.ColorPickerDialog +import com.jrummyapps.android.colorpicker.ColorPickerDialogListener +import com.yalantis.ucrop.UCrop +import com.yanzhenjie.permission.Action +import com.yanzhenjie.permission.runtime.Permission +import com.zhihu.matisse.Matisse +import com.zhihu.matisse.MimeType +import java.io.File + +class TranslucentThemeActivity : BaseActivity(), View.OnClickListener, OnSeekBarChangeListener, ColorPickerDialogListener { + private var mUri: Uri? = null + private var alpha = 0 + private var blur = 0 + private var mPalette: Palette? = null + + @BindView(R.id.select_color) + lateinit var mSelectColor: View + private var mAdapter: ThemeColorAdapter? = null + + @BindView(R.id.progress) + lateinit var mProgress: View + override fun onActivityResult(requestCode: Int, resultCode: Int, data: Intent?) { + super.onActivityResult(requestCode, resultCode, data) + if (requestCode == REQUEST_CODE_CHOOSE && resultCode == Activity.RESULT_OK) { + val sourceUri = Matisse.obtainResult(data)[0] + Glide.with(this) + .asDrawable() + .load(sourceUri) + .into(object : CustomTarget() { + override fun onLoadCleared(placeholder: Drawable?) {} + + override fun onResourceReady(resource: Drawable, transition: Transition?) { + val bitmap = ImageUtil.drawableToBitmap(resource) + val file = ImageUtil.bitmapToFile(bitmap, File(cacheDir, "origin_background.jpg")) + val sourceFileUri = Uri.fromFile(file) + val destUri = Uri.fromFile(File(cacheDir, "cropped_background.jpg")) + val height = BaseApplication.ScreenInfo.EXACT_SCREEN_HEIGHT.toFloat() + val width = BaseApplication.ScreenInfo.EXACT_SCREEN_WIDTH.toFloat() + val uCropOptions = UCrop.Options() + uCropOptions.setShowCropFrame(true) + uCropOptions.setShowCropGrid(true) + uCropOptions.setStatusBarColor(ColorUtils.getDarkerColor(ThemeUtils.getColorByAttr(this@TranslucentThemeActivity, R.attr.colorPrimary))) + uCropOptions.setToolbarColor(ThemeUtils.getColorByAttr(this@TranslucentThemeActivity, R.attr.colorPrimary)) + uCropOptions.setToolbarWidgetColor(ThemeUtils.getColorByAttr(this@TranslucentThemeActivity, R.attr.colorTextOnPrimary)) + uCropOptions.setActiveWidgetColor(ThemeUtils.getColorByAttr(this@TranslucentThemeActivity, R.attr.colorAccent)) + uCropOptions.setActiveControlsWidgetColor(ThemeUtils.getColorByAttr(this@TranslucentThemeActivity, R.attr.colorAccent)) + uCropOptions.setLogoColor(ThemeUtils.getColorByAttr(this@TranslucentThemeActivity, R.attr.colorPrimary)) + uCropOptions.setCompressionFormat(Bitmap.CompressFormat.JPEG) + UCrop.of(sourceFileUri, destUri) + .withAspectRatio(width / height, 1f) + .withOptions(uCropOptions) + .start(this@TranslucentThemeActivity) + } + }) + } else if (resultCode == Activity.RESULT_OK && requestCode == UCrop.REQUEST_CROP) { + mUri = UCrop.getOutput(data!!) + invalidateOptionsMenu() + refreshBackground() + } else if (resultCode == UCrop.RESULT_ERROR) { + val cropError = UCrop.getError(data!!) + cropError!!.printStackTrace() + } + } + + private fun refreshBackground() { + mProgress.visibility = View.VISIBLE + if (mUri == null) { + findViewById(R.id.background).setBackgroundColor(Color.BLACK) + mProgress.visibility = View.GONE + return + } + var bgOptions = RequestOptions.centerCropTransform() + .skipMemoryCache(true) + .diskCacheStrategy(DiskCacheStrategy.NONE) + if (blur > 0) { + bgOptions = bgOptions.transform(BlurTransformation(blur)) + } + Glide.with(this) + .asDrawable() + .load(mUri) + .apply(bgOptions) + .into(object : CustomTarget() { + override fun onResourceReady(resource: Drawable, transition: Transition?) { + resource.alpha = alpha + val bitmap = ImageUtil.drawableToBitmap(resource) + findViewById(R.id.background).backgroundTintList = null + findViewById(R.id.background).background = BitmapDrawable(resources, bitmap) + mPalette = Palette.from(bitmap).generate() + mAdapter!!.setPalette(mPalette) + mSelectColor.visibility = View.VISIBLE + mProgress.visibility = View.GONE + } + + override fun onLoadCleared(placeholder: Drawable?) {} + }) + } + + override fun refreshStatusBarColor() { + ImmersionBar.with(this) + .transparentBar() + .init() + } + + override fun getLayoutId(): Int { + return R.layout.activity_translucent_theme + } + + @SuppressLint("ApplySharedPref", "ClickableViewAccessibility") + override fun onCreate(savedInstanceState: Bundle?) { + super.onCreate(savedInstanceState) + setSupportActionBar(findViewById(R.id.toolbar) as Toolbar) + supportActionBar!!.setDisplayHomeAsUpEnabled(true) + supportActionBar!!.setTitle(R.string.title_dialog_translucent_theme) + (findViewById(R.id.tip) as TextView).apply { + text = HtmlCompat.fromHtml(getString(R.string.tip_translucent_theme), HtmlCompat.FROM_HTML_MODE_LEGACY) + } + (findViewById(R.id.custom_color) as Button).apply { + setOnClickListener(this@TranslucentThemeActivity) + } + (findViewById(R.id.select_pic) as Button).apply { + setOnClickListener(this@TranslucentThemeActivity) + } + mAdapter = ThemeColorAdapter(this) + mAdapter!!.onItemClickListener = OnItemClickListener { _: View?, themeColor: Int, _: Int, _: Int -> + appPreferences.translucentPrimaryColor = toString(themeColor) + ThemeUtils.refreshUI(this) + } + (findViewById(R.id.select_color_recycler_view) as RecyclerView).apply { + layoutManager = MyLinearLayoutManager(this@TranslucentThemeActivity, MyLinearLayoutManager.HORIZONTAL, false) + adapter = mAdapter + } + alpha = appPreferences.translucentBackgroundAlpha + blur = appPreferences.translucentBackgroundBlur + (findViewById(R.id.alpha) as SeekBar).apply { + progress = this@TranslucentThemeActivity.alpha + setOnSeekBarChangeListener(this@TranslucentThemeActivity) + } + (findViewById(R.id.blur) as SeekBar).apply { + progress = this@TranslucentThemeActivity.blur + setOnSeekBarChangeListener(this@TranslucentThemeActivity) + } + mProgress.setOnTouchListener { _: View?, _: MotionEvent? -> true } + mProgress.visibility = View.GONE + findViewById(R.id.background).setBackgroundColor(Color.BLACK) + } + + override fun onCreateOptionsMenu(menu: Menu): Boolean { + menuInflater.inflate(R.menu.menu_translucent_theme_toolbar, menu) + return super.onCreateOptionsMenu(menu) + } + + @SuppressLint("ApplySharedPref") + override fun onColorSelected(dialogId: Int, color: Int) { + appPreferences.translucentPrimaryColor = toString(color) + ThemeUtils.refreshUI(this) + } + + override fun onDialogDismissed(dialogId: Int) {} + + @SuppressLint("ApplySharedPref") + override fun onOptionsItemSelected(item: MenuItem): Boolean { + when (item.itemId) { + R.id.menu_finish -> { + appPreferences.apply { + translucentBackgroundAlpha = alpha + translucentBackgroundBlur = blur + } + savePic(object : SavePicCallback { + override fun onSuccess(t: File) { + ThemeUtil.getSharedPreferences(this@TranslucentThemeActivity) + .edit() + .putString(ThemeUtil.SP_THEME, ThemeUtil.THEME_TRANSLUCENT) + .putString(ThemeUtil.SP_OLD_THEME, ThemeUtil.THEME_TRANSLUCENT) + .commit() + toastShort(R.string.toast_save_pic_success) + translucentBackground = null + mProgress.visibility = View.GONE + finish() + } + }) + return true + } + R.id.select_color -> return true + } + return super.onOptionsItemSelected(item) + } + + private fun savePic(callback: SavePicCallback) { + mProgress.visibility = View.VISIBLE + var bgOptions = RequestOptions.centerCropTransform() + .skipMemoryCache(true) + .diskCacheStrategy(DiskCacheStrategy.NONE) + if (blur > 0) { + bgOptions = bgOptions.transform(BlurTransformation(blur)) + } + Glide.with(this) + .asDrawable() + .load(mUri) + .apply(bgOptions) + .into(object : CustomTarget() { + override fun onResourceReady(resource: Drawable, transition: Transition?) { + resource.alpha = alpha + val bitmap = ImageUtil.drawableToBitmap(resource) + val file = ImageUtil.compressImage(bitmap, File(filesDir, "background.jpg")) + mPalette = Palette.from(bitmap).generate() + appPreferences.translucentThemeBackgroundPath = file.absolutePath + ThemeUtils.refreshUI(this@TranslucentThemeActivity, this@TranslucentThemeActivity) + callback.onSuccess(file) + } + + override fun onLoadCleared(placeholder: Drawable?) {} + }) + } + + override fun onPrepareOptionsMenu(menu: Menu): Boolean { + val finishItem = menu.findItem(R.id.menu_finish) + finishItem.isEnabled = mUri != null + return super.onPrepareOptionsMenu(menu) + } + + override fun onProgressChanged(seekBar: SeekBar, progress: Int, fromUser: Boolean) {} + override fun onStartTrackingTouch(seekBar: SeekBar) {} + override fun onStopTrackingTouch(seekBar: SeekBar) { + when (seekBar.id) { + R.id.alpha -> alpha = seekBar.progress + R.id.blur -> blur = seekBar.progress + } + refreshBackground() + } + + override fun onClick(v: View) { + when (v.id) { + R.id.select_pic -> askPermission(Action { + Matisse.from(this) + .choose(MimeType.ofImage()) + .theme(if (ThemeUtil.isNightMode(this)) R.style.Matisse_Dracula else R.style.Matisse_Zhihu) + .imageEngine(MyImageEngine()) + .forResult(REQUEST_CODE_CHOOSE) + }) + R.id.custom_color -> { + val primaryColorPicker = ColorPickerDialog.newBuilder() + .setDialogTitle(R.string.title_color_picker_primary) + .setDialogType(ColorPickerDialog.TYPE_CUSTOM) + .setShowAlphaSlider(true) + .setDialogId(0) + .setAllowPresets(false) + .setColor(ThemeUtils.getColorById(this, R.color.default_color_primary)) + .create() + primaryColorPicker.setColorPickerDialogListener(this) + primaryColorPicker.show(fragmentManager, "ColorPicker_TranslucentThemePrimaryColor") + } + } + } + + private fun askPermission(granted: Action>) { + if (Build.VERSION.SDK_INT < Build.VERSION_CODES.Q) { + PermissionUtil.askPermission(this, granted, R.string.toast_no_permission_insert_photo, + PermissionUtil.Permission(Permission.Group.STORAGE, getString(R.string.tip_permission_storage))) + } else { + PermissionUtil.askPermission(this, granted, R.string.toast_no_permission_insert_photo, + PermissionUtil.Permission(Permission.READ_EXTERNAL_STORAGE, getString(R.string.tip_permission_storage))) + } + } + + interface SavePicCallback { + fun onSuccess(t: T) + } + + companion object { + val TAG = TranslucentThemeActivity::class.java.simpleName + const val REQUEST_CODE_CHOOSE = 2 + fun toString(alpha: Int, red: Int, green: Int, blue: Int): String { + val hr = Integer.toHexString(red) + val hg = Integer.toHexString(green) + val hb = Integer.toHexString(blue) + val ha = Integer.toHexString(alpha) + return "#" + fixHexString(ha) + fixHexString(hr) + fixHexString(hg) + fixHexString(hb) + } + + private fun fixHexString(string: String): String { + var hexStr = string + if (hexStr.isEmpty()) { + hexStr = "00" + } + if (hexStr.length == 1) { + hexStr = "0$hexStr" + } + if (hexStr.length > 2) { + hexStr = hexStr.substring(0, 2) + } + return hexStr + } + + fun toString(@ColorInt color: Int): String { + return toString(Color.alpha(color), Color.red(color), Color.green(color), Color.blue(color)) + } + } +} \ No newline at end of file diff --git a/app/src/main/java/com/huanchengfly/tieba/post/api/LiteApi.kt b/app/src/main/java/com/huanchengfly/tieba/post/api/LiteApi.kt index 9d7b65f6..82e51429 100644 --- a/app/src/main/java/com/huanchengfly/tieba/post/api/LiteApi.kt +++ b/app/src/main/java/com/huanchengfly/tieba/post/api/LiteApi.kt @@ -2,13 +2,14 @@ package com.huanchengfly.tieba.post.api import android.annotation.SuppressLint import android.content.Context +import com.huanchengfly.tieba.post.BaseApplication import com.huanchengfly.tieba.post.api.interfaces.CommonAPICallback import com.huanchengfly.tieba.post.api.models.ChangelogBean import com.huanchengfly.tieba.post.api.models.NewUpdateBean import com.huanchengfly.tieba.post.api.models.UpdateInfoBean -import com.huanchengfly.tieba.post.BaseApplication import com.huanchengfly.tieba.post.utils.SharedPreferencesUtil import com.huanchengfly.tieba.post.utils.VersionUtil +import com.huanchengfly.tieba.post.utils.appPreferences import com.tsy.sdk.myokhttp.MyOkHttp import com.tsy.sdk.myokhttp.response.GsonResponseHandler import io.michaelrocks.paranoid.Obfuscate @@ -18,8 +19,8 @@ import java.lang.ref.WeakReference class LiteApi private constructor(context: Context) { private val myOkHttp: MyOkHttp = MyOkHttp() private val contextWeakReference: WeakReference = WeakReference(context) - val context: Context? - get() = contextWeakReference.get() + val context: Context + get() = contextWeakReference.get()!! fun changelog(apiCallback: CommonAPICallback) { val builder = myOkHttp.get() @@ -44,7 +45,7 @@ class LiteApi private constructor(context: Context) { } fun newCheckUpdate(apiCallback: CommonAPICallback) { - val beta = SharedPreferencesUtil.get(context, SharedPreferencesUtil.SP_SETTINGS).getBoolean("check_beta_update", false) + val beta = context.appPreferences.checkBetaUpdate myOkHttp.get() .url(Url.CHECK_UPDATE) .addParam("version_code", VersionUtil.getVersionCode(context).toString()) diff --git a/app/src/main/java/com/huanchengfly/tieba/post/components/dialogs/CustomThemeDialog.java b/app/src/main/java/com/huanchengfly/tieba/post/components/dialogs/CustomThemeDialog.java deleted file mode 100644 index 2be436d9..00000000 --- a/app/src/main/java/com/huanchengfly/tieba/post/components/dialogs/CustomThemeDialog.java +++ /dev/null @@ -1,154 +0,0 @@ -package com.huanchengfly.tieba.post.components.dialogs; - -import android.annotation.SuppressLint; -import android.content.Context; -import android.content.DialogInterface; -import android.content.res.ColorStateList; -import android.graphics.Color; -import android.view.View; -import android.widget.CheckBox; -import android.widget.CompoundButton; -import android.widget.LinearLayout; - -import androidx.annotation.ColorInt; -import androidx.annotation.NonNull; -import androidx.appcompat.app.AlertDialog; - -import com.huanchengfly.tieba.post.ui.theme.utils.ThemeUtils; -import com.huanchengfly.tieba.post.R; -import com.huanchengfly.tieba.post.BaseApplication; -import com.huanchengfly.tieba.post.utils.SharedPreferencesUtil; -import com.jrummyapps.android.colorpicker.ColorPickerDialog; -import com.jrummyapps.android.colorpicker.ColorPickerDialogListener; - -import java.util.Objects; - -import static com.huanchengfly.tieba.post.utils.ThemeUtil.SP_CUSTOM_PRIMARY_COLOR; -import static com.huanchengfly.tieba.post.utils.ThemeUtil.SP_CUSTOM_STATUS_BAR_FONT_DARK; -import static com.huanchengfly.tieba.post.utils.ThemeUtil.SP_CUSTOM_TOOLBAR_PRIMARY_COLOR; -import static com.huanchengfly.tieba.post.utils.ThemeUtil.THEME_CUSTOM; - -public class CustomThemeDialog extends AlertDialog implements View.OnClickListener, DialogInterface.OnClickListener, CompoundButton.OnCheckedChangeListener, ColorPickerDialogListener { - private LinearLayout primaryColorLayout; - private View primaryColorView; - private CheckBox statusBarFont; - private CheckBox toolbarPrimaryColor; - private int primaryColor; - private boolean statusBarFontDark; - private boolean toolbarPrimary; - - public CustomThemeDialog(@NonNull Context context) { - super(context); - setButton(BUTTON_POSITIVE, context.getString(R.string.button_finish), this); - setCancelable(false); - setTitle(R.string.title_custom_theme); - initView(); - initListener(); - } - - public static String toString(int alpha, int red, int green, int blue) { - String hr = Integer.toHexString(red); - String hg = Integer.toHexString(green); - String hb = Integer.toHexString(blue); - String ha = Integer.toHexString(alpha); - return "#" + fixHexString(ha) + fixHexString(hr) + fixHexString(hg) + fixHexString(hb); - } - - public static String fixHexString(String hexString) { - if (hexString.length() < 1) { - hexString = "00"; - } - if (hexString.length() == 1) { - hexString = "0" + hexString; - } - if (hexString.length() > 2) { - hexString = hexString.substring(0, 2); - } - return hexString; - } - - public static String toString(@ColorInt int color) { - return toString(Color.alpha(color), Color.red(color), Color.green(color), Color.blue(color)); - } - - private void initListener() { - primaryColorLayout.setOnClickListener(this); - statusBarFont.setOnCheckedChangeListener(this); - toolbarPrimaryColor.setOnCheckedChangeListener(this); - } - - private void initView() { - View contentView = View.inflate(getContext(), R.layout.dialog_custom_theme, null); - primaryColorLayout = contentView.findViewById(R.id.custom_theme_primary_holder); - primaryColorView = contentView.findViewById(R.id.custom_theme_primary); - statusBarFont = contentView.findViewById(R.id.custom_theme_status_bar_font); - toolbarPrimaryColor = contentView.findViewById(R.id.custom_theme_toolbar_primary_color); - setView(contentView); - primaryColor = BaseApplication.ThemeDelegate.INSTANCE.getColorByAttr(getContext(), R.attr.colorPrimary, THEME_CUSTOM); - statusBarFontDark = SharedPreferencesUtil.get(getContext(), SharedPreferencesUtil.SP_SETTINGS) - .getBoolean(SP_CUSTOM_STATUS_BAR_FONT_DARK, false); - toolbarPrimary = SharedPreferencesUtil.get(getContext(), SharedPreferencesUtil.SP_SETTINGS) - .getBoolean(SP_CUSTOM_TOOLBAR_PRIMARY_COLOR, true); - refreshView(); - } - - private void refreshView() { - primaryColorView.setBackgroundTintList(ColorStateList.valueOf(primaryColor)); - statusBarFont.setChecked(statusBarFontDark); - toolbarPrimaryColor.setChecked(toolbarPrimary); - statusBarFont.setVisibility(toolbarPrimary ? View.VISIBLE : View.GONE); - ThemeUtils.refreshUI(getContext()); - } - - @Override - public void onClick(View v) { - if (v.getId() == R.id.custom_theme_primary_holder) { - ColorPickerDialog primaryColorPicker = ColorPickerDialog.newBuilder() - .setDialogTitle(R.string.title_color_picker_primary) - .setDialogType(ColorPickerDialog.TYPE_PRESETS) - .setShowAlphaSlider(false) - .setDialogId(0) - .setAllowPresets(true) - .setColor(primaryColor) - .create(); - primaryColorPicker.setColorPickerDialogListener(this); - primaryColorPicker.show(Objects.requireNonNull(ThemeUtils.getWrapperActivity(getContext())).getFragmentManager(), "ColorPicker_PrimaryColor"); - } - refreshView(); - } - - @SuppressLint("ApplySharedPref") - @Override - public void onClick(DialogInterface dialog, int which) { - SharedPreferencesUtil.get(getContext(), SharedPreferencesUtil.SP_SETTINGS) - .edit() - .putString(SP_CUSTOM_PRIMARY_COLOR, toString(primaryColor)) - .putBoolean(SP_CUSTOM_STATUS_BAR_FONT_DARK, statusBarFontDark || !toolbarPrimary) - .putBoolean(SP_CUSTOM_TOOLBAR_PRIMARY_COLOR, toolbarPrimary) - .commit(); - dialog.dismiss(); - } - - @Override - public void onCheckedChanged(CompoundButton buttonView, boolean isChecked) { - if (buttonView.getId() == R.id.custom_theme_status_bar_font) { - statusBarFontDark = isChecked; - } else if (buttonView.getId() == R.id.custom_theme_toolbar_primary_color) { - toolbarPrimary = isChecked; - statusBarFontDark = !isChecked; - } - refreshView(); - } - - @Override - public void onColorSelected(int dialogId, int color) { - if (dialogId == 0) { - primaryColor = color; - refreshView(); - } - } - - @Override - public void onDialogDismissed(int dialogId) { - } -} diff --git a/app/src/main/java/com/huanchengfly/tieba/post/components/dialogs/CustomThemeDialog.kt b/app/src/main/java/com/huanchengfly/tieba/post/components/dialogs/CustomThemeDialog.kt new file mode 100644 index 00000000..027dc4fe --- /dev/null +++ b/app/src/main/java/com/huanchengfly/tieba/post/components/dialogs/CustomThemeDialog.kt @@ -0,0 +1,139 @@ +package com.huanchengfly.tieba.post.components.dialogs + +import android.annotation.SuppressLint +import android.content.Context +import android.content.DialogInterface +import android.content.res.ColorStateList +import android.graphics.Color +import android.view.View +import android.widget.CheckBox +import android.widget.CompoundButton +import android.widget.LinearLayout +import androidx.annotation.ColorInt +import androidx.appcompat.app.AlertDialog +import com.huanchengfly.tieba.post.BaseApplication.ThemeDelegate.getColorByAttr +import com.huanchengfly.tieba.post.R +import com.huanchengfly.tieba.post.ui.theme.utils.ThemeUtils +import com.huanchengfly.tieba.post.utils.ThemeUtil +import com.huanchengfly.tieba.post.utils.appPreferences +import com.jrummyapps.android.colorpicker.ColorPickerDialog +import com.jrummyapps.android.colorpicker.ColorPickerDialogListener +import java.util.* + +class CustomThemeDialog(context: Context) : AlertDialog(context), + View.OnClickListener, DialogInterface.OnClickListener, CompoundButton.OnCheckedChangeListener, ColorPickerDialogListener { + private var primaryColorLayout: LinearLayout? = null + private var primaryColorView: View? = null + private var statusBarFont: CheckBox? = null + private var toolbarPrimaryColor: CheckBox? = null + private var primaryColor = 0 + private var statusBarFontDark = false + private var toolbarPrimary = false + private fun initListener() { + primaryColorLayout!!.setOnClickListener(this) + statusBarFont!!.setOnCheckedChangeListener(this) + toolbarPrimaryColor!!.setOnCheckedChangeListener(this) + } + + private fun initView() { + val contentView = View.inflate(context, R.layout.dialog_custom_theme, null) + primaryColorLayout = contentView.findViewById(R.id.custom_theme_primary_holder) + primaryColorView = contentView.findViewById(R.id.custom_theme_primary) + statusBarFont = contentView.findViewById(R.id.custom_theme_status_bar_font) + toolbarPrimaryColor = contentView.findViewById(R.id.custom_theme_toolbar_primary_color) + setView(contentView) + primaryColor = getColorByAttr(context, R.attr.colorPrimary, ThemeUtil.THEME_CUSTOM) + statusBarFontDark = context.appPreferences.customStatusBarFontDark + toolbarPrimary = context.appPreferences.customToolbarPrimaryColor + refreshView() + } + + private fun refreshView() { + primaryColorView!!.backgroundTintList = ColorStateList.valueOf(primaryColor) + statusBarFont!!.isChecked = statusBarFontDark + toolbarPrimaryColor!!.isChecked = toolbarPrimary + statusBarFont!!.visibility = if (toolbarPrimary) View.VISIBLE else View.GONE + ThemeUtils.refreshUI(context) + } + + override fun onClick(v: View) { + if (v.id == R.id.custom_theme_primary_holder) { + val primaryColorPicker = ColorPickerDialog.newBuilder() + .setDialogTitle(R.string.title_color_picker_primary) + .setDialogType(ColorPickerDialog.TYPE_PRESETS) + .setShowAlphaSlider(false) + .setDialogId(0) + .setAllowPresets(true) + .setColor(primaryColor) + .create() + primaryColorPicker.setColorPickerDialogListener(this) + primaryColorPicker.show(Objects.requireNonNull(ThemeUtils.getWrapperActivity(context)).fragmentManager, "ColorPicker_PrimaryColor") + } + refreshView() + } + + @SuppressLint("ApplySharedPref") + override fun onClick(dialog: DialogInterface, which: Int) { + context.appPreferences.apply { + customPrimaryColor = toString(primaryColor) + customStatusBarFontDark = (statusBarFontDark || !toolbarPrimary) + customToolbarPrimaryColor = toolbarPrimary + } + dialog.dismiss() + } + + override fun onCheckedChanged(buttonView: CompoundButton, isChecked: Boolean) { + if (buttonView.id == R.id.custom_theme_status_bar_font) { + statusBarFontDark = isChecked + } else if (buttonView.id == R.id.custom_theme_toolbar_primary_color) { + toolbarPrimary = isChecked + statusBarFontDark = !isChecked + } + refreshView() + } + + override fun onColorSelected(dialogId: Int, color: Int) { + if (dialogId == 0) { + primaryColor = color + refreshView() + } + } + + override fun onDialogDismissed(dialogId: Int) {} + + companion object { + fun toString(alpha: Int, red: Int, green: Int, blue: Int): String { + val hr = Integer.toHexString(red) + val hg = Integer.toHexString(green) + val hb = Integer.toHexString(blue) + val ha = Integer.toHexString(alpha) + return "#" + fixHexString(ha) + fixHexString(hr) + fixHexString(hg) + fixHexString(hb) + } + + private fun fixHexString(hex: String): String { + var hexString = hex + if (hexString.isEmpty()) { + hexString = "00" + } + if (hexString.length == 1) { + hexString = "0$hexString" + } + if (hexString.length > 2) { + hexString = hexString.substring(0, 2) + } + return hexString + } + + fun toString(@ColorInt color: Int): String { + return toString(Color.alpha(color), Color.red(color), Color.green(color), Color.blue(color)) + } + } + + init { + setButton(DialogInterface.BUTTON_POSITIVE, context.getString(R.string.button_finish), this) + setCancelable(false) + setTitle(R.string.title_custom_theme) + initView() + initListener() + } +} \ No newline at end of file diff --git a/app/src/main/java/com/huanchengfly/tieba/post/fragments/BaseFragment.java b/app/src/main/java/com/huanchengfly/tieba/post/fragments/BaseFragment.java index 7e498193..6bdcfc35 100644 --- a/app/src/main/java/com/huanchengfly/tieba/post/fragments/BaseFragment.java +++ b/app/src/main/java/com/huanchengfly/tieba/post/fragments/BaseFragment.java @@ -26,12 +26,11 @@ import butterknife.ButterKnife; import butterknife.Unbinder; /** - * Created by dasu on 2016/9/27. *

* Fragment基类,封装了懒加载的实现 *

- * 1、Viewpager + Fragment情况下,fragment的生命周期因Viewpager的缓存机制而失去了具体意义 - * 该抽象类自定义新的回调方法,当fragment可见状态改变时会触发的回调方法,和 Fragment 第一次可见时会回调的方法 + * ViewPager + Fragment 情况下,Fragment 的生命周期因 ViewPager 的缓存机制而失去了具体意义 + * 该抽象类自定义新的回调方法,当 Fragment 可见状态改变时会触发的回调方法,和 Fragment 第一次可见时会回调的方法 * * @see #onFragmentVisibleChange(boolean) * @see #onFragmentFirstVisible() @@ -171,18 +170,18 @@ public abstract class BaseFragment extends Fragment implements BackHandledInterf /** * 设置是否使用 view 的复用,默认开启 - * view 的复用是指,ViewPager 在销毁和重建 MessageListFragment 时会不断调用 onCreateView() -> onDestroyView() - * 之间的生命函数,这样可能会出现重复创建 view 的情况,导致界面上显示多个相同的 MessageListFragment + * view 的复用是指,ViewPager 在销毁和重建 Fragment 时会不断调用 onCreateView() -> onDestroyView() + * 之间的生命函数,这样可能会出现重复创建 view 的情况,导致界面上显示多个相同的 Fragment * view 的复用其实就是指保存第一次创建的 view,后面再 onCreateView() 时直接返回第一次创建的 view * - * @param isReuse + * @param isReuse 是否使用 view 的复用 */ protected void reuseView(boolean isReuse) { isReuseView = isReuse; } /** - * 去除setUserVisibleHint()多余的回调场景,保证只有当fragment可见状态发生变化时才回调 + * 去除 setUserVisibleHint() 多余的回调场景,保证只有当 Fragment 可见状态发生变化时才回调 * 回调时机在view创建完后,所以支持ui操作,解决在setUserVisibleHint()里进行ui操作有可能报null异常的问题 *

* 可在该回调方法里进行一些ui显示与隐藏,比如加载框的显示和隐藏 @@ -194,7 +193,7 @@ public abstract class BaseFragment extends Fragment implements BackHandledInterf } /** - * 在fragment首次可见时回调,可在这里进行加载数据,保证只在第一次打开Fragment时才会加载数据, + * 在 Fragment 首次可见时回调,可在这里进行加载数据,保证只在第一次打开 Fragment 时才会加载数据, * 这样就可以防止每次进入都重复加载数据 * 该方法会在 onFragmentVisibleChange() 之前调用,所以第一次打开时,可以用一个全局变量表示数据下载状态, * 然后在该方法内将状态设置为下载状态,接着去执行下载的任务 diff --git a/app/src/main/java/com/huanchengfly/tieba/post/fragments/FloorFragment.kt b/app/src/main/java/com/huanchengfly/tieba/post/fragments/FloorFragment.kt index b8d56afb..ab84a474 100644 --- a/app/src/main/java/com/huanchengfly/tieba/post/fragments/FloorFragment.kt +++ b/app/src/main/java/com/huanchengfly/tieba/post/fragments/FloorFragment.kt @@ -73,7 +73,7 @@ class FloorFragment : BaseBottomSheetDialogFragment() { dataBean!!.post!!.id, dataBean!!.post!!.floor, dataBean!!.post!!.author.nameShow, - AccountUtil.getLoginInfo(attachContext).nameShow).setPn(pn.toString()).toString())) + AccountUtil.getLoginInfo(attachContext)!!.nameShow).setPn(pn.toString()).toString())) } override fun onStart() { diff --git a/app/src/main/java/com/huanchengfly/tieba/post/fragments/ForumListFragment.kt b/app/src/main/java/com/huanchengfly/tieba/post/fragments/ForumListFragment.kt index e3a457e6..cd35ecfd 100644 --- a/app/src/main/java/com/huanchengfly/tieba/post/fragments/ForumListFragment.kt +++ b/app/src/main/java/com/huanchengfly/tieba/post/fragments/ForumListFragment.kt @@ -11,6 +11,10 @@ import androidx.recyclerview.widget.GridLayoutManager.SpanSizeLookup import androidx.recyclerview.widget.RecyclerView import androidx.swiperefreshlayout.widget.SwipeRefreshLayout import butterknife.BindView +import com.huanchengfly.tieba.post.BaseApplication +import com.huanchengfly.tieba.post.R +import com.huanchengfly.tieba.post.activities.ForumActivity +import com.huanchengfly.tieba.post.adapters.LikeForumListAdapter import com.huanchengfly.tieba.post.api.Error import com.huanchengfly.tieba.post.api.ForumSortType import com.huanchengfly.tieba.post.api.TiebaApi @@ -18,10 +22,6 @@ import com.huanchengfly.tieba.post.api.models.CommonResponse import com.huanchengfly.tieba.post.api.models.ForumRecommend import com.huanchengfly.tieba.post.api.retrofit.exception.TiebaException import com.huanchengfly.tieba.post.api.retrofit.exception.TiebaLocalException -import com.huanchengfly.tieba.post.activities.ForumActivity -import com.huanchengfly.tieba.post.R -import com.huanchengfly.tieba.post.adapters.LikeForumListAdapter -import com.huanchengfly.tieba.post.BaseApplication import com.huanchengfly.tieba.post.interfaces.OnItemClickListener import com.huanchengfly.tieba.post.interfaces.OnItemLongClickListener import com.huanchengfly.tieba.post.interfaces.Refreshable @@ -55,7 +55,7 @@ class ForumListFragment : BaseFragment(), Refreshable { override fun onResume() { super.onResume() gridLayoutManager!!.spanCount = spanCount - likeForumListAdapter!!.isSingle = SharedPreferencesUtil.get(attachContext, SharedPreferencesUtil.SP_SETTINGS).getBoolean("listSingle", false) + likeForumListAdapter!!.isSingle = appPreferences.listSingle } override fun onAccountSwitch() { @@ -78,7 +78,7 @@ class ForumListFragment : BaseFragment(), Refreshable { } private val spanCount: Int - get() = if (SharedPreferencesUtil.get(attachContext, SharedPreferencesUtil.SP_SETTINGS).getBoolean("listSingle", false)) { + get() = if (appPreferences.listSingle) { 1 } else { 2 @@ -96,8 +96,7 @@ class ForumListFragment : BaseFragment(), Refreshable { } private fun getSortType(forumName: String): ForumSortType { - val defaultSortType = SharedPreferencesUtil.get(attachContext, SharedPreferencesUtil.SP_SETTINGS) - .getString("default_sort_type", ForumSortType.REPLY_TIME.toString())!!.toInt() + val defaultSortType = appPreferences.defaultSortType!!.toInt() return ForumSortType.valueOf(SharedPreferencesUtil.get(attachContext, SharedPreferencesUtil.SP_SETTINGS) .getInt(forumName + "_sort_type", defaultSortType)) } @@ -127,20 +126,22 @@ class ForumListFragment : BaseFragment(), Refreshable { topItem.setTitle(if (already) R.string.menu_top_del else R.string.menu_top) popupMenu.setOnMenuItemClickListener { item: MenuItem -> when (item.itemId) { - R.id.menu_top -> if (!SharedPreferencesUtil.get(attachContext, SharedPreferencesUtil.SP_SETTINGS).getBoolean("show_top_forum_in_normal_list", true)) { - DialogUtil.build(attachContext) - .setTitle(R.string.title_dialog_show_top_forum) - .setMessage(R.string.message_dialog_show_top_forum) - .setNegativeButton(R.string.button_no) { _, _ -> toggleTopForum(likeForum.forumId) } - .setPositiveButton(R.string.button_yes) { _, _ -> - SharedPreferencesUtil.get(attachContext, SharedPreferencesUtil.SP_SETTINGS).edit().putBoolean("show_top_forum_in_normal_list", true).commit() - toggleTopForum(likeForum.forumId) - } - .setNeutralButton(R.string.button_cancel, null) - .create() - .show() - } else { - toggleTopForum(likeForum.forumId) + R.id.menu_top -> { + if (!appPreferences.showTopForumInNormalList) { + DialogUtil.build(attachContext) + .setTitle(R.string.title_dialog_show_top_forum) + .setMessage(R.string.message_dialog_show_top_forum) + .setNegativeButton(R.string.button_no) { _, _ -> toggleTopForum(likeForum.forumId) } + .setPositiveButton(R.string.button_yes) { _, _ -> + SharedPreferencesUtil.get(attachContext, SharedPreferencesUtil.SP_SETTINGS).edit().putBoolean("show_top_forum_in_normal_list", true).commit() + toggleTopForum(likeForum.forumId) + } + .setNeutralButton(R.string.button_cancel, null) + .create() + .show() + } else { + toggleTopForum(likeForum.forumId) + } } R.id.menu_copy -> TiebaUtil.copyText(attachContext, likeForum.forumName) R.id.menu_unfollow -> { diff --git a/app/src/main/java/com/huanchengfly/tieba/post/receivers/BootCompleteSignReceiver.java b/app/src/main/java/com/huanchengfly/tieba/post/receivers/BootCompleteSignReceiver.java deleted file mode 100644 index 1b7451cd..00000000 --- a/app/src/main/java/com/huanchengfly/tieba/post/receivers/BootCompleteSignReceiver.java +++ /dev/null @@ -1,45 +0,0 @@ -package com.huanchengfly.tieba.post.receivers; - -import android.app.AlarmManager; -import android.app.PendingIntent; -import android.content.BroadcastReceiver; -import android.content.Context; -import android.content.Intent; - -import com.huanchengfly.tieba.post.utils.SharedPreferencesUtil; -import com.huanchengfly.tieba.post.utils.TiebaUtil; -import com.huanchengfly.tieba.post.utils.Util; - -import java.util.Calendar; - -import static android.content.Context.ALARM_SERVICE; -import static android.content.Context.MODE_PRIVATE; - -public class BootCompleteSignReceiver extends BroadcastReceiver { - @Override - public void onReceive(Context context, Intent intent) { - if (Intent.ACTION_BOOT_COMPLETED.equals(intent.getAction())) { - boolean autoSign = context.getSharedPreferences("settings", MODE_PRIVATE) - .getBoolean("auto_sign", false); - if (autoSign) { - String autoSignTimeStr = context.getSharedPreferences("settings", MODE_PRIVATE) - .getString("auto_sign_time", "09:00"); - if (Util.getTimeInMillis(autoSignTimeStr) > System.currentTimeMillis()) { - TiebaUtil.initAutoSign(context); - } else { - int signDay = SharedPreferencesUtil.get(context, SharedPreferencesUtil.SP_SETTINGS).getInt(TiebaUtil.SP_SIGN_DAY, -1); - if (signDay != Calendar.getInstance().get(Calendar.DAY_OF_MONTH)) { - TiebaUtil.startSign(context); - } - AlarmManager alarmManager = (AlarmManager) context.getSystemService(ALARM_SERVICE); - if (alarmManager != null) { - Calendar calendar = Util.time2Calendar(autoSignTimeStr); - calendar.add(Calendar.DAY_OF_MONTH, 1); - PendingIntent pendingIntent = PendingIntent.getBroadcast(context, 0, new Intent(context, AutoSignAlarm.class), 0); - alarmManager.setInexactRepeating(AlarmManager.RTC, calendar.getTimeInMillis(), AlarmManager.INTERVAL_DAY, pendingIntent); - } - } - } - } - } -} diff --git a/app/src/main/java/com/huanchengfly/tieba/post/receivers/BootCompleteSignReceiver.kt b/app/src/main/java/com/huanchengfly/tieba/post/receivers/BootCompleteSignReceiver.kt new file mode 100644 index 00000000..f8a91156 --- /dev/null +++ b/app/src/main/java/com/huanchengfly/tieba/post/receivers/BootCompleteSignReceiver.kt @@ -0,0 +1,36 @@ +package com.huanchengfly.tieba.post.receivers + +import android.app.AlarmManager +import android.app.PendingIntent +import android.content.BroadcastReceiver +import android.content.Context +import android.content.Intent +import com.huanchengfly.tieba.post.utils.TiebaUtil +import com.huanchengfly.tieba.post.utils.Util +import com.huanchengfly.tieba.post.utils.appPreferences +import java.util.* + +class BootCompleteSignReceiver : BroadcastReceiver() { + override fun onReceive(context: Context, intent: Intent) { + if (Intent.ACTION_BOOT_COMPLETED == intent.action) { + val autoSign = context.appPreferences.autoSign + if (autoSign) { + val autoSignTimeStr = context.appPreferences.autoSignTime + if (Util.getTimeInMillis(autoSignTimeStr) > System.currentTimeMillis()) { + TiebaUtil.initAutoSign(context) + } else { + val signDay = context.appPreferences.signDay + if (signDay != Calendar.getInstance()[Calendar.DAY_OF_MONTH]) { + TiebaUtil.startSign(context) + } + val alarmManager = context.getSystemService(Context.ALARM_SERVICE) as AlarmManager + val time = Util.time2Calendar(autoSignTimeStr).apply { + add(Calendar.DAY_OF_MONTH, 1) + }.timeInMillis + val pendingIntent = PendingIntent.getBroadcast(context, 0, Intent(context, AutoSignAlarm::class.java), 0) + alarmManager.setInexactRepeating(AlarmManager.RTC, time, AlarmManager.INTERVAL_DAY, pendingIntent) + } + } + } + } +} \ No newline at end of file diff --git a/app/src/main/java/com/huanchengfly/tieba/post/utils/AccountUtil.java b/app/src/main/java/com/huanchengfly/tieba/post/utils/AccountUtil.java index 5474bd55..7d08383f 100644 --- a/app/src/main/java/com/huanchengfly/tieba/post/utils/AccountUtil.java +++ b/app/src/main/java/com/huanchengfly/tieba/post/utils/AccountUtil.java @@ -8,15 +8,14 @@ import android.widget.Toast; import androidx.annotation.NonNull; import androidx.annotation.Nullable; +import com.huanchengfly.tieba.post.R; import com.huanchengfly.tieba.post.api.Error; import com.huanchengfly.tieba.post.api.TiebaApi; import com.huanchengfly.tieba.post.api.interfaces.CommonCallback; import com.huanchengfly.tieba.post.api.retrofit.exception.TiebaException; -import com.huanchengfly.tieba.post.R; import com.huanchengfly.tieba.post.models.MyInfoBean; import com.huanchengfly.tieba.post.models.database.Account; -import org.jetbrains.annotations.NotNull; import org.litepal.LitePal; import java.util.List; @@ -29,8 +28,8 @@ public class AccountUtil { public static final String TAG = "AccountUtil"; public static final String ACTION_SWITCH_ACCOUNT = "com.huanchengfly.tieba.post.action.SWITCH_ACCOUNT"; + @Nullable public static Account getLoginInfo(@NonNull Context context) { - if (context == null) return null; int loginUser = context.getSharedPreferences("accountData", Context.MODE_PRIVATE).getInt("now", -1); if (loginUser == -1) { return null; @@ -54,11 +53,11 @@ public class AccountUtil { return LitePal.where("bduss = ?", bduss).findFirst(Account.class); } - public static boolean isLoggedIn(Context context) { + public static boolean isLoggedIn(@NonNull Context context) { return (getLoginInfo(context) != null); } - public static boolean newAccount(Context context, Account account, boolean needSwitch) { + public static boolean newAccount(@NonNull Context context, @NonNull Account account, boolean needSwitch) { if (account.save()) { if (needSwitch) { return switchUser(context, account.getId()); @@ -68,17 +67,12 @@ public class AccountUtil { return false; } - public static boolean switchUser(Context context, int id) { - context.sendBroadcast(new Intent() - .setAction(ACTION_SWITCH_ACCOUNT)); + public static boolean switchUser(@NonNull Context context, int id) { + context.sendBroadcast(new Intent().setAction(ACTION_SWITCH_ACCOUNT)); return context.getSharedPreferences("accountData", Context.MODE_PRIVATE).edit().putInt("now", id).commit(); } - public static void updateUserInfo(Context context, CommonCallback commonCallback) { - if (context == null) { - commonCallback.onFailure(Error.ERROR_UNKNOWN, "未知错误"); - return; - } + public static void updateUserInfo(@NonNull Context context, CommonCallback commonCallback) { Account account = getLoginInfo(context); if (account == null) { commonCallback.onFailure(Error.ERROR_NOT_LOGGED_IN, "未登录"); @@ -105,10 +99,9 @@ public class AccountUtil { } public static void updateUserInfoByBduss(@NonNull Context context, @NonNull String bduss, @Nullable CommonCallback commonCallback) { - if (context == null) return; TiebaApi.getInstance().myInfo(AccountUtil.getBdussCookie(bduss)).enqueue(new Callback() { @Override - public void onResponse(@NotNull Call call, @NotNull Response response) { + public void onResponse(@NonNull Call call, @NonNull Response response) { MyInfoBean myInfoBean = response.body(); if (myInfoBean == null) { if (commonCallback != null) @@ -149,7 +142,7 @@ public class AccountUtil { } @Override - public void onFailure(@NotNull Call call, @NotNull Throwable t) { + public void onFailure(@NonNull Call call, @NonNull Throwable t) { if (commonCallback != null) { if (t instanceof TiebaException) { commonCallback.onFailure(((TiebaException) t).getCode(), t.getMessage()); @@ -162,8 +155,7 @@ public class AccountUtil { } @SuppressWarnings("ApplySharedPref") - public static void exit(Context context) { - if (context == null) return; + public static void exit(@NonNull Context context) { List accounts = getAllAccounts(); Account account = getLoginInfo(context); if (account == null) return; diff --git a/app/src/main/java/com/huanchengfly/tieba/post/utils/AppPreferencesUtils.kt b/app/src/main/java/com/huanchengfly/tieba/post/utils/AppPreferencesUtils.kt index 154b2020..87def1e0 100644 --- a/app/src/main/java/com/huanchengfly/tieba/post/utils/AppPreferencesUtils.kt +++ b/app/src/main/java/com/huanchengfly/tieba/post/utils/AppPreferencesUtils.kt @@ -2,21 +2,78 @@ package com.huanchengfly.tieba.post.utils import android.content.Context import android.content.SharedPreferences +import io.michaelrocks.paranoid.Obfuscate import kotlin.properties.ReadWriteProperty import kotlin.reflect.KProperty +@Obfuscate open class AppPreferencesUtils(context: Context) { private val preferences: SharedPreferences = context.getSharedPreferences("settings", Context.MODE_PRIVATE) - //PreferenceManager.getDefaultSharedPreferences(context) - var loadPictureWhenScroll by SharedPreferenceDelegates.boolean(true) + var autoSign by SharedPreferenceDelegates.boolean(defaultValue = false, key = "auto_sign") + + var autoSignTime by SharedPreferenceDelegates.string(defaultValue = "09:00", key = "auto_sign_time") + + var checkBetaUpdate by SharedPreferenceDelegates.boolean(defaultValue = false, key = "check_beta_update") + + var collectThreadSeeLz by SharedPreferenceDelegates.boolean(defaultValue = true, key = "collect_thread_see_lz") + + var customPrimaryColor by SharedPreferenceDelegates.string(key = "custom_primary_color") + + var customStatusBarFontDark by SharedPreferenceDelegates.boolean(defaultValue = false, key = "custom_status_bar_font_dark") + + var customToolbarPrimaryColor by SharedPreferenceDelegates.boolean(defaultValue = true, key = "custom_toolbar_primary_color") + + var defaultSortType by SharedPreferenceDelegates.string(key = "default_sort_type", defaultValue = "0") + + var darkTheme by SharedPreferenceDelegates.string(key = "dark_theme", defaultValue = "dark") + + var followSystemNight by SharedPreferenceDelegates.boolean(defaultValue = true, key = "follow_system_night") + + var hideExplore by SharedPreferenceDelegates.boolean(defaultValue = false) + + var imageLoadType by SharedPreferenceDelegates.string(key = "image_load_type", defaultValue = "0") + + var listSingle by SharedPreferenceDelegates.boolean(defaultValue = false) + + var levelIconOldStyle by SharedPreferenceDelegates.boolean(defaultValue = false, key = "level_icon_old_style") + var littleTail by SharedPreferenceDelegates.string(key = "little_tail") + var loadPictureWhenScroll by SharedPreferenceDelegates.boolean(defaultValue = true) + + var radius by SharedPreferenceDelegates.int(defaultValue = 8) + + var signDay by SharedPreferenceDelegates.int(defaultValue = -1, key = "sign_day") + + var showBothUsernameAndNickname by SharedPreferenceDelegates.boolean(defaultValue = false, key = "show_both_username_and_nickname") + + var showShortcutInThread by SharedPreferenceDelegates.boolean(defaultValue = true) + + var showTopForumInNormalList by SharedPreferenceDelegates.boolean(defaultValue = true, key = "show_top_forum_in_normal_list") + + var statusBarDarker by SharedPreferenceDelegates.boolean(defaultValue = true, key = "status_bar_darker") + + var translucentBackgroundAlpha by SharedPreferenceDelegates.int(defaultValue = 255, key = "translucent_background_alpha") + + var translucentBackgroundBlur by SharedPreferenceDelegates.int(key = "translucent_background_blur") + + var translucentThemeBackgroundPath by SharedPreferenceDelegates.string(key = "translucent_theme_background_path") + + var translucentPrimaryColor by SharedPreferenceDelegates.string(key = "translucent_primary_color") + + var useCustomTabs by SharedPreferenceDelegates.boolean(defaultValue = true, key = "use_custom_tabs") + + var useWebView by SharedPreferenceDelegates.boolean(defaultValue = true, key = "use_webview") + private object SharedPreferenceDelegates { - fun int(defaultValue: Int = 0) = object : ReadWriteProperty { + fun int( + defaultValue: Int = 0, + key: String? = null + ) = object : ReadWriteProperty { override fun getValue(thisRef: AppPreferencesUtils, property: KProperty<*>): Int { - return thisRef.preferences.getInt(property.name, defaultValue) + return thisRef.preferences.getInt(key ?: property.name, defaultValue) } override fun setValue( @@ -24,7 +81,7 @@ open class AppPreferencesUtils(context: Context) { property: KProperty<*>, value: Int ) { - thisRef.preferences.edit().putInt(property.name, value).apply() + thisRef.preferences.edit().putInt(key ?: property.name, value).apply() } } @@ -46,13 +103,16 @@ open class AppPreferencesUtils(context: Context) { } } - fun boolean(defaultValue: Boolean = false) = + fun boolean( + defaultValue: Boolean = false, + key: String? = null + ) = object : ReadWriteProperty { override fun getValue( thisRef: AppPreferencesUtils, property: KProperty<*> ): Boolean { - return thisRef.preferences.getBoolean(property.name, defaultValue) + return thisRef.preferences.getBoolean(key ?: property.name, defaultValue) } override fun setValue( @@ -60,7 +120,7 @@ open class AppPreferencesUtils(context: Context) { property: KProperty<*>, value: Boolean ) { - thisRef.preferences.edit().putBoolean(property.name, value).apply() + thisRef.preferences.edit().putBoolean(key ?: property.name, value).apply() } } @@ -121,7 +181,7 @@ open class AppPreferencesUtils(context: Context) { } } } +} - val Context.appPreferences: AppPreferencesUtils - get() = AppPreferencesUtils(this) -} \ No newline at end of file +val Context.appPreferences: AppPreferencesUtils + get() = AppPreferencesUtils(this) \ No newline at end of file diff --git a/app/src/main/java/com/huanchengfly/tieba/post/utils/ThemeUtil.java b/app/src/main/java/com/huanchengfly/tieba/post/utils/ThemeUtil.java index 7bba5c8d..93c5621a 100644 --- a/app/src/main/java/com/huanchengfly/tieba/post/utils/ThemeUtil.java +++ b/app/src/main/java/com/huanchengfly/tieba/post/utils/ThemeUtil.java @@ -61,7 +61,6 @@ public class ThemeUtil { public static final String THEME_GREY_DARK = "grey_dark"; public static final String THEME_AMOLED_DARK = "amoled_dark"; - public static final String SP_CUSTOM_PRIMARY_COLOR = "custom_primary_color"; public static final String SP_TRANSLUCENT_PRIMARY_COLOR = "translucent_primary_color"; public static final String SP_CUSTOM_STATUS_BAR_FONT_DARK = "custom_status_bar_font_dark"; public static final String SP_CUSTOM_TOOLBAR_PRIMARY_COLOR = "custom_toolbar_primary_color"; diff --git a/app/src/main/java/com/huanchengfly/tieba/post/utils/TiebaUtil.java b/app/src/main/java/com/huanchengfly/tieba/post/utils/TiebaUtil.java deleted file mode 100644 index 09fa50a1..00000000 --- a/app/src/main/java/com/huanchengfly/tieba/post/utils/TiebaUtil.java +++ /dev/null @@ -1,133 +0,0 @@ -package com.huanchengfly.tieba.post.utils; - -import android.annotation.SuppressLint; -import android.app.AlarmManager; -import android.app.PendingIntent; -import android.content.ClipData; -import android.content.ClipboardManager; -import android.content.Context; -import android.content.Intent; -import android.content.SharedPreferences; -import android.os.Build; -import android.webkit.CookieManager; -import android.widget.Toast; - -import com.huanchengfly.tieba.post.R; -import com.huanchengfly.tieba.post.models.database.Account; -import com.huanchengfly.tieba.post.receivers.AutoSignAlarm; -import com.huanchengfly.tieba.post.services.OKSignService; - -import org.jetbrains.annotations.Nullable; - -import java.util.Calendar; - -import static android.content.Context.ALARM_SERVICE; -import static android.content.Context.MODE_PRIVATE; - -public class TiebaUtil { - public static final String SP_SIGN_DAY = "sign_day"; - - public static void copyText(Context context, String text, String toast) { - ClipboardManager cm = (ClipboardManager) context.getSystemService(Context.CLIPBOARD_SERVICE); - if (cm != null) { - ClipData clipData = ClipData.newPlainText("Tieba Lite", text); - cm.setPrimaryClip(clipData); - Toast.makeText(context, toast, Toast.LENGTH_SHORT).show(); - } - } - - public static void copyText(Context context, String text) { - copyText(context, text, context.getString(R.string.toast_copy_success)); - } - - public static void initAutoSign(Context context) { - AlarmManager alarmManager = (AlarmManager) context.getSystemService(ALARM_SERVICE); - boolean autoSign = context.getSharedPreferences("settings", MODE_PRIVATE) - .getBoolean("auto_sign", false); - if (alarmManager != null) { - PendingIntent pendingIntent = PendingIntent.getBroadcast(context, 0, new Intent(context, AutoSignAlarm.class), 0); - if (autoSign) { - String autoSignTimeStr = context.getSharedPreferences("settings", MODE_PRIVATE) - .getString("auto_sign_time", "09:00"); - String[] time = autoSignTimeStr.split(":"); - int hour = Integer.parseInt(time[0]); - int minute = Integer.parseInt(time[1]); - Calendar calendar = Calendar.getInstance(); - calendar.set(Calendar.HOUR_OF_DAY, hour); - calendar.set(Calendar.MINUTE, minute); - if (calendar.getTimeInMillis() >= System.currentTimeMillis()) { - alarmManager.setInexactRepeating(AlarmManager.RTC, calendar.getTimeInMillis(), AlarmManager.INTERVAL_DAY, pendingIntent); - } - } else { - alarmManager.cancel(pendingIntent); - } - } - } - - public static void startSign(Context context) { - SharedPreferencesUtil.get(context, SharedPreferencesUtil.SP_SETTINGS) - .edit() - .putInt(SP_SIGN_DAY, Calendar.getInstance().get(Calendar.DAY_OF_MONTH)) - .apply(); - if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) { - context.startForegroundService(new Intent(context, OKSignService.class) - .addFlags(Intent.FLAG_ACTIVITY_NEW_TASK) - .setAction(OKSignService.ACTION_START_SIGN)); - } else { - context.startService(new Intent(context, OKSignService.class) - .addFlags(Intent.FLAG_ACTIVITY_NEW_TASK) - .setAction(OKSignService.ACTION_START_SIGN)); - } - } - - public static void shareText(Context context, String text) { - Intent sendIntent = new Intent(); - sendIntent.setAction(Intent.ACTION_SEND); - String shareText = text + "\n「分享自Tieba Lite客户端」"; - sendIntent.putExtra(Intent.EXTRA_TEXT, shareText); - sendIntent.setType("text/plain"); - context.startActivity(sendIntent); - } - - public static void shareText(Context context, String text, String title) { - if (title == null) { - shareText(context, text); - } - Intent sendIntent = new Intent(); - sendIntent.setAction(Intent.ACTION_SEND); - String shareText = "「" + title + "」\n" + text + "\n「分享自Tieba Lite客户端」"; - sendIntent.putExtra(Intent.EXTRA_TEXT, shareText); - sendIntent.setType("text/plain"); - context.startActivity(sendIntent); - } - - @Deprecated - @Nullable - public static String getBduss(Context context) { - Account account = AccountUtil.getLoginInfo(context); - if (account != null) { - return account.getBduss(); - } - return null; - } - - @Deprecated - @Nullable - public static String getBdussCookie(Context context) { - String bduss = getBduss(context); - if (bduss != null) { - return "BDUSS=" + bduss + ";"; - } - return null; - } - - @SuppressLint("ApplySharedPref") - @Deprecated - public static void exit(Context context) { - SharedPreferences sp = context.getSharedPreferences("accountData", MODE_PRIVATE); - SharedPreferences.Editor edit = sp.edit(); - edit.clear().commit(); - CookieManager.getInstance().removeAllCookies(null); - Toast.makeText(context, "退出登录成功", Toast.LENGTH_SHORT).show(); - } -} \ No newline at end of file diff --git a/app/src/main/java/com/huanchengfly/tieba/post/utils/TiebaUtil.kt b/app/src/main/java/com/huanchengfly/tieba/post/utils/TiebaUtil.kt new file mode 100644 index 00000000..3cbcc0ce --- /dev/null +++ b/app/src/main/java/com/huanchengfly/tieba/post/utils/TiebaUtil.kt @@ -0,0 +1,69 @@ +package com.huanchengfly.tieba.post.utils + +import android.app.AlarmManager +import android.app.PendingIntent +import android.content.ClipData +import android.content.ClipboardManager +import android.content.Context +import android.content.Intent +import android.os.Build +import com.huanchengfly.tieba.post.R +import com.huanchengfly.tieba.post.receivers.AutoSignAlarm +import com.huanchengfly.tieba.post.services.OKSignService +import com.huanchengfly.tieba.post.toastShort +import java.util.* + +object TiebaUtil { + @JvmStatic + @JvmOverloads + fun copyText(context: Context, text: String?, toast: String = context.getString(R.string.toast_copy_success)) { + val cm = context.getSystemService(Context.CLIPBOARD_SERVICE) as ClipboardManager + val clipData = ClipData.newPlainText("Tieba Lite", text) + cm.setPrimaryClip(clipData) + context.toastShort(toast) + } + + fun initAutoSign(context: Context) { + val alarmManager = context.getSystemService(Context.ALARM_SERVICE) as AlarmManager + val autoSign = context.appPreferences.autoSign + val pendingIntent = PendingIntent.getBroadcast(context, 0, Intent(context, AutoSignAlarm::class.java), 0) + if (autoSign) { + val autoSignTimeStr = context.appPreferences.autoSignTime!! + val time = autoSignTimeStr.split(":".toRegex()).toTypedArray() + val hour = time[0].toInt() + val minute = time[1].toInt() + val calendar = Calendar.getInstance() + calendar[Calendar.HOUR_OF_DAY] = hour + calendar[Calendar.MINUTE] = minute + if (calendar.timeInMillis >= System.currentTimeMillis()) { + alarmManager.setInexactRepeating(AlarmManager.RTC, calendar.timeInMillis, AlarmManager.INTERVAL_DAY, pendingIntent) + } + } else { + alarmManager.cancel(pendingIntent) + } + } + + @JvmStatic + fun startSign(context: Context) { + context.appPreferences.signDay = Calendar.getInstance()[Calendar.DAY_OF_MONTH] + if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) { + context.startForegroundService(Intent(context, OKSignService::class.java) + .addFlags(Intent.FLAG_ACTIVITY_NEW_TASK) + .setAction(OKSignService.ACTION_START_SIGN)) + } else { + context.startService(Intent(context, OKSignService::class.java) + .addFlags(Intent.FLAG_ACTIVITY_NEW_TASK) + .setAction(OKSignService.ACTION_START_SIGN)) + } + } + + @JvmStatic + @JvmOverloads + fun shareText(context: Context, text: String, title: String? = null) { + context.startActivity(Intent().apply { + action = Intent.ACTION_SEND + type = "text/plain" + putExtra(Intent.EXTRA_TEXT, "${if (title != null) "「$title」\n" else ""}$text\n(分享自贴吧 Lite)") + }) + } +} \ No newline at end of file diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml index 4e9a27cf..f4346579 100644 --- a/app/src/main/res/values/strings.xml +++ b/app/src/main/res/values/strings.xml @@ -272,7 +272,7 @@ (每小时更新一次,以实时讨论量排序) 图片保存在 %1$s 吧默认排序方式 - 设置浏览吧是贴子的默认排序方式 + 设置浏览吧时贴子的默认排序方式 加载失败 已删除 撤销 diff --git a/app/src/main/res/xml/custom_preferences.xml b/app/src/main/res/xml/custom_preferences.xml index 2e028ec8..3d4e242a 100644 --- a/app/src/main/res/xml/custom_preferences.xml +++ b/app/src/main/res/xml/custom_preferences.xml @@ -9,7 +9,10 @@ android:layout="@layout/layout_preference" android:icon="@drawable/ic_round_format_paint_red" android:title="@string/title_select_theme"> - + - \ No newline at end of file diff --git a/app/src/main/res/xml/habit_preferences.xml b/app/src/main/res/xml/habit_preferences.xml index 2f6ec032..1733f817 100644 --- a/app/src/main/res/xml/habit_preferences.xml +++ b/app/src/main/res/xml/habit_preferences.xml @@ -4,9 +4,7 @@ xmlns:android="http://schemas.android.com/apk/res/android"> - - - + + \ No newline at end of file diff --git a/app/src/main/res/xml/other_preferences.xml b/app/src/main/res/xml/other_preferences.xml index 2031d787..d7ef67c4 100644 --- a/app/src/main/res/xml/other_preferences.xml +++ b/app/src/main/res/xml/other_preferences.xml @@ -22,15 +22,5 @@ android:title="@string/title_use_webview" android:summaryOn="@string/tip_use_webview_on" android:summaryOff="@string/tip_use_webview"/> - - \ No newline at end of file diff --git a/app/src/main/res/xml/preferences.xml b/app/src/main/res/xml/preferences.xml index 51e74172..3ea1bcfc 100644 --- a/app/src/main/res/xml/preferences.xml +++ b/app/src/main/res/xml/preferences.xml @@ -50,7 +50,6 @@ -