diff --git a/.github/workflows/code_quality.yml b/.github/workflows/code_quality.yml index acc759f6..10978f4e 100644 --- a/.github/workflows/code_quality.yml +++ b/.github/workflows/code_quality.yml @@ -1,7 +1,6 @@ name: Qodana on: workflow_dispatch: - pull_request: push: jobs: diff --git a/.gitignore b/.gitignore index 833f0b3c..0a5bf0cf 100644 --- a/.gitignore +++ b/.gitignore @@ -84,4 +84,6 @@ app/debug/* .project .settings/org.eclipse.buildship.core.prefs app/.settings/org.eclipse.buildship.core.prefs -.DS_Store \ No newline at end of file +.DS_Store + +resources/ \ No newline at end of file diff --git a/app/build.gradle b/app/build.gradle index ae9309cc..05caaaa2 100644 --- a/app/build.gradle +++ b/app/build.gradle @@ -4,14 +4,13 @@ plugins { } private static String baseVersionName() { - return "2.8.7" + return "3.0.0" } android { compileSdk 33 defaultConfig { - applicationId "com.qhy040404.libraryonetap" minSdk 29 targetSdk 33 @@ -43,21 +42,38 @@ android { } } +configurations.all { + exclude group: 'androidx.appcompat', module: 'appcompat' +} + +gradle.projectsEvaluated { + tasks.withType(JavaCompile) { + options.compilerArgs << "-Xlint:deprecation" + } +} + dependencies { - implementation 'androidx.core:core-ktx:1.8.0' - implementation 'androidx.appcompat:appcompat:1.4.2' - implementation 'com.google.android.material:material:1.6.1' + implementation 'androidx.appcompat:appcompat:1.6.0-alpha05' implementation 'androidx.constraintlayout:constraintlayout:2.1.4' - implementation 'androidx.preference:preference:1.2.0' + implementation 'androidx.core:core-ktx:1.8.0' implementation 'androidx.navigation:navigation-fragment-ktx:2.5.0' implementation 'androidx.navigation:navigation-ui-ktx:2.5.0' - implementation("com.squareup.okhttp3:okhttp:4.10.0") - implementation("com.google.code.gson:gson:2.9.0") - implementation("dev.rikka.rikkax.preference:simplemenu-preference:1.0.3") - implementation('com.tencent.bugly:crashreport:4.0.4') - implementation("com.drakeet.about:about:2.5.1") - implementation("com.drakeet.multitype:multitype:4.3.0") - implementation("io.coil-kt:coil:2.1.0") + implementation 'androidx.preference:preference:1.2.0' + implementation 'com.drakeet.about:about:2.5.1' + implementation 'com.drakeet.multitype:multitype:4.3.0' + implementation 'com.github.zhaobozhen.libraries:utils:1.1.1' + implementation 'com.google.android.material:material:1.6.1' + implementation 'com.squareup.moshi:moshi-kotlin:1.13.0' + implementation 'com.squareup.okhttp3:okhttp:4.10.0' + implementation 'com.tencent.bugly:crashreport:4.0.4' + implementation 'dev.rikka.rikkax.appcompat:appcompat:1.4.1' + implementation 'dev.rikka.rikkax.material:material:2.5.0' + implementation 'dev.rikka.rikkax.material:material-preference:2.0.0' + implementation 'dev.rikka.rikkax.preference:simplemenu-preference:1.0.3' + implementation 'dev.rikka.rikkax.recyclerview:recyclerview-ktx:1.3.1' + implementation 'dev.rikka.rikkax.widget:borderview:1.1.0' + implementation 'io.coil-kt:coil:2.1.0' + implementation 'me.zhanghai.android.appiconloader:appiconloader:1.4.0' } import java.text.SimpleDateFormat diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml index 196ce21d..37e5fda8 100644 --- a/app/src/main/AndroidManifest.xml +++ b/app/src/main/AndroidManifest.xml @@ -14,21 +14,18 @@ - + android:label="@string/about_title" + android:theme="@style/Theme.MaterialComponents.DayNight.NoActionBar.Library" /> - - - diff --git a/app/src/main/java/com/qhy040404/libraryonetap/LibraryOneTapApp.kt b/app/src/main/java/com/qhy040404/libraryonetap/LibraryOneTapApp.kt index 53947f20..af7d413d 100644 --- a/app/src/main/java/com/qhy040404/libraryonetap/LibraryOneTapApp.kt +++ b/app/src/main/java/com/qhy040404/libraryonetap/LibraryOneTapApp.kt @@ -2,8 +2,17 @@ package com.qhy040404.libraryonetap import android.app.Activity import android.app.Application +import coil.Coil +import coil.ImageLoader +import com.absinthe.libraries.utils.utils.Utility +import com.google.android.material.color.DynamicColors +import com.qhy040404.libraryonetap.app.AppIconFetcherFactory import com.qhy040404.libraryonetap.constant.Constants +import com.qhy040404.libraryonetap.constant.GlobalValues +import com.qhy040404.libraryonetap.utils.AppUtils import com.tencent.bugly.crashreport.CrashReport +import rikka.material.app.DayNightDelegate +import rikka.material.app.LocaleDelegate import java.util.* class LibraryOneTapApp : Application() { @@ -22,6 +31,21 @@ class LibraryOneTapApp : Application() { strategy ) app = this + + LocaleDelegate.defaultLocale = AppUtils.locale + DayNightDelegate.setApplicationContext(this) + DayNightDelegate.setDefaultNightMode(AppUtils.getNightMode(GlobalValues.darkMode)) + DynamicColors.applyToActivitiesIfAvailable(this) + + Utility.init(this) + + Coil.setImageLoader { + ImageLoader(this).newBuilder() + .components { + add(AppIconFetcherFactory(this@LibraryOneTapApp)) + } + .build() + } } fun addActivity(activity: Activity) = activityList.add(activity) diff --git a/app/src/main/java/com/qhy040404/libraryonetap/app/AppIconFetcherFactory.kt b/app/src/main/java/com/qhy040404/libraryonetap/app/AppIconFetcherFactory.kt new file mode 100644 index 00000000..56b9055b --- /dev/null +++ b/app/src/main/java/com/qhy040404/libraryonetap/app/AppIconFetcherFactory.kt @@ -0,0 +1,32 @@ +package com.qhy040404.libraryonetap.app + +import android.content.Context +import android.content.pm.PackageInfo +import android.graphics.drawable.BitmapDrawable +import coil.ImageLoader +import coil.decode.DataSource +import coil.fetch.DrawableResult +import coil.fetch.FetchResult +import coil.fetch.Fetcher +import coil.request.Options +import com.qhy040404.libraryonetap.utils.extensions.ViewExtensions.dp +import me.zhanghai.android.appiconloader.AppIconLoader + +class AppIconFetcherFactory(private val ctx: Context) : Fetcher.Factory { + private val loader = AppIconLoader(40.dp, false, ctx) + + override fun create(data: PackageInfo, options: Options, imageLoader: ImageLoader): Fetcher { + return AppIconFetcher(ctx, data, loader) + } + + class AppIconFetcher( + private val context: Context, + private val info: PackageInfo, + private val loader: AppIconLoader, + ) : Fetcher { + override suspend fun fetch(): FetchResult { + val icon = loader.loadIcon(info.applicationInfo) + return DrawableResult(BitmapDrawable(context.resources, icon), true, DataSource.DISK) + } + } +} \ No newline at end of file diff --git a/app/src/main/java/com/qhy040404/libraryonetap/base/BaseActivity.kt b/app/src/main/java/com/qhy040404/libraryonetap/base/BaseActivity.kt index 19321a6d..d684931f 100644 --- a/app/src/main/java/com/qhy040404/libraryonetap/base/BaseActivity.kt +++ b/app/src/main/java/com/qhy040404/libraryonetap/base/BaseActivity.kt @@ -1,61 +1,72 @@ package com.qhy040404.libraryonetap.base +import android.content.res.Resources +import android.graphics.Color import android.os.Bundle import android.view.MenuItem -import androidx.appcompat.app.AppCompatActivity -import androidx.appcompat.app.AppCompatDelegate +import androidx.viewbinding.ViewBinding import com.qhy040404.libraryonetap.LibraryOneTapApp import com.qhy040404.libraryonetap.R import com.qhy040404.libraryonetap.constant.GlobalValues -import com.qhy040404.libraryonetap.utils.RandomDataUtils -import java.util.* +import com.qhy040404.libraryonetap.utils.AppUtils +import com.qhy040404.libraryonetap.utils.OsUtils +import com.qhy040404.libraryonetap.utils.extensions.CompatExtensions.inflateBinding +import rikka.material.app.MaterialActivity @Suppress("DEPRECATION") -abstract class BaseActivity : AppCompatActivity() { +abstract class BaseActivity : MaterialActivity() { + + protected lateinit var binding: VB + override fun onCreate(savedInstanceState: Bundle?) { - val config = resources.configuration - val dm = resources.displayMetrics - var theme = GlobalValues.theme - - when (GlobalValues.darkMode) { - "system" -> AppCompatDelegate.setDefaultNightMode(AppCompatDelegate.MODE_NIGHT_FOLLOW_SYSTEM) - "on" -> AppCompatDelegate.setDefaultNightMode(AppCompatDelegate.MODE_NIGHT_YES) - "off" -> AppCompatDelegate.setDefaultNightMode(AppCompatDelegate.MODE_NIGHT_NO) - } - if (GlobalValues.theme == "random") { - theme = RandomDataUtils.randomTheme + if (!GlobalValues.md3) { + setTheme(AppUtils.getThemeID(GlobalValues.theme)) } - when (theme) { - "purple" -> setTheme(R.style.Theme_Purple) - "blue" -> setTheme(R.style.Theme_Blue) - "pink" -> setTheme(R.style.Theme_Pink) - "green" -> setTheme(R.style.Theme_Green) - "simple" -> setTheme(R.style.Theme_Simple) - } - config.setLocale( - when (GlobalValues.locale) { - "zh" -> Locale.SIMPLIFIED_CHINESE - "en" -> Locale.ENGLISH - else -> Locale.getDefault() - } - ) - resources.updateConfiguration(config, dm) super.onCreate(savedInstanceState) LibraryOneTapApp.instance?.addActivity(this) - setContentView(getLayoutId()) + if (!this::binding.isInitialized) { + binding = inflateBinding(layoutInflater) + } + + setContentView(binding.root) supportActionBar?.setDisplayHomeAsUpEnabled(true) init() } + override fun shouldApplyTranslucentSystemBars(): Boolean { + return true + } + + override fun computeUserThemeKey(): String? { + return GlobalValues.darkMode + GlobalValues.theme + GlobalValues.md3 + } + + override fun onApplyTranslucentSystemBars() { + super.onApplyTranslucentSystemBars() + window.statusBarColor = Color.TRANSPARENT + window.decorView.post { + window.navigationBarColor = Color.TRANSPARENT + if (OsUtils.atLeastQ()) { + window.isNavigationBarContrastEnforced = false + } + } + } + + override fun onApplyUserThemeResource(theme: Resources.Theme, isDecorView: Boolean) { + theme.applyStyle(R.style.ThemeOverlay, true) + + if (!GlobalValues.md3) { + theme.applyStyle(AppUtils.getThemeID(GlobalValues.theme), true) + } + } + override fun onOptionsItemSelected(item: MenuItem): Boolean { finish() return super.onOptionsItemSelected(item) } protected abstract fun init() - - protected abstract fun getLayoutId(): Int } \ No newline at end of file diff --git a/app/src/main/java/com/qhy040404/libraryonetap/base/BaseFragment.kt b/app/src/main/java/com/qhy040404/libraryonetap/base/BaseFragment.kt new file mode 100644 index 00000000..f6107405 --- /dev/null +++ b/app/src/main/java/com/qhy040404/libraryonetap/base/BaseFragment.kt @@ -0,0 +1,38 @@ +package com.qhy040404.libraryonetap.base + +import android.os.Bundle +import android.view.LayoutInflater +import android.view.View +import android.view.ViewGroup +import androidx.annotation.CallSuper +import androidx.fragment.app.Fragment +import androidx.viewbinding.ViewBinding +import com.qhy040404.libraryonetap.utils.extensions.CompatExtensions.inflateBinding + +abstract class BaseFragment : Fragment() { + protected lateinit var binding: VB + + private var parentActivityVisible = false + private var visible = false + private var localParentFragment: BaseFragment? = null + + override fun onViewCreated(view: View, savedInstanceState: Bundle?) { + super.onViewCreated(view, savedInstanceState) + init() + } + + abstract fun init() + + @CallSuper + override fun onCreate(savedInstanceState: Bundle?) { + super.onCreate(savedInstanceState) + binding = inflateBinding(layoutInflater) + } + + @CallSuper + override fun onCreateView( + inflater: LayoutInflater, + container: ViewGroup?, + savedInstanceState: Bundle?, + ): View = binding.root +} \ No newline at end of file diff --git a/app/src/main/java/com/qhy040404/libraryonetap/constant/Constants.kt b/app/src/main/java/com/qhy040404/libraryonetap/constant/Constants.kt index 93c1b60b..b6ff4832 100644 --- a/app/src/main/java/com/qhy040404/libraryonetap/constant/Constants.kt +++ b/app/src/main/java/com/qhy040404/libraryonetap/constant/Constants.kt @@ -11,15 +11,17 @@ object Constants { const val PREF_DARK = "dark" const val PREF_THEME = "theme" + const val PREF_MD3 = "md3" const val PREF_LOCALE = "locale" const val PREF_RESET = "reset" const val PREF_INIT = "initialized" + const val PREF_CACHE = "cache" const val PREF_ABOUT = "about" const val DEFAULT_DARK = "system" - const val DEFAULT_THEME = "simple" + const val DEFAULT_THEME = "blue" const val DEFAULT_LOCALE = "system" const val CONTENT_TYPE_SSO = "application/x-www-form-urlencoded; charset=utf-8" diff --git a/app/src/main/java/com/qhy040404/libraryonetap/constant/GlobalManager.kt b/app/src/main/java/com/qhy040404/libraryonetap/constant/GlobalManager.kt index 21490436..e599ee47 100644 --- a/app/src/main/java/com/qhy040404/libraryonetap/constant/GlobalManager.kt +++ b/app/src/main/java/com/qhy040404/libraryonetap/constant/GlobalManager.kt @@ -1,12 +1,15 @@ package com.qhy040404.libraryonetap.constant import android.content.pm.PackageManager -import com.google.gson.Gson import com.qhy040404.libraryonetap.LibraryOneTapApp import com.qhy040404.libraryonetap.utils.lazy.ResettableLazyUtils +import com.squareup.moshi.Moshi +import com.squareup.moshi.kotlin.reflect.KotlinJsonAdapterFactory object GlobalManager { val packageManager: PackageManager by lazy { LibraryOneTapApp.app.packageManager } val lazyMgr = ResettableLazyUtils.resettableManager() - val gson: Gson by lazy { Gson() } + val moshi: Moshi = Moshi.Builder() + .addLast(KotlinJsonAdapterFactory()) + .build() } \ No newline at end of file diff --git a/app/src/main/java/com/qhy040404/libraryonetap/constant/GlobalValues.kt b/app/src/main/java/com/qhy040404/libraryonetap/constant/GlobalValues.kt index 1f731095..9978c1f3 100644 --- a/app/src/main/java/com/qhy040404/libraryonetap/constant/GlobalValues.kt +++ b/app/src/main/java/com/qhy040404/libraryonetap/constant/GlobalValues.kt @@ -14,7 +14,7 @@ object GlobalValues { // App val version = - LibraryOneTapApp.app.getString(R.string.app_name) + " " + PackageUtils.buildType + " " + PackageUtils.versionName + " (${PackageUtils.versionCode})" + LibraryOneTapApp.app.getString(R.string.app_name) + " ${PackageUtils.buildType} v${PackageUtils.versionName} (${PackageUtils.versionCode})" // Preferences var name: String by SPDelegates(Constants.PREF_NAME, Constants.GLOBAL_ERROR) @@ -23,6 +23,7 @@ object GlobalValues { var darkMode: String by SPDelegates(Constants.PREF_DARK, Constants.DEFAULT_DARK) var theme: String by SPDelegates(Constants.PREF_THEME, Constants.DEFAULT_THEME) + var md3: Boolean by SPDelegates(Constants.PREF_MD3, false) var locale: String by SPDelegates(Constants.PREF_LOCALE, Constants.DEFAULT_LOCALE) var initialized: Boolean by SPDelegates(Constants.PREF_INIT, false) diff --git a/app/src/main/java/com/qhy040404/libraryonetap/constant/URLManager.kt b/app/src/main/java/com/qhy040404/libraryonetap/constant/URLManager.kt index 9a834d76..493c6a50 100644 --- a/app/src/main/java/com/qhy040404/libraryonetap/constant/URLManager.kt +++ b/app/src/main/java/com/qhy040404/libraryonetap/constant/URLManager.kt @@ -7,8 +7,6 @@ object URLManager { const val LIBRARY_SSO_URL = "https://sso.dlut.edu.cn/cas/login?service=http://seat.lib.dlut.edu.cn/yanxiujian/client/login.php?redirect=index.php" - const val LIBRARY_LOGIN_DIRECT_URL = - "http://seat.lib.dlut.edu.cn/yanxiujian/client/login.php?redirect=index.php" const val LIBRARY_SESSION_URL = "http://seat.lib.dlut.edu.cn/yanxiujian/client/orderRoomAction.php?action=checkSession" const val LIBRARY_ORDER_LIST_URL = @@ -30,7 +28,6 @@ object URLManager { const val BATH_SSO_URL = "https://sso.dlut.edu.cn/cas/login?service=http%3A%2F%2F202.118.74.5%3A8193%2FopenHomeRJPage" - const val BATH_DIRECT_URL = "http://202.118.74.5:8193/openHomeRJPage" const val BATH_SAVE_CART_URL = "http://202.118.74.5:8193/goods/saveGoodsShopcar" const val BATH_UPDATE_CART_URL = "http://202.118.74.5:8193/goods/updateGoodsShopcar" const val BATH_MAIN_FUNC_URL = "http://202.118.74.5:8193/goods/queryNoChoiceTimeInfo" diff --git a/app/src/main/java/com/qhy040404/libraryonetap/data/CancelData.kt b/app/src/main/java/com/qhy040404/libraryonetap/data/CancelData.kt new file mode 100644 index 00000000..23d5e2f7 --- /dev/null +++ b/app/src/main/java/com/qhy040404/libraryonetap/data/CancelData.kt @@ -0,0 +1,10 @@ +package com.qhy040404.libraryonetap.data + +import com.qhy040404.libraryonetap.constant.GlobalManager.moshi +import com.qhy040404.libraryonetap.data.model.CancelDataClass + +object CancelData { + fun getMessage(returnData: String): String { + return moshi.adapter(CancelDataClass::class.java).fromJson(returnData)?.message!! + } +} \ No newline at end of file diff --git a/app/src/main/java/com/qhy040404/libraryonetap/data/ElectricData.kt b/app/src/main/java/com/qhy040404/libraryonetap/data/ElectricData.kt new file mode 100644 index 00000000..e7a3b7d7 --- /dev/null +++ b/app/src/main/java/com/qhy040404/libraryonetap/data/ElectricData.kt @@ -0,0 +1,17 @@ +package com.qhy040404.libraryonetap.data + +import com.qhy040404.libraryonetap.constant.GlobalManager.moshi +import com.qhy040404.libraryonetap.data.model.ElectricDataClass + +@Suppress("SpellCheckingInspection") +object ElectricData { + fun getSSMC(data: String): String { + return moshi.adapter(ElectricDataClass::class.java) + .fromJson(data)?.dormitoryInfo_list!![0].SSMC!! + } + + fun getResele(data: String): String { + return moshi.adapter(ElectricDataClass::class.java) + .fromJson(data)?.dormitoryInfo_list!![0].resele!! + } +} \ No newline at end of file diff --git a/app/src/main/java/com/qhy040404/libraryonetap/data/NetData.kt b/app/src/main/java/com/qhy040404/libraryonetap/data/NetData.kt new file mode 100644 index 00000000..9ddddd11 --- /dev/null +++ b/app/src/main/java/com/qhy040404/libraryonetap/data/NetData.kt @@ -0,0 +1,18 @@ +package com.qhy040404.libraryonetap.data + +import com.qhy040404.libraryonetap.constant.GlobalManager.moshi +import com.qhy040404.libraryonetap.data.model.NetDataClass + +object NetData { + fun getFee(data: String): String { + return moshi.adapter(NetDataClass::class.java).fromJson(data)?.fee!! + } + + fun getDynamicUsedFlow(data: String): String { + return moshi.adapter(NetDataClass::class.java).fromJson(data)?.dynamicUsedFlow!! + } + + fun getDynamicRemainFlow(data: String): String { + return moshi.adapter(NetDataClass::class.java).fromJson(data)?.dynamicRemainFlow!! + } +} \ No newline at end of file diff --git a/app/src/main/java/com/qhy040404/libraryonetap/data/OrderListData.kt b/app/src/main/java/com/qhy040404/libraryonetap/data/OrderListData.kt new file mode 100644 index 00000000..fc0cc0af --- /dev/null +++ b/app/src/main/java/com/qhy040404/libraryonetap/data/OrderListData.kt @@ -0,0 +1,176 @@ +package com.qhy040404.libraryonetap.data + +import com.qhy040404.libraryonetap.constant.GlobalManager.moshi +import com.qhy040404.libraryonetap.data.model.OrderListDataClass +import com.qhy040404.libraryonetap.utils.TimeUtils + +@Suppress("FunctionName", "LocalVariableName", "PropertyName") +object OrderListData { + private val today = TimeUtils.getToday("-", true) + + fun getTotal(data: String): String { + return moshi.adapter(OrderListDataClass::class.java).fromJson(data)?.total!! + } + + fun getOrder_id(data: String, mode: String): String { + val mClass = moshi.adapter(OrderListDataClass::class.java).fromJson(data) + var order_id = "oid" + var notHasToday = true + for (i in mClass?.rows!!.indices) { + val list = mClass.rows[i] + if ((list.order_process == "进行中" || list.order_process == "暂离" || list.order_process == "审核通过") && list.order_type == mode && list.order_date == today) { + order_id = list.order_id!! + notHasToday = false + break + } + } + if (notHasToday) { + for (i in mClass.rows.indices) { + val list = mClass.rows[i] + if ((list.order_process == "进行中" || list.order_process == "暂离" || list.order_process == "审核通过") && list.order_type == mode) { + order_id = list.order_id!! + break + } + } + } + return order_id + } + + fun getOrder_process(data: String, mode: String): String { + val mClass = moshi.adapter(OrderListDataClass::class.java).fromJson(data) + var order_process = "" + var notHasToday = true + for (i in mClass?.rows!!.indices) { + val list = mClass.rows[i] + if ((list.order_process == "进行中" || list.order_process == "暂离" || list.order_process == "审核通过") && list.order_type == mode && list.order_date == today) { + order_process = list.order_process + notHasToday = false + break + } + } + if (notHasToday) { + for (i in mClass.rows.indices) { + val list = mClass.rows[i] + if ((list.order_process == "进行中" || list.order_process == "暂离" || list.order_process == "审核通过") && list.order_type == mode) { + order_process = list.order_process + break + } + } + } + return order_process + } + + fun getSpace_name(data: String, mode: String): String { + val mClass = moshi.adapter(OrderListDataClass::class.java).fromJson(data) + var space_name = "" + var notHasToday = true + for (i in mClass?.rows!!.indices) { + val list = mClass.rows[i] + if ((list.order_process == "进行中" || list.order_process == "暂离" || list.order_process == "审核通过") && list.order_type == mode && list.order_date == today) { + space_name = list.space_name!! + notHasToday = false + break + } + } + if (notHasToday) { + for (i in mClass.rows.indices) { + val list = mClass.rows[i] + if ((list.order_process == "进行中" || list.order_process == "暂离" || list.order_process == "审核通过") && list.order_type == mode) { + space_name = list.space_name!! + break + } + } + } + return space_name + } + + fun getSeat_label(data: String, mode: String): String { + val mClass = moshi.adapter(OrderListDataClass::class.java).fromJson(data) + var seat_label = "" + var notHasToday = true + for (i in mClass?.rows!!.indices) { + val list = mClass.rows[i] + if ((list.order_process == "进行中" || list.order_process == "暂离" || list.order_process == "审核通过") && list.order_type == mode && list.order_date == today) { + seat_label = list.seat_label.toString() + notHasToday = false + break + } + } + if (notHasToday) { + for (i in mClass.rows.indices) { + val list = mClass.rows[i] + if ((list.order_process == "进行中" || list.order_process == "暂离" || list.order_process == "审核通过") && list.order_type == mode) { + seat_label = list.seat_label.toString() + break + } + } + } + return seat_label + } + + fun getOrder_date(data: String, mode: String): String { + val mClass = moshi.adapter(OrderListDataClass::class.java).fromJson(data) + var order_date = "" + var notHasToday = true + for (i in mClass?.rows!!.indices) { + val list = mClass.rows[i] + if ((list.order_process == "进行中" || list.order_process == "暂离" || list.order_process == "审核通过") && list.order_type == mode && list.order_date == today) { + order_date = list.order_date + notHasToday = false + break + } + } + if (notHasToday) { + for (i in mClass.rows.indices) { + val list = mClass.rows[i] + if ((list.order_process == "进行中" || list.order_process == "暂离" || list.order_process == "审核通过") && list.order_type == mode) { + order_date = list.order_date!! + break + } + } + } + return order_date + } + + fun getBack_time(data: String, mode: String, prompt: String): String { + val mClass = moshi.adapter(OrderListDataClass::class.java).fromJson(data) + var back_time = "" + for (i in mClass?.rows!!.indices) { + val list = mClass.rows[i] + if (list.order_process == "暂离" && list.order_type == mode) { + if (list.back_time != "00:00:00") { + back_time = prompt + list.back_time + } + break + } + } + return back_time + } + + fun getAll_users(data: String): String { + val mClass = moshi.adapter(OrderListDataClass::class.java).fromJson(data) + var all_users = "" + for (i in mClass?.rows!!.indices) { + val list = mClass.rows[i] + if ((list.order_process == "进行中" || list.order_process == "暂离" || list.order_process == "审核通过") && list.order_type == "1") { + all_users = list.all_users.toString() + break + } + } + return all_users + } + + fun getFull_time(data: String): String { + val mClass = moshi.adapter(OrderListDataClass::class.java).fromJson(data) + var full_time = "" + for (i in mClass?.rows!!.indices) { + val list = mClass.rows[i] + if ((list.order_process == "进行中" || list.order_process == "暂离" || list.order_process == "审核通过") && list.order_type == "1") { + full_time = list.order_start_time!!.split(" ").toTypedArray()[1] + "-" + + list.order_end_time!!.split(" ").toTypedArray()[1] + break + } + } + return full_time + } +} \ No newline at end of file diff --git a/app/src/main/java/com/qhy040404/libraryonetap/data/ReserveData.kt b/app/src/main/java/com/qhy040404/libraryonetap/data/ReserveData.kt new file mode 100644 index 00000000..a982641b --- /dev/null +++ b/app/src/main/java/com/qhy040404/libraryonetap/data/ReserveData.kt @@ -0,0 +1,10 @@ +package com.qhy040404.libraryonetap.data + +import com.qhy040404.libraryonetap.constant.GlobalManager.moshi +import com.qhy040404.libraryonetap.data.model.ReserveDataClass + +object ReserveData { + fun getAddCode(data: String): String { + return moshi.adapter(ReserveDataClass::class.java).fromJson(data)?.data!!.addCode!! + } +} \ No newline at end of file diff --git a/app/src/main/java/com/qhy040404/libraryonetap/data/SessionData.kt b/app/src/main/java/com/qhy040404/libraryonetap/data/SessionData.kt new file mode 100644 index 00000000..15700c14 --- /dev/null +++ b/app/src/main/java/com/qhy040404/libraryonetap/data/SessionData.kt @@ -0,0 +1,10 @@ +package com.qhy040404.libraryonetap.data + +import com.qhy040404.libraryonetap.constant.GlobalManager.moshi +import com.qhy040404.libraryonetap.data.model.SessionDataClass + +object SessionData { + fun isSuccess(returnData: String): Boolean { + return moshi.adapter(SessionDataClass::class.java).fromJson(returnData)?.success!! + } +} \ No newline at end of file diff --git a/app/src/main/java/com/qhy040404/libraryonetap/data/VolunteerData.kt b/app/src/main/java/com/qhy040404/libraryonetap/data/VolunteerData.kt new file mode 100644 index 00000000..b1eecdd1 --- /dev/null +++ b/app/src/main/java/com/qhy040404/libraryonetap/data/VolunteerData.kt @@ -0,0 +1,18 @@ +package com.qhy040404.libraryonetap.data + +import com.qhy040404.libraryonetap.constant.GlobalManager.moshi +import com.qhy040404.libraryonetap.data.model.VolunteerDataClass + +object VolunteerData { + fun getSameID(data: String): Int { + return moshi.adapter(VolunteerDataClass::class.java).fromJson(data)?.numSameID!! + } + + fun getSameName(data: String): Int { + return moshi.adapter(VolunteerDataClass::class.java).fromJson(data)?.numSameName!! + } + + fun getTotalHours(data: String): Double { + return moshi.adapter(VolunteerDataClass::class.java).fromJson(data)?.totalDuration!! + } +} \ No newline at end of file diff --git a/app/src/main/java/com/qhy040404/libraryonetap/data/model/CancelDataClass.kt b/app/src/main/java/com/qhy040404/libraryonetap/data/model/CancelDataClass.kt new file mode 100644 index 00000000..c05b469d --- /dev/null +++ b/app/src/main/java/com/qhy040404/libraryonetap/data/model/CancelDataClass.kt @@ -0,0 +1,5 @@ +package com.qhy040404.libraryonetap.data.model + +data class CancelDataClass( + val message: String? = null, +) diff --git a/app/src/main/java/com/qhy040404/libraryonetap/data/model/ElectricDataClass.kt b/app/src/main/java/com/qhy040404/libraryonetap/data/model/ElectricDataClass.kt new file mode 100644 index 00000000..798468cc --- /dev/null +++ b/app/src/main/java/com/qhy040404/libraryonetap/data/model/ElectricDataClass.kt @@ -0,0 +1,6 @@ +package com.qhy040404.libraryonetap.data.model + +@Suppress("SpellCheckingInspection") +data class ElectricDataClass( + val dormitoryInfo_list: List? = null, +) diff --git a/app/src/main/java/com/qhy040404/libraryonetap/data/model/ElectricInnerDataClass.kt b/app/src/main/java/com/qhy040404/libraryonetap/data/model/ElectricInnerDataClass.kt new file mode 100644 index 00000000..a248a628 --- /dev/null +++ b/app/src/main/java/com/qhy040404/libraryonetap/data/model/ElectricInnerDataClass.kt @@ -0,0 +1,7 @@ +package com.qhy040404.libraryonetap.data.model + +@Suppress("SpellCheckingInspection") +data class ElectricInnerDataClass( + val SSMC: String? = null, + val resele: String? = null, +) diff --git a/app/src/main/java/com/qhy040404/libraryonetap/data/model/NetDataClass.kt b/app/src/main/java/com/qhy040404/libraryonetap/data/model/NetDataClass.kt new file mode 100644 index 00000000..1e5733c0 --- /dev/null +++ b/app/src/main/java/com/qhy040404/libraryonetap/data/model/NetDataClass.kt @@ -0,0 +1,7 @@ +package com.qhy040404.libraryonetap.data.model + +data class NetDataClass( + val fee: String? = null, + val dynamicRemainFlow: String? = null, + val dynamicUsedFlow: String? = null, +) diff --git a/app/src/main/java/com/qhy040404/libraryonetap/data/model/OrderListDataClass.kt b/app/src/main/java/com/qhy040404/libraryonetap/data/model/OrderListDataClass.kt new file mode 100644 index 00000000..296d4293 --- /dev/null +++ b/app/src/main/java/com/qhy040404/libraryonetap/data/model/OrderListDataClass.kt @@ -0,0 +1,6 @@ +package com.qhy040404.libraryonetap.data.model + +data class OrderListDataClass( + val total: String? = null, + val rows: List? = null, +) diff --git a/app/src/main/java/com/qhy040404/libraryonetap/data/model/OrderListInnerDataClass.kt b/app/src/main/java/com/qhy040404/libraryonetap/data/model/OrderListInnerDataClass.kt new file mode 100644 index 00000000..750e1491 --- /dev/null +++ b/app/src/main/java/com/qhy040404/libraryonetap/data/model/OrderListInnerDataClass.kt @@ -0,0 +1,14 @@ +package com.qhy040404.libraryonetap.data.model + +data class OrderListInnerDataClass( + val order_id: String? = null, + val order_type: String? = null, + val space_name: String? = null, + val seat_label: Any? = null, + val all_users: Any? = null, + val order_start_time: String? = null, + val order_date: String? = null, + val back_time: String? = null, + val order_end_time: String? = null, + val order_process: String? = null, +) diff --git a/app/src/main/java/com/qhy040404/libraryonetap/data/model/ReserveDataClass.kt b/app/src/main/java/com/qhy040404/libraryonetap/data/model/ReserveDataClass.kt new file mode 100644 index 00000000..d27aef87 --- /dev/null +++ b/app/src/main/java/com/qhy040404/libraryonetap/data/model/ReserveDataClass.kt @@ -0,0 +1,5 @@ +package com.qhy040404.libraryonetap.data.model + +data class ReserveDataClass( + val data: ReserveInnerDataClass? = null, +) diff --git a/app/src/main/java/com/qhy040404/libraryonetap/data/model/ReserveInnerDataClass.kt b/app/src/main/java/com/qhy040404/libraryonetap/data/model/ReserveInnerDataClass.kt new file mode 100644 index 00000000..c8abe258 --- /dev/null +++ b/app/src/main/java/com/qhy040404/libraryonetap/data/model/ReserveInnerDataClass.kt @@ -0,0 +1,5 @@ +package com.qhy040404.libraryonetap.data.model + +data class ReserveInnerDataClass( + val addCode: String? = null, +) diff --git a/app/src/main/java/com/qhy040404/libraryonetap/data/model/SessionDataClass.kt b/app/src/main/java/com/qhy040404/libraryonetap/data/model/SessionDataClass.kt new file mode 100644 index 00000000..ba69258c --- /dev/null +++ b/app/src/main/java/com/qhy040404/libraryonetap/data/model/SessionDataClass.kt @@ -0,0 +1,5 @@ +package com.qhy040404.libraryonetap.data.model + +data class SessionDataClass( + val success: Boolean = false, +) diff --git a/app/src/main/java/com/qhy040404/libraryonetap/data/model/VolunteerDataClass.kt b/app/src/main/java/com/qhy040404/libraryonetap/data/model/VolunteerDataClass.kt new file mode 100644 index 00000000..349f817e --- /dev/null +++ b/app/src/main/java/com/qhy040404/libraryonetap/data/model/VolunteerDataClass.kt @@ -0,0 +1,7 @@ +package com.qhy040404.libraryonetap.data.model + +data class VolunteerDataClass( + val numSameID: Int = 0, + val numSameName: Int = 0, + val totalDuration: Double = 0.0, +) diff --git a/app/src/main/java/com/qhy040404/libraryonetap/datamodel/CancelData.kt b/app/src/main/java/com/qhy040404/libraryonetap/datamodel/CancelData.kt deleted file mode 100644 index ce7e8e01..00000000 --- a/app/src/main/java/com/qhy040404/libraryonetap/datamodel/CancelData.kt +++ /dev/null @@ -1,14 +0,0 @@ -package com.qhy040404.libraryonetap.datamodel - -import com.qhy040404.libraryonetap.constant.GlobalManager.gson -import java.io.Serializable - -object CancelData { - fun getMessage(returnData: String?): String { - return gson.fromJson(returnData, GsonData::class.java).message!! - } - - private class GsonData : Serializable { - val message: String? = null - } -} \ No newline at end of file diff --git a/app/src/main/java/com/qhy040404/libraryonetap/datamodel/ElectricData.kt b/app/src/main/java/com/qhy040404/libraryonetap/datamodel/ElectricData.kt deleted file mode 100644 index 7c087721..00000000 --- a/app/src/main/java/com/qhy040404/libraryonetap/datamodel/ElectricData.kt +++ /dev/null @@ -1,27 +0,0 @@ -package com.qhy040404.libraryonetap.datamodel - -import com.google.gson.annotations.SerializedName -import com.qhy040404.libraryonetap.constant.GlobalManager.gson -import java.io.Serializable - -@Suppress("SpellCheckingInspection") -object ElectricData { - fun getSSMC(data: String?): String { - return gson.fromJson(data, GsonData::class.java).dormitoryInfo_list!![0].ssmc!! - } - - fun getResele(data: String?): String { - return gson.fromJson(data, GsonData::class.java).dormitoryInfo_list!![0].resele!! - } - - @Suppress("PropertyName") - private class GsonData : Serializable { - val dormitoryInfo_list: List? = null - - class DormitoryInfoListBean : Serializable { - @SerializedName("SSMC") - val ssmc: String? = null - val resele: String? = null - } - } -} \ No newline at end of file diff --git a/app/src/main/java/com/qhy040404/libraryonetap/datamodel/NetData.kt b/app/src/main/java/com/qhy040404/libraryonetap/datamodel/NetData.kt deleted file mode 100644 index b8648096..00000000 --- a/app/src/main/java/com/qhy040404/libraryonetap/datamodel/NetData.kt +++ /dev/null @@ -1,24 +0,0 @@ -package com.qhy040404.libraryonetap.datamodel - -import com.qhy040404.libraryonetap.constant.GlobalManager.gson -import java.io.Serializable - -object NetData { - fun getFee(data: String?): String { - return gson.fromJson(data, GsonData::class.java).fee!! - } - - fun getDynamicUsedFlow(data: String?): String { - return gson.fromJson(data, GsonData::class.java).dynamicUsedFlow!! - } - - fun getDynamicRemainFlow(data: String?): String { - return gson.fromJson(data, GsonData::class.java).dynamicRemainFlow!! - } - - private class GsonData : Serializable { - val fee: String? = null - val dynamicRemainFlow: String? = null - val dynamicUsedFlow: String? = null - } -} \ No newline at end of file diff --git a/app/src/main/java/com/qhy040404/libraryonetap/datamodel/OrderListData.kt b/app/src/main/java/com/qhy040404/libraryonetap/datamodel/OrderListData.kt deleted file mode 100644 index f9c98bc6..00000000 --- a/app/src/main/java/com/qhy040404/libraryonetap/datamodel/OrderListData.kt +++ /dev/null @@ -1,219 +0,0 @@ -package com.qhy040404.libraryonetap.datamodel - -import com.qhy040404.libraryonetap.constant.GlobalManager.gson -import com.qhy040404.libraryonetap.utils.TimeUtils -import java.io.Serializable - -@Suppress("FunctionName") -object OrderListData { - fun getTotal(data: String): String { - return gson.fromJson(data, GsonData::class.java).total!! - } - - fun getOrder_id(data: String, mode: String): String { - return gson.fromJson(data, GsonData::class.java).getOrder_id(mode) - } - - fun getOrder_process(data: String, mode: String): String { - return gson.fromJson(data, GsonData::class.java).getOrder_process(mode) - } - - fun getSpace_name(data: String, mode: String): String { - return gson.fromJson(data, GsonData::class.java).getSpace_name(mode) - } - - fun getSeat_label(data: String, mode: String): String { - return gson.fromJson(data, GsonData::class.java).getSeat_label(mode) - } - - fun getOrder_date(data: String, mode: String): String { - return gson.fromJson(data, GsonData::class.java).getOrder_date(mode) - } - - fun getBack_time(data: String, mode: String, prompt: String): String { - return gson.fromJson(data, GsonData::class.java).getBack_time(mode, prompt) - } - - fun getAll_users(data: String): String { - return gson.fromJson(data, GsonData::class.java).getAll_users() - } - - fun getFull_time(data: String): String { - return gson.fromJson(data, GsonData::class.java).getFull_time() - } - - @Suppress("LocalVariableName", "PropertyName") - private class GsonData : Serializable { - val today = TimeUtils.getToday("-", true) - val total: String? = null - val rows: List? = null - - fun getOrder_id(mode: String): String { - var order_id = "oid" - var notHasToday = true - for (i in rows!!.indices) { - val list = rows[i] - if ((list.order_process == "进行中" || list.order_process == "暂离" || list.order_process == "审核通过") && list.order_type == mode && list.order_date == today) { - order_id = list.order_id!! - notHasToday = false - break - } - } - if (notHasToday) { - for (i in rows.indices) { - val list = rows[i] - if ((list.order_process == "进行中" || list.order_process == "暂离" || list.order_process == "审核通过") && list.order_type == mode) { - order_id = list.order_id!! - break - } - } - } - return order_id - } - - fun getOrder_process(mode: String): String { - var order_process = "" - var notHasToday = true - for (i in rows!!.indices) { - val list = rows[i] - if ((list.order_process == "进行中" || list.order_process == "暂离" || list.order_process == "审核通过") && list.order_type == mode && list.order_date == today) { - order_process = list.order_process - notHasToday = false - break - } - } - if (notHasToday) { - for (i in rows.indices) { - val list = rows[i] - if ((list.order_process == "进行中" || list.order_process == "暂离" || list.order_process == "审核通过") && list.order_type == mode) { - order_process = list.order_process - break - } - } - } - return order_process - } - - fun getSpace_name(mode: String): String { - var space_name = "" - var notHasToday = true - for (i in rows!!.indices) { - val list = rows[i] - if ((list.order_process == "进行中" || list.order_process == "暂离" || list.order_process == "审核通过") && list.order_type == mode && list.order_date == today) { - space_name = list.space_name!! - notHasToday = false - break - } - } - if (notHasToday) { - for (i in rows.indices) { - val list = rows[i] - if ((list.order_process == "进行中" || list.order_process == "暂离" || list.order_process == "审核通过") && list.order_type == mode) { - space_name = list.space_name!! - break - } - } - } - return space_name - } - - fun getSeat_label(mode: String): String { - var seat_label = "" - var notHasToday = true - for (i in rows!!.indices) { - val list = rows[i] - if ((list.order_process == "进行中" || list.order_process == "暂离" || list.order_process == "审核通过") && list.order_type == mode && list.order_date == today) { - seat_label = list.seat_label.toString() - notHasToday = false - break - } - } - if (notHasToday) { - for (i in rows.indices) { - val list = rows[i] - if ((list.order_process == "进行中" || list.order_process == "暂离" || list.order_process == "审核通过") && list.order_type == mode) { - seat_label = list.seat_label.toString() - break - } - } - } - return seat_label - } - - fun getOrder_date(mode: String): String { - var order_date = "" - var notHasToday = true - for (i in rows!!.indices) { - val list = rows[i] - if ((list.order_process == "进行中" || list.order_process == "暂离" || list.order_process == "审核通过") && list.order_type == mode && list.order_date == today) { - order_date = list.order_date - notHasToday = false - break - } - } - if (notHasToday) { - for (i in rows.indices) { - val list = rows[i] - if ((list.order_process == "进行中" || list.order_process == "暂离" || list.order_process == "审核通过") && list.order_type == mode) { - order_date = list.order_date!! - break - } - } - } - return order_date - } - - fun getBack_time(mode: String, prompt: String): String { - var back_time = "" - for (i in rows!!.indices) { - val list = rows[i] - if (list.order_process == "暂离" && list.order_type == mode) { - if (list.back_time != "00:00:00") { - back_time = prompt + list.back_time - } - break - } - } - return back_time - } - - fun getAll_users(): String { - var all_users = "" - for (i in rows!!.indices) { - val list = rows[i] - if ((list.order_process == "进行中" || list.order_process == "暂离" || list.order_process == "审核通过") && list.order_type == "1") { - all_users = list.all_users.toString() - break - } - } - return all_users - } - - fun getFull_time(): String { - var full_time = "" - for (i in rows!!.indices) { - val list = rows[i] - if ((list.order_process == "进行中" || list.order_process == "暂离" || list.order_process == "审核通过") && list.order_type == "1") { - full_time = list.order_start_time!!.split(" ") - .toTypedArray()[1] + "-" + list.order_end_time!!.split(" ") - .toTypedArray()[1] - break - } - } - return full_time - } - - class RowsBean : Serializable { - val order_id: String? = null - val order_type: String? = null - val space_name: String? = null - val seat_label: Any? = null - val all_users: Any? = null - val order_start_time: String? = null - val order_date: String? = null - val back_time: String? = null - val order_end_time: String? = null - val order_process: String? = null - } - } -} \ No newline at end of file diff --git a/app/src/main/java/com/qhy040404/libraryonetap/datamodel/ReserveData.kt b/app/src/main/java/com/qhy040404/libraryonetap/datamodel/ReserveData.kt deleted file mode 100644 index ed692503..00000000 --- a/app/src/main/java/com/qhy040404/libraryonetap/datamodel/ReserveData.kt +++ /dev/null @@ -1,18 +0,0 @@ -package com.qhy040404.libraryonetap.datamodel - -import com.qhy040404.libraryonetap.constant.GlobalManager.gson -import java.io.Serializable - -object ReserveData { - fun getAddCode(data: String?): String { - return gson.fromJson(data, GsonData::class.java).data!!.addCode!! - } - - private class GsonData : Serializable { - val data: DataBean? = null - - class DataBean : Serializable { - val addCode: String? = null - } - } -} \ No newline at end of file diff --git a/app/src/main/java/com/qhy040404/libraryonetap/datamodel/SessionData.kt b/app/src/main/java/com/qhy040404/libraryonetap/datamodel/SessionData.kt deleted file mode 100644 index 41236b40..00000000 --- a/app/src/main/java/com/qhy040404/libraryonetap/datamodel/SessionData.kt +++ /dev/null @@ -1,14 +0,0 @@ -package com.qhy040404.libraryonetap.datamodel - -import com.qhy040404.libraryonetap.constant.GlobalManager.gson -import java.io.Serializable - -object SessionData { - fun isSuccess(returnData: String?): Boolean { - return gson.fromJson(returnData, GsonData::class.java).success - } - - private class GsonData : Serializable { - val success = false - } -} \ No newline at end of file diff --git a/app/src/main/java/com/qhy040404/libraryonetap/datamodel/VolunteerData.kt b/app/src/main/java/com/qhy040404/libraryonetap/datamodel/VolunteerData.kt deleted file mode 100644 index 22a14dd1..00000000 --- a/app/src/main/java/com/qhy040404/libraryonetap/datamodel/VolunteerData.kt +++ /dev/null @@ -1,24 +0,0 @@ -package com.qhy040404.libraryonetap.datamodel - -import com.qhy040404.libraryonetap.constant.GlobalManager.gson -import java.io.Serializable - -object VolunteerData { - fun getSameID(data: String?): Int { - return gson.fromJson(data, GsonData::class.java).numSameID - } - - fun getSameName(data: String?): Int { - return gson.fromJson(data, GsonData::class.java).numSameName - } - - fun getTotalHours(data: String?): Double { - return gson.fromJson(data, GsonData::class.java).totalDuration - } - - private class GsonData : Serializable { - val numSameID = 0 - val numSameName = 0 - val totalDuration = 0.0 - } -} \ No newline at end of file diff --git a/app/src/main/java/com/qhy040404/libraryonetap/fragment/IAppBarContainer.kt b/app/src/main/java/com/qhy040404/libraryonetap/fragment/IAppBarContainer.kt new file mode 100644 index 00000000..fdf6f08a --- /dev/null +++ b/app/src/main/java/com/qhy040404/libraryonetap/fragment/IAppBarContainer.kt @@ -0,0 +1,8 @@ +package com.qhy040404.libraryonetap.fragment + +import android.view.View + +interface IAppBarContainer { + fun scheduleAppbarLiftingStatus(isLifted: Boolean, from: String) + fun setLiftOnScrollTargetView(targetView: View) +} diff --git a/app/src/main/java/com/qhy040404/libraryonetap/fragment/IListController.kt b/app/src/main/java/com/qhy040404/libraryonetap/fragment/IListController.kt new file mode 100644 index 00000000..4eba7b50 --- /dev/null +++ b/app/src/main/java/com/qhy040404/libraryonetap/fragment/IListController.kt @@ -0,0 +1,11 @@ +package com.qhy040404.libraryonetap.fragment + +import androidx.recyclerview.widget.RecyclerView +import rikka.widget.borderview.BorderViewDelegate + +interface IListController { + fun onReturnTop() + fun getBorderViewDelegate(): BorderViewDelegate? + fun isAllowRefreshing(): Boolean + fun getSuitableLayoutManager(): RecyclerView.LayoutManager? +} \ No newline at end of file diff --git a/app/src/main/java/com/qhy040404/libraryonetap/fragment/SettingsFragment.kt b/app/src/main/java/com/qhy040404/libraryonetap/fragment/SettingsFragment.kt index 16347bac..d21443a0 100644 --- a/app/src/main/java/com/qhy040404/libraryonetap/fragment/SettingsFragment.kt +++ b/app/src/main/java/com/qhy040404/libraryonetap/fragment/SettingsFragment.kt @@ -2,57 +2,99 @@ package com.qhy040404.libraryonetap.fragment import android.content.Intent import android.os.Bundle -import androidx.appcompat.app.AlertDialog +import android.view.LayoutInflater +import android.view.ViewGroup +import android.widget.FrameLayout +import android.widget.Toast import androidx.preference.Preference import androidx.preference.PreferenceFragmentCompat +import androidx.recyclerview.widget.RecyclerView +import com.absinthe.libraries.utils.extensions.addPaddingTop +import com.absinthe.libraries.utils.utils.UiUtils +import com.google.android.material.dialog.MaterialAlertDialogBuilder import com.qhy040404.libraryonetap.LibraryOneTapApp import com.qhy040404.libraryonetap.R import com.qhy040404.libraryonetap.constant.Constants import com.qhy040404.libraryonetap.constant.GlobalManager -import com.qhy040404.libraryonetap.ui.AboutActivity +import com.qhy040404.libraryonetap.constant.GlobalValues +import com.qhy040404.libraryonetap.ui.about.AboutActivity +import com.qhy040404.libraryonetap.utils.AppUtils +import com.qhy040404.libraryonetap.utils.CacheUtils import com.qhy040404.libraryonetap.utils.SPUtils +import rikka.material.app.DayNightDelegate +import rikka.material.app.LocaleDelegate +import rikka.material.preference.MaterialSwitchPreference import rikka.preference.SimpleMenuPreference -import kotlin.system.exitProcess +import rikka.recyclerview.fixEdgeEffect +import rikka.widget.borderview.BorderRecyclerView +import rikka.widget.borderview.BorderView +import rikka.widget.borderview.BorderViewDelegate +import java.util.* + +class SettingsFragment : PreferenceFragmentCompat(), IListController { + + private lateinit var borderViewDelegate: BorderViewDelegate + private lateinit var prefRecyclerView: RecyclerView -class SettingsFragment : PreferenceFragmentCompat() { override fun onCreatePreferences(savedInstanceState: Bundle?, rootKey: String?) { setPreferencesFromResource(R.xml.root_preferences, rootKey) + findPreference(Constants.PREF_THEME)?.isVisible = !GlobalValues.md3 + findPreference(Constants.PREF_DARK)?.apply { - setOnPreferenceChangeListener { _, _ -> + setOnPreferenceChangeListener { _, newValue -> + GlobalValues.darkMode = newValue.toString() + DayNightDelegate.setDefaultNightMode(AppUtils.getNightMode(newValue.toString())) activity?.recreate() true } } findPreference(Constants.PREF_THEME)?.apply { - setOnPreferenceChangeListener { _, _ -> + setOnPreferenceChangeListener { _, newValue -> + GlobalValues.theme = newValue.toString() GlobalManager.lazyMgr.reset() activity?.recreate() true } } - findPreference(Constants.PREF_LOCALE)?.apply { - setOnPreferenceChangeListener { _, _ -> + findPreference(Constants.PREF_MD3)?.apply { + setOnPreferenceChangeListener { _, newValue -> + GlobalValues.md3 = newValue as Boolean activity?.recreate() true } } + findPreference(Constants.PREF_LOCALE)?.apply { + setOnPreferenceChangeListener { _, newValue -> + if (newValue is String) { + val locale: Locale = if ("SYSTEM" == newValue) { + LocaleDelegate.systemLocale + } else { + Locale.forLanguageTag(newValue) + } + LocaleDelegate.defaultLocale = locale + activity?.recreate() + } + true + } + } + findPreference(Constants.PREF_RESET)?.apply { setOnPreferenceClickListener { - AlertDialog.Builder(requireContext()) + MaterialAlertDialogBuilder(requireContext()) .setMessage(R.string.dataResetConfirm) .setTitle(R.string.title_activity_settings) .setPositiveButton(R.string.ok) { _, _ -> SPUtils.resetAll() - AlertDialog.Builder(requireContext()) + MaterialAlertDialogBuilder(requireContext()) .setMessage(R.string.dataResetFinish) .setTitle(R.string.title_activity_settings) .setPositiveButton(R.string.ok) { _, _ -> LibraryOneTapApp.instance?.exit() - exitProcess(0) + AppUtils.clearAppData(LibraryOneTapApp.app) } .setCancelable(false) .create() @@ -65,11 +107,76 @@ class SettingsFragment : PreferenceFragmentCompat() { } } + findPreference(Constants.PREF_CACHE)?.apply { + summary = CacheUtils.getCacheSize() + setOnPreferenceClickListener { + CacheUtils.trimCaches() + Toast.makeText(requireContext(), R.string.cacheCleared, Toast.LENGTH_SHORT) + .show() + summary = "0.00 K" + true + } + } + findPreference(Constants.PREF_ABOUT)?.apply { + summary = GlobalValues.version setOnPreferenceClickListener { startActivity(Intent(requireContext(), AboutActivity::class.java)) true } } } + + override fun onResume() { + super.onResume() + scheduleAppbarRaisingStatus( + !getBorderViewDelegate().isShowingTopBorder, + "SettingsFragment onResume" + ) + (activity as? IAppBarContainer)?.setLiftOnScrollTargetView(prefRecyclerView) + } + + override fun onCreateRecyclerView( + inflater: LayoutInflater, + parent: ViewGroup, + savedInstanceState: Bundle?, + ): RecyclerView { + val recyclerView = + super.onCreateRecyclerView(inflater, parent, savedInstanceState) as BorderRecyclerView + recyclerView.id = android.R.id.list + recyclerView.fixEdgeEffect() + recyclerView.addPaddingTop(UiUtils.getStatusBarHeight()) + recyclerView.overScrollMode = RecyclerView.OVER_SCROLL_NEVER + recyclerView.isVerticalScrollBarEnabled = false + + val lp = recyclerView.layoutParams + if (lp is FrameLayout.LayoutParams) { + lp.rightMargin = + recyclerView.context.resources.getDimension(rikka.material.R.dimen.rd_activity_horizontal_margin) + .toInt() + lp.leftMargin = lp.rightMargin + } + + borderViewDelegate = recyclerView.borderViewDelegate + borderViewDelegate.borderVisibilityChangedListener = + BorderView.OnBorderVisibilityChangedListener { top: Boolean, _: Boolean, _: Boolean, _: Boolean -> + scheduleAppbarRaisingStatus( + !top, + "SettingsFragment OnBorderVisibilityChangedListener: top=$top" + ) + } + + prefRecyclerView = recyclerView + return recyclerView + } + + private fun scheduleAppbarRaisingStatus(isLifted: Boolean, from: String) { + (activity as? IAppBarContainer)?.scheduleAppbarLiftingStatus(isLifted, from) + } + + override fun onReturnTop() {} + + override fun getBorderViewDelegate(): BorderViewDelegate = borderViewDelegate + override fun isAllowRefreshing(): Boolean = true + override fun getSuitableLayoutManager(): RecyclerView.LayoutManager? = null } \ No newline at end of file diff --git a/app/src/main/java/com/qhy040404/libraryonetap/fragment/library/DetailFragment.kt b/app/src/main/java/com/qhy040404/libraryonetap/fragment/library/DetailFragment.kt new file mode 100644 index 00000000..b095f37b --- /dev/null +++ b/app/src/main/java/com/qhy040404/libraryonetap/fragment/library/DetailFragment.kt @@ -0,0 +1,431 @@ +package com.qhy040404.libraryonetap.fragment.library + +import android.annotation.SuppressLint +import android.graphics.BitmapFactory +import android.os.Looper +import android.os.StrictMode +import android.view.View +import android.widget.Button +import android.widget.ImageView +import android.widget.ProgressBar +import android.widget.TextView +import com.google.android.material.dialog.MaterialAlertDialogBuilder +import com.qhy040404.libraryonetap.LibraryOneTapApp +import com.qhy040404.libraryonetap.R +import com.qhy040404.libraryonetap.base.BaseFragment +import com.qhy040404.libraryonetap.constant.Constants +import com.qhy040404.libraryonetap.constant.GlobalValues +import com.qhy040404.libraryonetap.constant.URLManager +import com.qhy040404.libraryonetap.data.CancelData +import com.qhy040404.libraryonetap.data.OrderListData +import com.qhy040404.libraryonetap.data.ReserveData +import com.qhy040404.libraryonetap.data.SessionData +import com.qhy040404.libraryonetap.databinding.FragmentDetailBinding +import com.qhy040404.libraryonetap.ui.dialog.ReserveDialog +import com.qhy040404.libraryonetap.utils.AppUtils +import com.qhy040404.libraryonetap.utils.ReserveUtils +import com.qhy040404.libraryonetap.utils.TimeUtils +import com.qhy040404.libraryonetap.utils.des.DesEncryptUtils +import com.qhy040404.libraryonetap.utils.web.Requests +import okhttp3.Call +import okhttp3.Callback +import okhttp3.Request +import okhttp3.Response +import java.io.IOException + +@Suppress("LocalVariableName") +class DetailFragment : BaseFragment() { + override fun init() = initView() + + private fun initView() { + val textView: TextView = binding.textView + textView.visibility = View.VISIBLE + Thread(Detail()).start() + } + + private inner class Detail : Runnable { + @SuppressLint("SetTextI18n") + override fun run() { + Looper.prepare() + StrictMode.setThreadPolicy( + StrictMode.ThreadPolicy.Builder() + .detectDiskReads().detectDiskWrites().detectNetwork() + .penaltyLog().build() + ) + StrictMode.setVmPolicy( + StrictMode.VmPolicy.Builder() + .detectLeakedSqlLiteObjects().detectLeakedClosableObjects() + .penaltyLog().penaltyDeath().build() + ) + + val textView = binding.textView + val leave = binding.button4 + val tempLeave: Button = binding.button5 + val enter: Button = binding.button6 + val imageView: ImageView = binding.imageView + val refresh: Button = binding.button7 + val cancel: Button = binding.button10 + val reserve: Button = binding.button11 + val reset: Button = binding.button9 + val tempReset: Button = binding.button14 + val progressBar: ProgressBar = binding.progressBar + + val des = DesEncryptUtils() + + val id: String = GlobalValues.id + val passwd: String = GlobalValues.passwd + + var loginSuccess = false + var timer = 0 + while (!loginSuccess && AppUtils.checkData(id, passwd)) { + val ltResponse: String = Requests.get(URLManager.LIBRARY_SSO_URL) + val ltData: String = try { + "LT" + ltResponse.split("LT")[1].split("cas")[0] + "cas" + } catch (e: Exception) { + "" + } + + if (ltData != "") { + val rawData = "$id$passwd$ltData" + val rsa: String = des.strEnc(rawData, "1", "2", "3") + + Requests.post( + URLManager.LIBRARY_SSO_URL, + Requests.loginPostData(id, passwd, ltData, rsa), + GlobalValues.ctSso + ) + } + + val session: String = + Requests.post(URLManager.LIBRARY_SESSION_URL, "", GlobalValues.ctSso) + if (SessionData.isSuccess(session)) { + progressBar.post { progressBar.visibility = View.INVISIBLE } + loginSuccess = true + } else { + timer++ + if (timer >= 3) { + textView.post { + textView.text = LibraryOneTapApp.app.getString(R.string.failTimes) + } + Looper.loop() + break + } + } + } + val list = Requests.get(URLManager.LIBRARY_ORDER_LIST_URL) + val total = OrderListData.getTotal(list) + refresh.post { refresh.setOnClickListener { requireActivity().recreate() } } + if (total != "0") { + val space_name = OrderListData.getSpace_name(list, "2") + val seat_label = OrderListData.getSeat_label(list, "2") + val order_date = OrderListData.getOrder_date(list, "2") + var order_id = OrderListData.getOrder_id(list, "2") + var order_process = OrderListData.getOrder_process(list, "2") + val back_time = + OrderListData.getBack_time(list, + "2", + LibraryOneTapApp.app.getString(R.string.tempEndTime)) + + if (order_id == "oid") { + order_id = LibraryOneTapApp.app.getString(R.string.noValidOrder) + reserve.post { + reserve.visibility = View.VISIBLE + reserve.isClickable = true + } + } + + if (order_process == "审核通过") { + order_process = LibraryOneTapApp.app.getString(R.string.notStart) + + cancel.post { + cancel.visibility = View.VISIBLE + cancel.isClickable = true + } + + val today = TimeUtils.getToday("-", true) + if (order_date != today) { + reserve.post { + reserve.visibility = View.VISIBLE + reserve.isClickable = true + } + } else { + reset.post { + reset.visibility = View.VISIBLE + reset.isClickable = true + } + } + } else if (order_process == "进行中") { + order_process = LibraryOneTapApp.app.getString(R.string.inside) + } else if (order_process == "暂离") { + order_process = LibraryOneTapApp.app.getString(R.string.outside) + tempReset.post { + tempReset.visibility = View.VISIBLE + tempReset.isClickable = true + } + } + + enter.post { + enter.setOnClickListener { + val request = + Request.Builder() + .url(URLManager.getQRUrl(Constants.LIBRARY_METHOD_IN, order_id)) + .build() + val call = Requests.client.newCall(request) + call.enqueue(object : Callback { + override fun onFailure(call: Call, e: IOException) {} + + override fun onResponse(call: Call, response: Response) { + val picture_bt = response.body!!.bytes() + val pictureInput = response.body!!.byteStream() + val bitmap = + BitmapFactory.decodeByteArray(picture_bt, 0, picture_bt.size) + imageView.post { imageView.setImageBitmap(bitmap) } + pictureInput.close() + } + }) + } + } + leave.post { + leave.setOnClickListener { + val request = + Request.Builder() + .url(URLManager.getQRUrl(Constants.LIBRARY_METHOD_OUT, order_id)) + .build() + val call = Requests.client.newCall(request) + call.enqueue(object : Callback { + override fun onFailure(call: Call, e: IOException) {} + + override fun onResponse(call: Call, response: Response) { + val picture_bt = response.body!!.bytes() + val pictureInput = response.body!!.byteStream() + val bitmap = + BitmapFactory.decodeByteArray(picture_bt, 0, picture_bt.size) + imageView.post { imageView.setImageBitmap(bitmap) } + pictureInput.close() + } + }) + } + } + tempLeave.post { + tempLeave.setOnClickListener { + val request = + Request.Builder() + .url(URLManager.getQRUrl(Constants.LIBRARY_METHOD_TEMP, order_id)) + .build() + val call = Requests.client.newCall(request) + call.enqueue(object : Callback { + override fun onFailure(call: Call, e: IOException) {} + + override fun onResponse(call: Call, response: Response) { + val picture_bt = response.body!!.bytes() + val pictureInput = response.body!!.byteStream() + val bitmap = + BitmapFactory.decodeByteArray(picture_bt, 0, picture_bt.size) + imageView.post { imageView.setImageBitmap(bitmap) } + pictureInput.close() + } + }) + } + } + cancel.post { + cancel.setOnClickListener { + StrictMode.setThreadPolicy( + StrictMode.ThreadPolicy.Builder() + .detectDiskReads().detectDiskWrites().detectNetwork() + .penaltyLog().build() + ) + StrictMode.setVmPolicy( + StrictMode.VmPolicy.Builder() + .detectLeakedSqlLiteObjects().detectLeakedClosableObjects() + .penaltyLog().penaltyDeath().build() + ) + MaterialAlertDialogBuilder(requireContext()) + .setMessage(R.string.confirmCancel) + .setTitle(R.string.library) + .setPositiveButton(R.string.justCancel) { _, _ -> + val message = CancelData.getMessage( + Requests.post( + URLManager.LIBRARY_ORDER_OPERATION_URL, + "order_id=$order_id&order_type=2&method=Cancel", + GlobalValues.ctSso + ) + ) + MaterialAlertDialogBuilder(requireContext()) + .setMessage(message) + .setTitle(R.string.library) + .setPositiveButton(R.string.ok) { _, _ -> requireActivity().recreate() } + .setCancelable(true) + .create() + .show() + } + .setNegativeButton(R.string.cancelCancel) { _, _ -> } + .setCancelable(true) + .create() + .show() + } + } + reserve.post { + reserve.setOnClickListener { + ReserveDialog().showAlertDialog(requireActivity()) + } + } + reset.post { + reset.setOnClickListener { + StrictMode.setThreadPolicy( + StrictMode.ThreadPolicy.Builder() + .detectDiskReads().detectDiskWrites().detectNetwork() + .penaltyLog().build() + ) + StrictMode.setVmPolicy( + StrictMode.VmPolicy.Builder() + .detectLeakedSqlLiteObjects().detectLeakedClosableObjects() + .penaltyLog().penaltyDeath().build() + ) + MaterialAlertDialogBuilder(requireContext()) + .setMessage(R.string.confirmReset) + .setTitle(R.string.library) + .setPositiveButton(R.string.ok) { _, _ -> + val roomCode = ReserveUtils.getResetRoomCode(space_name).toString() + val targetSeat = "\"seat_label\":\"$seat_label\"" + var seat_id = "" + + val availableMap = ReserveUtils.formatAvailableMap( + Requests.get( + URLManager.constructAvailableUrl( + TimeUtils.getToday("/", false), + roomCode + ) + ) + ) + val amList = availableMap.split(",") + + for (element in amList) { + if (element == targetSeat) { + val i = amList.indexOf(element) + if (amList[i + 4] == Constants.RESERVE_VALID || amList[i + 4] == Constants.RESERVE_HAS_PERSON) { + seat_id = + amList[amList.indexOf(element) - 1].replace( + "\"seat_id\":", + "" + ) + .replace("\"", "") + break + } + } + } + + Requests.post( + URLManager.LIBRARY_ORDER_OPERATION_URL, + "order_id=$order_id&order_type=2&method=Cancel", + GlobalValues.ctSso + ) + + val addCodeOrigin = Requests.post( + URLManager.LIBRARY_RESERVE_ADDCODE_URL, + ReserveUtils.constructParaForAddCode(seat_id), + GlobalValues.ctVCard + ) + val addCode = ReserveData.getAddCode(addCodeOrigin) + Requests.post( + URLManager.LIBRART_RESERVE_FINAL_URL, + ReserveUtils.constructParaForFinalReserve(addCode), + GlobalValues.ctVCard + ) + requireActivity().recreate() + } + .setNegativeButton(R.string.no) { _, _ -> } + .setCancelable(false) + .create() + .show() + } + } + tempReset.post { + tempReset.setOnClickListener { + StrictMode.setThreadPolicy( + StrictMode.ThreadPolicy.Builder() + .detectDiskReads().detectDiskWrites().detectNetwork() + .penaltyLog().build() + ) + StrictMode.setVmPolicy( + StrictMode.VmPolicy.Builder() + .detectLeakedSqlLiteObjects().detectLeakedClosableObjects() + .penaltyLog().penaltyDeath().build() + ) + MaterialAlertDialogBuilder(requireContext()) + .setMessage(R.string.confirmReset) + .setTitle(R.string.library) + .setPositiveButton(R.string.ok) { _, _ -> + val roomCode = ReserveUtils.getResetRoomCode(space_name).toString() + val targetSeat = "\"seat_label\":\"$seat_label\"" + var seat_id = "" + + val availableMap = ReserveUtils.formatAvailableMap( + Requests.get( + URLManager.constructAvailableUrl( + TimeUtils.getToday("/", false), + roomCode + ) + ) + ) + val amList = availableMap.split(",") + + for (element in amList) { + if (element == targetSeat) { + val i = amList.indexOf(element) + if (amList[i + 4] == Constants.RESERVE_VALID || amList[i + 4] == Constants.RESERVE_HAS_PERSON) { + seat_id = + amList[amList.indexOf(element) - 1].replace( + "\"seat_id\":", + "" + ) + .replace("\"", "") + break + } + } + } + + Requests.post( + URLManager.LIBRARY_ORDER_OPERATION_URL, + "order_id=$order_id&order_type=2&method=Release", + GlobalValues.ctSso + ) + + val addCodeOrigin = Requests.post( + URLManager.LIBRARY_RESERVE_ADDCODE_URL, + ReserveUtils.constructParaForAddCode(seat_id), + GlobalValues.ctVCard + ) + val addCode = ReserveData.getAddCode(addCodeOrigin) + Requests.post( + URLManager.LIBRART_RESERVE_FINAL_URL, + ReserveUtils.constructParaForFinalReserve(addCode), + GlobalValues.ctVCard + ) + requireActivity().recreate() + } + .setNegativeButton(R.string.no) { _, _ -> } + .setCancelable(false) + .create() + .show() + } + } + textView.post { + textView.text = + "order_id: $order_id\n\n$order_process\n\n$space_name\n$seat_label\n$order_date\n$back_time" + } + Looper.loop() + } else if (!AppUtils.checkData(id, passwd)) { + textView.post { + textView.text = LibraryOneTapApp.app.getString(R.string.noLoginData) + } + progressBar.post { progressBar.visibility = View.INVISIBLE } + Looper.loop() + } else { + textView.post { + textView.text = LibraryOneTapApp.app.getString(R.string.loginTimeout) + } + Looper.loop() + } + } + } +} diff --git a/app/src/main/java/com/qhy040404/libraryonetap/ui/YanxiujianActivity.kt b/app/src/main/java/com/qhy040404/libraryonetap/fragment/library/YanxiujianFragment.kt similarity index 55% rename from app/src/main/java/com/qhy040404/libraryonetap/ui/YanxiujianActivity.kt rename to app/src/main/java/com/qhy040404/libraryonetap/fragment/library/YanxiujianFragment.kt index f51c6468..861126b5 100644 --- a/app/src/main/java/com/qhy040404/libraryonetap/ui/YanxiujianActivity.kt +++ b/app/src/main/java/com/qhy040404/libraryonetap/fragment/library/YanxiujianFragment.kt @@ -1,18 +1,23 @@ -package com.qhy040404.libraryonetap.ui +package com.qhy040404.libraryonetap.fragment.library import android.annotation.SuppressLint import android.graphics.BitmapFactory import android.os.Looper import android.os.StrictMode import android.view.View -import android.widget.* -import androidx.appcompat.app.AlertDialog +import android.widget.Button +import android.widget.ImageView +import android.widget.ProgressBar +import android.widget.TextView +import com.qhy040404.libraryonetap.LibraryOneTapApp import com.qhy040404.libraryonetap.R -import com.qhy040404.libraryonetap.base.BaseActivity +import com.qhy040404.libraryonetap.base.BaseFragment import com.qhy040404.libraryonetap.constant.GlobalValues import com.qhy040404.libraryonetap.constant.URLManager -import com.qhy040404.libraryonetap.datamodel.OrderListData -import com.qhy040404.libraryonetap.datamodel.SessionData +import com.qhy040404.libraryonetap.data.OrderListData +import com.qhy040404.libraryonetap.data.SessionData +import com.qhy040404.libraryonetap.databinding.FragmentYanxiujianBinding +import com.qhy040404.libraryonetap.utils.AppUtils import com.qhy040404.libraryonetap.utils.des.DesEncryptUtils import com.qhy040404.libraryonetap.utils.web.Requests import okhttp3.Call @@ -22,13 +27,11 @@ import okhttp3.Response import java.io.IOException @Suppress("LocalVariableName") -class YanxiujianActivity : BaseActivity() { +class YanxiujianFragment : BaseFragment() { override fun init() = initView() - override fun getLayoutId(): Int = R.layout.activity_yanxiujian - private fun initView() { - val textView2: TextView = findViewById(R.id.textView2) + val textView2: TextView = binding.textView2 textView2.visibility = View.VISIBLE Thread(Yanxiujian()).start() } @@ -48,10 +51,10 @@ class YanxiujianActivity : BaseActivity() { .penaltyLog().penaltyDeath().build() ) - val textView2: TextView = findViewById(R.id.textView2) - val imageView2: ImageView = findViewById(R.id.imageView2) - val refresh2: Button = findViewById(R.id.button12) - val progressBar2: ProgressBar = findViewById(R.id.progressBar2) + val textView2: TextView = binding.textView2 + val imageView2: ImageView = binding.imageView2 + val refresh2: Button = binding.button12 + val progressBar2: ProgressBar = binding.progressBar2 val des = DesEncryptUtils() @@ -60,40 +63,34 @@ class YanxiujianActivity : BaseActivity() { var loginSuccess = false var timer = 0 - while (!loginSuccess) { + while (!loginSuccess && AppUtils.checkData(id, passwd)) { val ltResponse: String = Requests.get(URLManager.LIBRARY_SSO_URL) - val ltData: String = "LT" + ltResponse.split("LT")[1].split("cas")[0] + "cas" - - val rawData = "$id$passwd$ltData" - val rsa: String = des.strEnc(rawData, "1", "2", "3") + val ltData: String = try { + "LT" + ltResponse.split("LT")[1].split("cas")[0] + "cas" + } catch (e: Exception) { + "" + } - Requests.post( - URLManager.LIBRARY_SSO_URL, - Requests.loginPostData(id, passwd, ltData, rsa), - GlobalValues.ctSso - ) + if (ltData != "") { + val rawData = "$id$passwd$ltData" + val rsa: String = des.strEnc(rawData, "1", "2", "3") - Requests.get(URLManager.LIBRARY_LOGIN_DIRECT_URL) + Requests.post( + URLManager.LIBRARY_SSO_URL, + Requests.loginPostData(id, passwd, ltData, rsa), + GlobalValues.ctSso + ) + } val session: String = Requests.post(URLManager.LIBRARY_SESSION_URL, "", GlobalValues.ctSso) if (SessionData.isSuccess(session)) { - Toast.makeText(this@YanxiujianActivity, R.string.loaded, Toast.LENGTH_SHORT) - .show() progressBar2.post { progressBar2.visibility = View.INVISIBLE } loginSuccess = true } else { - Toast.makeText(this@YanxiujianActivity, R.string.logFail, Toast.LENGTH_SHORT) - .show() timer++ if (timer >= 3) { - AlertDialog.Builder(this@YanxiujianActivity) - .setMessage(R.string.failTimes) - .setTitle(R.string.error) - .setPositiveButton(R.string.ok) { _, _ -> this@YanxiujianActivity.finish() } - .setCancelable(false) - .create() - .show() + textView2.text = LibraryOneTapApp.app.getString(R.string.failTimes) Looper.loop() break } @@ -101,6 +98,7 @@ class YanxiujianActivity : BaseActivity() { } val list = Requests.get(URLManager.LIBRARY_ORDER_LIST_URL) val total = OrderListData.getTotal(list) + refresh2.post { refresh2.setOnClickListener { requireActivity().recreate() } } if (total != "0") { val space_name = OrderListData.getSpace_name(list, "1") val order_date = OrderListData.getOrder_date(list, "1") @@ -110,19 +108,13 @@ class YanxiujianActivity : BaseActivity() { val full_time = OrderListData.getFull_time(list) if (order_id == "oid") { - order_id = getString(R.string.noValidOrder) + order_id = LibraryOneTapApp.app.getString(R.string.noValidOrder) } when (order_process) { - "审核通过" -> { - order_process = getString(R.string.notStart) - } - "进行中" -> { - order_process = getString(R.string.inside) - } - "暂离" -> { - order_process = getString(R.string.outside) - } + "审核通过" -> order_process = LibraryOneTapApp.app.getString(R.string.notStart) + "进行中" -> order_process = LibraryOneTapApp.app.getString(R.string.inside) + "暂离" -> order_process = LibraryOneTapApp.app.getString(R.string.outside) } val request = Request.Builder().url(URLManager.LIBRARY_QR_CERT_URL).build() @@ -138,18 +130,21 @@ class YanxiujianActivity : BaseActivity() { pictureInput.close() } }) - refresh2.setOnClickListener { recreate() } - textView2.text = - "order_id: $order_id\n\n$order_process\n\n$space_name\n$order_date\n$full_time\n\n$all_users" + textView2.post { + textView2.text = + "order_id: $order_id\n\n$order_process\n\n$space_name\n$order_date\n$full_time\n\n$all_users" + } + Looper.loop() + } else if (!AppUtils.checkData(id, passwd)) { + textView2.post { + textView2.text = LibraryOneTapApp.app.getString(R.string.noLoginData) + } + progressBar2.post { progressBar2.visibility = View.INVISIBLE } Looper.loop() } else { - AlertDialog.Builder(this@YanxiujianActivity) - .setMessage(R.string.loginTimeout) - .setTitle(R.string.error) - .setPositiveButton(R.string.ok) { _, _ -> this@YanxiujianActivity.finish() } - .setCancelable(false) - .create() - .show() + textView2.post { + textView2.text = LibraryOneTapApp.app.getString(R.string.loginTimeout) + } Looper.loop() } } diff --git a/app/src/main/java/com/qhy040404/libraryonetap/fragment/tools/ToolsInitFragment.kt b/app/src/main/java/com/qhy040404/libraryonetap/fragment/tools/ToolsInitFragment.kt index 9b42e120..bd4001fc 100644 --- a/app/src/main/java/com/qhy040404/libraryonetap/fragment/tools/ToolsInitFragment.kt +++ b/app/src/main/java/com/qhy040404/libraryonetap/fragment/tools/ToolsInitFragment.kt @@ -5,18 +5,20 @@ import android.os.Bundle import android.os.Looper import android.os.StrictMode import android.widget.Toast -import androidx.appcompat.app.AlertDialog import androidx.preference.Preference import androidx.preference.PreferenceFragmentCompat +import com.google.android.material.dialog.MaterialAlertDialogBuilder +import com.qhy040404.libraryonetap.LibraryOneTapApp import com.qhy040404.libraryonetap.R import com.qhy040404.libraryonetap.constant.Constants import com.qhy040404.libraryonetap.constant.GlobalValues import com.qhy040404.libraryonetap.constant.URLManager -import com.qhy040404.libraryonetap.datamodel.ElectricData -import com.qhy040404.libraryonetap.datamodel.NetData -import com.qhy040404.libraryonetap.datamodel.VolunteerData +import com.qhy040404.libraryonetap.data.ElectricData +import com.qhy040404.libraryonetap.data.NetData +import com.qhy040404.libraryonetap.data.VolunteerData import com.qhy040404.libraryonetap.ui.tools.BathReserveActivity import com.qhy040404.libraryonetap.ui.tools.VCardActivity +import com.qhy040404.libraryonetap.utils.AppUtils import com.qhy040404.libraryonetap.utils.tools.GetPortalData import com.qhy040404.libraryonetap.utils.tools.NetworkStateUtils import com.qhy040404.libraryonetap.utils.tools.PermissionUtils @@ -43,9 +45,16 @@ class ToolsInitFragment : PreferenceFragmentCompat() { Toast.makeText(requireContext(), R.string.error, Toast.LENGTH_SHORT).show() } } else if (netName == "DLUT-LingShui") { - startActivity(Intent(requireContext(), BathReserveActivity::class.java)) + if (AppUtils.checkDataAndDialog(requireContext(), + GlobalValues.id, + GlobalValues.passwd, + R.string.tools, + R.string.noLoginData) + ) { + startActivity(Intent(requireContext(), BathReserveActivity::class.java)) + } } else { - AlertDialog.Builder(requireContext()) + MaterialAlertDialogBuilder(requireContext()) .setMessage(R.string.networkLimit) .setTitle(R.string.bath_title) .setPositiveButton(R.string.ok) { _, _ -> } @@ -59,7 +68,6 @@ class ToolsInitFragment : PreferenceFragmentCompat() { findPreference(Constants.TOOLS_NET)?.apply { setOnPreferenceClickListener { - Toast.makeText(requireContext(), R.string.loading, Toast.LENGTH_SHORT).show() Thread(GetNet()).start() true } @@ -67,7 +75,6 @@ class ToolsInitFragment : PreferenceFragmentCompat() { findPreference(Constants.TOOLS_ELECTRIC)?.apply { setOnPreferenceClickListener { - Toast.makeText(requireContext(), R.string.loading, Toast.LENGTH_SHORT).show() Thread(GetElectric()).start() true } @@ -75,14 +82,20 @@ class ToolsInitFragment : PreferenceFragmentCompat() { findPreference(Constants.TOOLS_VCARD)?.apply { setOnPreferenceClickListener { - startActivity(Intent(requireContext(), VCardActivity::class.java)) + if (AppUtils.checkDataAndDialog(requireContext(), + GlobalValues.id, + GlobalValues.passwd, + R.string.tools, + R.string.noLoginData) + ) { + startActivity(Intent(requireContext(), VCardActivity::class.java)) + } true } } findPreference(Constants.TOOLS_VOLUNTEER)?.apply { setOnPreferenceClickListener { - Toast.makeText(requireContext(), R.string.loading, Toast.LENGTH_SHORT).show() Thread(GetVolunteer()).start() true } @@ -105,25 +118,37 @@ class ToolsInitFragment : PreferenceFragmentCompat() { val id: String = GlobalValues.id val passwd: String = GlobalValues.passwd - val data: String = GetPortalData.getPortalData(id, passwd, 1) - - val remainFee = NetData.getFee(data) - val usedNet = NetData.getDynamicUsedFlow(data) - val remainNet = NetData.getDynamicRemainFlow(data) - val netMessage = - getString(R.string.remainNetFeeAndColon) + remainFee + getString(R.string.rmb) + "\n" + getString( - R.string.usedNetAndColon - ) + usedNet + getString(R.string.gigabyte) + "\n" + getString(R.string.remainNetAndColon) + remainNet + getString( - R.string.gigabyte - ) - - AlertDialog.Builder(requireContext()) - .setMessage(netMessage) - .setTitle(R.string.remainNet) - .setPositiveButton(R.string.ok) { _, _ -> } - .setCancelable(true) - .create() - .show() + val checked = AppUtils.checkDataAndDialog(requireContext(), + id, + passwd, + R.string.tools, + R.string.noLoginData) + + if (checked) { + Toast.makeText(requireContext(), R.string.loading, Toast.LENGTH_SHORT).show() + + val data: String = GetPortalData.getPortalData(id, passwd, 1) + + val remainFee = NetData.getFee(data) + val usedNet = NetData.getDynamicUsedFlow(data) + val remainNet = NetData.getDynamicRemainFlow(data) + val netMessage = + LibraryOneTapApp.app.getString(R.string.remainNetFeeAndColon) + remainFee + LibraryOneTapApp.app.getString( + R.string.rmb) + "\n" + LibraryOneTapApp.app.getString( + R.string.usedNetAndColon + ) + usedNet + LibraryOneTapApp.app.getString(R.string.gigabyte) + "\n" + LibraryOneTapApp.app.getString( + R.string.remainNetAndColon) + remainNet + LibraryOneTapApp.app.getString( + R.string.gigabyte + ) + + MaterialAlertDialogBuilder(requireContext()) + .setMessage(netMessage) + .setTitle(R.string.remainNet) + .setPositiveButton(R.string.ok) { _, _ -> } + .setCancelable(true) + .create() + .show() + } Looper.loop() } } @@ -144,23 +169,33 @@ class ToolsInitFragment : PreferenceFragmentCompat() { val id: String = GlobalValues.id val passwd: String = GlobalValues.passwd - val data: String = GetPortalData.getPortalData(id, passwd, 0) - - @Suppress("SpellCheckingInspection", "LocalVariableName") - val SSMC = ElectricData.getSSMC(data) - val remainElectric = ElectricData.getResele(data) - val electricMessage = - SSMC + "\n" + getString(R.string.remainElectricAndColon) + remainElectric + getString( - R.string.degree - ) - - AlertDialog.Builder(requireContext()) - .setMessage(electricMessage) - .setTitle(R.string.remainElectric) - .setPositiveButton(R.string.ok) { _, _ -> } - .setCancelable(true) - .create() - .show() + val checked = AppUtils.checkDataAndDialog(requireContext(), + id, + passwd, + R.string.tools, + R.string.noLoginData) + + if (checked) { + Toast.makeText(requireContext(), R.string.loading, Toast.LENGTH_SHORT).show() + + val data: String = GetPortalData.getPortalData(id, passwd, 0) + + @Suppress("SpellCheckingInspection", "LocalVariableName") + val SSMC = ElectricData.getSSMC(data) + val remainElectric = ElectricData.getResele(data) + val electricMessage = + SSMC + "\n" + LibraryOneTapApp.app.getString(R.string.remainElectricAndColon) + remainElectric + LibraryOneTapApp.app.getString( + R.string.degree + ) + + MaterialAlertDialogBuilder(requireContext()) + .setMessage(electricMessage) + .setTitle(R.string.remainElectric) + .setPositiveButton(R.string.ok) { _, _ -> } + .setCancelable(true) + .create() + .show() + } Looper.loop() } } @@ -178,32 +213,43 @@ class ToolsInitFragment : PreferenceFragmentCompat() { .detectLeakedSqlLiteObjects().detectLeakedClosableObjects() .penaltyLog().penaltyDeath().build() ) - val postData = - VolunteerUtils.createVolunteerPostData(GlobalValues.name, GlobalValues.id) - val data = Requests.post(URLManager.VOLTIME_POST_URL, postData, GlobalValues.ctJson) + val checked = AppUtils.checkDataAndDialog(requireContext(), + GlobalValues.name, + GlobalValues.id, + R.string.tools, + R.string.noLoginData) - val sameID = VolunteerData.getSameID(data) - val sameName = VolunteerData.getSameName(data) + if (checked) { + Toast.makeText(requireContext(), R.string.loading, Toast.LENGTH_SHORT).show() - if (sameID != 1 || sameName != 1) { - AlertDialog.Builder(requireContext()) - .setMessage(R.string.sameData) - .setTitle(R.string.volunteer_title) - .setPositiveButton(R.string.ok) { _, _ -> } - .setCancelable(true) - .create() - .show() - } else { - val totalHours: String = - VolunteerData.getTotalHours(data).toString() + getString(R.string.hours) - val message = GlobalValues.name + "\n" + GlobalValues.id + "\n" + totalHours - AlertDialog.Builder(requireContext()) - .setMessage(message) - .setTitle(R.string.volunteer_title) - .setPositiveButton(R.string.ok) { _, _ -> } - .setCancelable(true) - .create() - .show() + val postData = + VolunteerUtils.createVolunteerPostData(GlobalValues.name, GlobalValues.id) + val data = Requests.post(URLManager.VOLTIME_POST_URL, postData, GlobalValues.ctJson) + + val sameID = VolunteerData.getSameID(data) + val sameName = VolunteerData.getSameName(data) + + if (sameID != 1 || sameName != 1) { + MaterialAlertDialogBuilder(requireContext()) + .setMessage(R.string.sameData) + .setTitle(R.string.volunteer_title) + .setPositiveButton(R.string.ok) { _, _ -> } + .setCancelable(true) + .create() + .show() + } else { + val totalHours: String = + VolunteerData.getTotalHours(data).toString() + + LibraryOneTapApp.app.getString(R.string.hours) + val message = GlobalValues.name + "\n" + GlobalValues.id + "\n" + totalHours + MaterialAlertDialogBuilder(requireContext()) + .setMessage(message) + .setTitle(R.string.volunteer_title) + .setPositiveButton(R.string.ok) { _, _ -> } + .setCancelable(true) + .create() + .show() + } } Looper.loop() } diff --git a/app/src/main/java/com/qhy040404/libraryonetap/recycleview/SimplePageActivity.java b/app/src/main/java/com/qhy040404/libraryonetap/recycleview/SimplePageActivity.java new file mode 100644 index 00000000..8508815c --- /dev/null +++ b/app/src/main/java/com/qhy040404/libraryonetap/recycleview/SimplePageActivity.java @@ -0,0 +1,206 @@ +package com.qhy040404.libraryonetap.recycleview; + +import android.annotation.SuppressLint; +import android.content.res.TypedArray; +import android.graphics.drawable.Drawable; +import android.os.Bundle; +import android.view.MenuItem; +import android.view.View; +import android.view.Window; +import android.widget.ProgressBar; + +import androidx.annotation.DrawableRes; +import androidx.annotation.LayoutRes; +import androidx.annotation.NonNull; +import androidx.annotation.Nullable; +import androidx.appcompat.app.ActionBar; +import androidx.appcompat.widget.Toolbar; +import androidx.core.content.ContextCompat; +import androidx.core.graphics.Insets; +import androidx.core.view.OnApplyWindowInsetsListener; +import androidx.core.view.ViewCompat; +import androidx.core.view.WindowCompat; +import androidx.core.view.WindowInsetsCompat; +import androidx.recyclerview.widget.RecyclerView; + +import com.drakeet.multitype.MultiTypeAdapter; +import com.google.android.material.appbar.AppBarLayout; +import com.qhy040404.libraryonetap.R; +import com.qhy040404.libraryonetap.recycleview.simplepage.Category; +import com.qhy040404.libraryonetap.recycleview.simplepage.CategoryViewBinder; +import com.qhy040404.libraryonetap.recycleview.simplepage.ClickableItem; +import com.qhy040404.libraryonetap.recycleview.simplepage.ClickableItemViewBinder; +import com.qhy040404.libraryonetap.recycleview.simplepage.ImageLoader; +import com.qhy040404.libraryonetap.recycleview.simplepage.OnClickableItemClickedListener; + +import java.util.ArrayList; +import java.util.List; + +import rikka.material.app.MaterialActivity; + +@SuppressWarnings("All") +public abstract class SimplePageActivity extends MaterialActivity { + + private Toolbar toolbar; + private ProgressBar progressBar; + + private List items; + private MultiTypeAdapter adapter; + private RecyclerView recyclerView; + private @Nullable + ImageLoader imageLoader; + private boolean initialized; + private @Nullable + OnClickableItemClickedListener onClickableItemClickedListener; + private boolean givenInsetsToDecorView = false; + + protected abstract void onItemsCreated(@NonNull List items); + + public @Nullable + ImageLoader getImageLoader() { + return imageLoader; + } + + @SuppressLint("NotifyDataSetChanged") + public void setImageLoader(@NonNull ImageLoader imageLoader) { + this.imageLoader = imageLoader; + if (initialized) { + adapter.notifyDataSetChanged(); + } + } + + @LayoutRes + protected int layoutRes() { + return R.layout.simplepage_activity; + } + + @Override + protected void onCreate(Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + setContentView(layoutRes()); + toolbar = findViewById(R.id.simple_toolbar); + progressBar = findViewById(R.id.simple_progressbar); + + progressBar.setVisibility(View.INVISIBLE); + + setSupportActionBar(toolbar); + ActionBar actionBar = getSupportActionBar(); + if (actionBar != null) { + actionBar.setDisplayHomeAsUpEnabled(true); + actionBar.setDisplayShowHomeEnabled(true); + } + onApplyPresetAttrs(); + recyclerView = findViewById(R.id.simple_list); + applyEdgeToEdge(); + } + + private void applyEdgeToEdge() { + Window window = getWindow(); + int navigationBarColor = ContextCompat.getColor(this, R.color.simple_page_navigationBarColor); + window.setNavigationBarColor(navigationBarColor); + + final AppBarLayout appBarLayout = findViewById(R.id.header_layout); + final View decorView = window.getDecorView(); + final int originalRecyclerViewPaddingBottom = recyclerView.getPaddingBottom(); + + givenInsetsToDecorView = false; + WindowCompat.setDecorFitsSystemWindows(window, false); + ViewCompat.setOnApplyWindowInsetsListener(decorView, new OnApplyWindowInsetsListener() { + @SuppressWarnings("deprecation") + @Override + public WindowInsetsCompat onApplyWindowInsets(View v, WindowInsetsCompat windowInsets) { + Insets navigationBarsInsets = windowInsets.getInsets(WindowInsetsCompat.Type.navigationBars()); + boolean isGestureNavigation = navigationBarsInsets.bottom <= 20 * getResources().getDisplayMetrics().density; + + if (!isGestureNavigation) { + ViewCompat.onApplyWindowInsets(decorView, windowInsets); + givenInsetsToDecorView = true; + } else if (givenInsetsToDecorView) { + ViewCompat.onApplyWindowInsets( + decorView, + new WindowInsetsCompat.Builder() + .setInsets( + WindowInsetsCompat.Type.navigationBars(), + Insets.of(navigationBarsInsets.left, navigationBarsInsets.top, navigationBarsInsets.right, 0) + ) + .build() + ); + } + decorView.setPadding(windowInsets.getSystemWindowInsetLeft(), decorView.getPaddingTop(), windowInsets.getSystemWindowInsetRight(), decorView.getPaddingBottom()); + appBarLayout.setPadding(appBarLayout.getPaddingLeft(), windowInsets.getSystemWindowInsetTop(), appBarLayout.getPaddingRight(), appBarLayout.getPaddingBottom()); + recyclerView.setPadding(recyclerView.getPaddingLeft(), recyclerView.getPaddingTop(), recyclerView.getPaddingRight(), originalRecyclerViewPaddingBottom + navigationBarsInsets.bottom); + return windowInsets; + } + }); + } + + @Override + protected void onPostCreate(@Nullable Bundle savedInstanceState) { + super.onPostCreate(savedInstanceState); + adapter = new MultiTypeAdapter(); + adapter.register(Category.class, new CategoryViewBinder()); + adapter.register(ClickableItem.class, new ClickableItemViewBinder(this)); + items = new ArrayList<>(); + onItemsCreated(items); + adapter.setItems(items); + adapter.setHasStableIds(true); + recyclerView.setAdapter(adapter); + initialized = true; + } + + private void onApplyPresetAttrs() { + final TypedArray a = obtainStyledAttributes(R.styleable.SimplePageActivity); + Drawable navigationIcon = a.getDrawable(R.styleable.SimplePageActivity_simplePageNavigationIcon); + if (navigationIcon != null) { + setNavigationIcon(navigationIcon); + } + a.recycle(); + } + + /** + * Set the icon to use for the toolbar's navigation button. + * + * @param resId Resource ID of a drawable to set + */ + public void setNavigationIcon(@DrawableRes int resId) { + toolbar.setNavigationIcon(resId); + } + + public void setNavigationIcon(@NonNull Drawable drawable) { + toolbar.setNavigationIcon(drawable); + } + + @Override + public boolean onOptionsItemSelected(MenuItem menuItem) { + if (menuItem.getItemId() == android.R.id.home) { + onBackPressed(); + } + return super.onOptionsItemSelected(menuItem); + } + + @Override + public void setTitle(@NonNull CharSequence title) { + toolbar.setTitle(title); + } + + public Toolbar getToolbar() { + return toolbar; + } + + public List getItems() { + return items; + } + + public MultiTypeAdapter getAdapter() { + return adapter; + } + + public @Nullable + OnClickableItemClickedListener getOnClickableItemClickedListener() { + return onClickableItemClickedListener; + } + + public void setOnClickableItemClickedListener(@Nullable OnClickableItemClickedListener listener) { + this.onClickableItemClickedListener = listener; + } +} \ No newline at end of file diff --git a/app/src/main/java/com/qhy040404/libraryonetap/recycleview/simplepage/Category.java b/app/src/main/java/com/qhy040404/libraryonetap/recycleview/simplepage/Category.java new file mode 100644 index 00000000..b0ee96ba --- /dev/null +++ b/app/src/main/java/com/qhy040404/libraryonetap/recycleview/simplepage/Category.java @@ -0,0 +1,42 @@ +package com.qhy040404.libraryonetap.recycleview.simplepage; + +import android.graphics.drawable.Drawable; +import android.view.View; + +import androidx.annotation.NonNull; +import androidx.annotation.Nullable; + +public class Category { + + public @NonNull + final String title; + public @Nullable + final Drawable actionIcon; + public @Nullable + final String actionIconContentDescription; + private @Nullable + View.OnClickListener onActionClickListener; + + public Category(@NonNull String title) { + this(title, null, null); + } + + public Category(@NonNull String title, @Nullable Drawable actionIcon) { + this(title, actionIcon, null); + } + + public Category(@NonNull String title, @Nullable Drawable actionIcon, @Nullable String actionIconContentDescription) { + this.title = title; + this.actionIcon = actionIcon; + this.actionIconContentDescription = actionIconContentDescription; + } + + @Nullable + public View.OnClickListener getOnActionClickListener() { + return onActionClickListener; + } + + public void setOnActionClickListener(@Nullable View.OnClickListener onActionClickListener) { + this.onActionClickListener = onActionClickListener; + } +} \ No newline at end of file diff --git a/app/src/main/java/com/qhy040404/libraryonetap/recycleview/simplepage/CategoryViewBinder.java b/app/src/main/java/com/qhy040404/libraryonetap/recycleview/simplepage/CategoryViewBinder.java new file mode 100644 index 00000000..9cb6e26f --- /dev/null +++ b/app/src/main/java/com/qhy040404/libraryonetap/recycleview/simplepage/CategoryViewBinder.java @@ -0,0 +1,53 @@ +package com.qhy040404.libraryonetap.recycleview.simplepage; + +import android.view.LayoutInflater; +import android.view.View; +import android.view.ViewGroup; +import android.widget.ImageButton; +import android.widget.TextView; + +import androidx.annotation.NonNull; +import androidx.recyclerview.widget.RecyclerView; + +import com.drakeet.multitype.ItemViewBinder; +import com.qhy040404.libraryonetap.R; + +@SuppressWarnings("WeakerAccess") +public class CategoryViewBinder extends ItemViewBinder { + + @Override + @NonNull + public ViewHolder onCreateViewHolder(@NonNull LayoutInflater inflater, @NonNull ViewGroup parent) { + return new ViewHolder(inflater.inflate(R.layout.simplepage_item_category, parent, false)); + } + + @Override + public void onBindViewHolder(@NonNull ViewHolder holder, @NonNull Category category) { + holder.category.setText(category.title); + holder.actionIcon.setImageDrawable(category.actionIcon); + holder.actionIcon.setContentDescription(category.actionIconContentDescription); + if (category.actionIcon != null) { + holder.actionIcon.setVisibility(View.VISIBLE); + } else { + holder.actionIcon.setVisibility(View.GONE); + } + holder.actionIcon.setOnClickListener(category.getOnActionClickListener()); + } + + @Override + public long getItemId(@NonNull Category item) { + return item.hashCode(); + } + + public static class ViewHolder extends RecyclerView.ViewHolder { + + public TextView category; + public ImageButton actionIcon; + + public ViewHolder(View itemView) { + super(itemView); + category = itemView.findViewById(R.id.category); + actionIcon = itemView.findViewById(R.id.actionIcon); + } + } +} \ No newline at end of file diff --git a/app/src/main/java/com/qhy040404/libraryonetap/recycleview/simplepage/ClickableItem.java b/app/src/main/java/com/qhy040404/libraryonetap/recycleview/simplepage/ClickableItem.java new file mode 100644 index 00000000..17577392 --- /dev/null +++ b/app/src/main/java/com/qhy040404/libraryonetap/recycleview/simplepage/ClickableItem.java @@ -0,0 +1,39 @@ +package com.qhy040404.libraryonetap.recycleview.simplepage; + +import androidx.annotation.DrawableRes; +import androidx.annotation.NonNull; +import androidx.annotation.Nullable; + +import com.qhy040404.libraryonetap.R; + +public class ClickableItem { + + public @DrawableRes + final int avatarResId; + public @NonNull + final String name; + public @NonNull + final String desc; + public @Nullable + String url; + + public ClickableItem(@NonNull String name, @NonNull String desc) { + this(R.color.white, name, desc, null); + } + + public ClickableItem(@DrawableRes int avatarResId, @NonNull String name, @NonNull String desc) { + this(avatarResId, name, desc, null); + } + + public ClickableItem( + @DrawableRes int avatarResId, + @NonNull String name, + @NonNull String desc, + @Nullable String url) { + + this.avatarResId = avatarResId; + this.name = name; + this.desc = desc; + this.url = url; + } +} \ No newline at end of file diff --git a/app/src/main/java/com/qhy040404/libraryonetap/recycleview/simplepage/ClickableItemViewBinder.java b/app/src/main/java/com/qhy040404/libraryonetap/recycleview/simplepage/ClickableItemViewBinder.java new file mode 100644 index 00000000..c3bfff6d --- /dev/null +++ b/app/src/main/java/com/qhy040404/libraryonetap/recycleview/simplepage/ClickableItemViewBinder.java @@ -0,0 +1,83 @@ +package com.qhy040404.libraryonetap.recycleview.simplepage; + +import android.content.ActivityNotFoundException; +import android.content.Intent; +import android.net.Uri; +import android.view.LayoutInflater; +import android.view.View; +import android.view.ViewGroup; +import android.widget.ImageView; +import android.widget.TextView; + +import androidx.annotation.NonNull; +import androidx.recyclerview.widget.RecyclerView; + +import com.drakeet.multitype.ItemViewBinder; +import com.qhy040404.libraryonetap.R; +import com.qhy040404.libraryonetap.recycleview.SimplePageActivity; + +@SuppressWarnings("WeakerAccess") +public class ClickableItemViewBinder extends ItemViewBinder { + + private @NonNull + final SimplePageActivity activity; + + public ClickableItemViewBinder(@NonNull SimplePageActivity activity) { + this.activity = activity; + } + + @Override + @NonNull + public ViewHolder onCreateViewHolder(@NonNull LayoutInflater inflater, @NonNull ViewGroup parent) { + return new ViewHolder(inflater.inflate(R.layout.simplepage_item_clickable, parent, false), activity); + } + + @Override + public void onBindViewHolder(@NonNull ViewHolder holder, @NonNull ClickableItem contributor) { + holder.avatar.setImageResource(contributor.avatarResId); + holder.name.setText(contributor.name); + holder.desc.setText(contributor.desc); + holder.data = contributor; + } + + @Override + public long getItemId(@NonNull ClickableItem item) { + return item.hashCode(); + } + + public static class ViewHolder extends RecyclerView.ViewHolder implements View.OnClickListener { + + protected @NonNull + final SimplePageActivity activity; + public ImageView avatar; + public TextView name; + public TextView desc; + public ClickableItem data; + + public ViewHolder(View itemView, @NonNull SimplePageActivity activity) { + super(itemView); + this.activity = activity; + avatar = itemView.findViewById(R.id.avatar); + name = itemView.findViewById(R.id.name); + desc = itemView.findViewById(R.id.desc); + itemView.setOnClickListener(this); + } + + @Override + public void onClick(View v) { + OnClickableItemClickedListener listener = activity.getOnClickableItemClickedListener(); + if (listener != null && listener.onClickableItemClicked(v, data)) { + return; + } + if (data.url != null) { + Intent intent = new Intent(Intent.ACTION_VIEW); + intent.setData(Uri.parse(data.url)); + try { + v.getContext().startActivity(intent); + } catch (ActivityNotFoundException e) { + e.printStackTrace(); + } + } + } + } +} \ No newline at end of file diff --git a/app/src/main/java/com/qhy040404/libraryonetap/recycleview/simplepage/ImageLoader.java b/app/src/main/java/com/qhy040404/libraryonetap/recycleview/simplepage/ImageLoader.java new file mode 100644 index 00000000..1290a76d --- /dev/null +++ b/app/src/main/java/com/qhy040404/libraryonetap/recycleview/simplepage/ImageLoader.java @@ -0,0 +1,10 @@ +package com.qhy040404.libraryonetap.recycleview.simplepage; + +import android.widget.ImageView; + +import androidx.annotation.NonNull; + +public interface ImageLoader { + + void load(@NonNull ImageView imageView, @NonNull String url); +} \ No newline at end of file diff --git a/app/src/main/java/com/qhy040404/libraryonetap/recycleview/simplepage/OnClickableItemClickedListener.java b/app/src/main/java/com/qhy040404/libraryonetap/recycleview/simplepage/OnClickableItemClickedListener.java new file mode 100644 index 00000000..c96a782e --- /dev/null +++ b/app/src/main/java/com/qhy040404/libraryonetap/recycleview/simplepage/OnClickableItemClickedListener.java @@ -0,0 +1,12 @@ +package com.qhy040404.libraryonetap.recycleview.simplepage; + +import android.view.View; + +import androidx.annotation.CheckResult; +import androidx.annotation.NonNull; + +public interface OnClickableItemClickedListener { + + @CheckResult + boolean onClickableItemClicked(@NonNull View itemView, @NonNull ClickableItem contributor); +} \ No newline at end of file diff --git a/app/src/main/java/com/qhy040404/libraryonetap/ui/DetailActivity.kt b/app/src/main/java/com/qhy040404/libraryonetap/ui/DetailActivity.kt deleted file mode 100644 index ad77efde..00000000 --- a/app/src/main/java/com/qhy040404/libraryonetap/ui/DetailActivity.kt +++ /dev/null @@ -1,411 +0,0 @@ -package com.qhy040404.libraryonetap.ui - -import android.annotation.SuppressLint -import android.graphics.BitmapFactory -import android.os.Looper -import android.os.StrictMode -import android.view.View -import android.widget.* -import androidx.appcompat.app.AlertDialog -import com.qhy040404.libraryonetap.R -import com.qhy040404.libraryonetap.base.BaseActivity -import com.qhy040404.libraryonetap.constant.Constants -import com.qhy040404.libraryonetap.constant.GlobalValues -import com.qhy040404.libraryonetap.constant.URLManager -import com.qhy040404.libraryonetap.datamodel.CancelData -import com.qhy040404.libraryonetap.datamodel.OrderListData -import com.qhy040404.libraryonetap.datamodel.ReserveData -import com.qhy040404.libraryonetap.datamodel.SessionData -import com.qhy040404.libraryonetap.ui.dialog.ReserveDialog -import com.qhy040404.libraryonetap.utils.ReserveUtils -import com.qhy040404.libraryonetap.utils.TimeUtils -import com.qhy040404.libraryonetap.utils.des.DesEncryptUtils -import com.qhy040404.libraryonetap.utils.web.Requests -import okhttp3.Call -import okhttp3.Callback -import okhttp3.Request -import okhttp3.Response -import java.io.IOException - -@Suppress("LocalVariableName") -class DetailActivity : BaseActivity() { - override fun init() = initView() - - override fun getLayoutId(): Int = R.layout.activity_detail - - private fun initView() { - val textView: TextView = findViewById(R.id.textView) - textView.visibility = View.VISIBLE - Thread(Detail()).start() - } - - private inner class Detail : Runnable { - @SuppressLint("SetTextI18n") - override fun run() { - Looper.prepare() - StrictMode.setThreadPolicy( - StrictMode.ThreadPolicy.Builder() - .detectDiskReads().detectDiskWrites().detectNetwork() - .penaltyLog().build() - ) - StrictMode.setVmPolicy( - StrictMode.VmPolicy.Builder() - .detectLeakedSqlLiteObjects().detectLeakedClosableObjects() - .penaltyLog().penaltyDeath().build() - ) - - val textView: TextView = findViewById(R.id.textView) - val leave: Button = findViewById(R.id.button4) - val tempLeave: Button = findViewById(R.id.button5) - val enter: Button = findViewById(R.id.button6) - val imageView: ImageView = findViewById(R.id.imageView) - val refresh: Button = findViewById(R.id.button7) - val cancel: Button = findViewById(R.id.button10) - val reserve: Button = findViewById(R.id.button11) - val reset: Button = findViewById(R.id.button9) - val tempReset: Button = findViewById(R.id.button14) - val progressBar: ProgressBar = findViewById(R.id.progressBar) - - val des = DesEncryptUtils() - - val id: String = GlobalValues.id - val passwd: String = GlobalValues.passwd - - var loginSuccess = false - var timer = 0 - while (!loginSuccess) { - val ltResponse: String = Requests.get(URLManager.LIBRARY_SSO_URL) - val ltData: String = "LT" + ltResponse.split("LT")[1].split("cas")[0] + "cas" - - val rawData = "$id$passwd$ltData" - val rsa: String = des.strEnc(rawData, "1", "2", "3") - - Requests.post( - URLManager.LIBRARY_SSO_URL, - Requests.loginPostData(id, passwd, ltData, rsa), - GlobalValues.ctSso - ) - - Requests.get(URLManager.LIBRARY_LOGIN_DIRECT_URL) - - val session: String = - Requests.post(URLManager.LIBRARY_SESSION_URL, "", GlobalValues.ctSso) - if (SessionData.isSuccess(session)) { - Toast.makeText(this@DetailActivity, R.string.loaded, Toast.LENGTH_SHORT).show() - progressBar.post { progressBar.visibility = View.INVISIBLE } - loginSuccess = true - } else { - Toast.makeText(this@DetailActivity, R.string.logFail, Toast.LENGTH_SHORT).show() - timer++ - if (timer >= 3) { - AlertDialog.Builder(this@DetailActivity) - .setMessage(R.string.failTimes) - .setTitle(R.string.error) - .setPositiveButton(R.string.ok) { _, _ -> this@DetailActivity.finish() } - .setCancelable(false) - .create() - .show() - Looper.loop() - break - } - } - } - val list = Requests.get(URLManager.LIBRARY_ORDER_LIST_URL) - val total = OrderListData.getTotal(list) - if (total != "0") { - val space_name = OrderListData.getSpace_name(list, "2") - val seat_label = OrderListData.getSeat_label(list, "2") - val order_date = OrderListData.getOrder_date(list, "2") - var order_id = OrderListData.getOrder_id(list, "2") - var order_process = OrderListData.getOrder_process(list, "2") - val back_time = - OrderListData.getBack_time(list, "2", getString(R.string.tempEndTime)) - - if (order_id == "oid") { - order_id = getString(R.string.noValidOrder) - reserve.post { - reserve.visibility = View.VISIBLE - reserve.isClickable = true - } - } - - if (order_process == "审核通过") { - order_process = getString(R.string.notStart) - - cancel.post { - cancel.visibility = View.VISIBLE - cancel.isClickable = true - } - - val today = TimeUtils.getToday("-", true) - if (order_date != today) { - reserve.post { - reserve.visibility = View.VISIBLE - reserve.isClickable = true - } - } else { - reset.post { - reset.visibility = View.VISIBLE - reset.isClickable = true - } - } - } else if (order_process == "进行中") { - order_process = getString(R.string.inside) - } else if (order_process == "暂离") { - order_process = getString(R.string.outside) - tempReset.post { - tempReset.visibility = View.VISIBLE - tempReset.isClickable = true - } - } - - enter.setOnClickListener { - val request = - Request.Builder() - .url(URLManager.getQRUrl(Constants.LIBRARY_METHOD_IN, order_id)) - .build() - val call = Requests.client.newCall(request) - call.enqueue(object : Callback { - override fun onFailure(call: Call, e: IOException) {} - - override fun onResponse(call: Call, response: Response) { - val picture_bt = response.body!!.bytes() - val pictureInput = response.body!!.byteStream() - val bitmap = - BitmapFactory.decodeByteArray(picture_bt, 0, picture_bt.size) - imageView.post { imageView.setImageBitmap(bitmap) } - pictureInput.close() - } - }) - } - leave.setOnClickListener { - val request = - Request.Builder() - .url(URLManager.getQRUrl(Constants.LIBRARY_METHOD_OUT, order_id)) - .build() - val call = Requests.client.newCall(request) - call.enqueue(object : Callback { - override fun onFailure(call: Call, e: IOException) {} - - override fun onResponse(call: Call, response: Response) { - val picture_bt = response.body!!.bytes() - val pictureInput = response.body!!.byteStream() - val bitmap = - BitmapFactory.decodeByteArray(picture_bt, 0, picture_bt.size) - imageView.post { imageView.setImageBitmap(bitmap) } - pictureInput.close() - } - }) - } - tempLeave.setOnClickListener { - val request = - Request.Builder() - .url(URLManager.getQRUrl(Constants.LIBRARY_METHOD_TEMP, order_id)) - .build() - val call = Requests.client.newCall(request) - call.enqueue(object : Callback { - override fun onFailure(call: Call, e: IOException) {} - - override fun onResponse(call: Call, response: Response) { - val picture_bt = response.body!!.bytes() - val pictureInput = response.body!!.byteStream() - val bitmap = - BitmapFactory.decodeByteArray(picture_bt, 0, picture_bt.size) - imageView.post { imageView.setImageBitmap(bitmap) } - pictureInput.close() - } - }) - } - refresh.setOnClickListener { recreate() } - cancel.setOnClickListener { - StrictMode.setThreadPolicy( - StrictMode.ThreadPolicy.Builder() - .detectDiskReads().detectDiskWrites().detectNetwork() - .penaltyLog().build() - ) - StrictMode.setVmPolicy( - StrictMode.VmPolicy.Builder() - .detectLeakedSqlLiteObjects().detectLeakedClosableObjects() - .penaltyLog().penaltyDeath().build() - ) - AlertDialog.Builder(this@DetailActivity) - .setMessage(R.string.confirmCancel) - .setTitle(R.string.library) - .setPositiveButton(R.string.justCancel) { _, _ -> - val message = CancelData.getMessage( - Requests.post( - URLManager.LIBRARY_ORDER_OPERATION_URL, - "order_id=$order_id&order_type=2&method=Cancel", - GlobalValues.ctSso - ) - ) - AlertDialog.Builder(this@DetailActivity) - .setMessage(message) - .setTitle(R.string.library) - .setPositiveButton(R.string.ok) { _, _ -> recreate() } - .setCancelable(true) - .create() - .show() - } - .setNegativeButton(R.string.cancelCancel) { _, _ -> } - .setCancelable(true) - .create() - .show() - } - reserve.setOnClickListener { ReserveDialog().showAlertDialog(this@DetailActivity) } - reset.setOnClickListener { - StrictMode.setThreadPolicy( - StrictMode.ThreadPolicy.Builder() - .detectDiskReads().detectDiskWrites().detectNetwork() - .penaltyLog().build() - ) - StrictMode.setVmPolicy( - StrictMode.VmPolicy.Builder() - .detectLeakedSqlLiteObjects().detectLeakedClosableObjects() - .penaltyLog().penaltyDeath().build() - ) - AlertDialog.Builder(this@DetailActivity) - .setMessage(R.string.confirmReset) - .setTitle(R.string.library) - .setPositiveButton(R.string.ok) { _, _ -> - val roomCode = ReserveUtils.getResetRoomCode(space_name).toString() - val targetSeat = "\"seat_label\":\"$seat_label\"" - var seat_id = "" - - val availableMap = ReserveUtils.formatAvailableMap( - Requests.get( - URLManager.constructAvailableUrl( - TimeUtils.getToday("/", false), - roomCode - ) - ) - ) - val amList = availableMap.split(",") - - for (element in amList) { - if (element == targetSeat) { - if (amList[amList.indexOf(element) + 4] == Constants.RESERVE_VALID || amList[amList.indexOf( - element - ) + 4] == Constants.RESERVE_HAS_PERSON - ) { - seat_id = - amList[amList.indexOf(element) - 1].replace( - "\"seat_id\":", - "" - ) - .replace("\"", "") - break - } - } - } - - Requests.post( - URLManager.LIBRARY_ORDER_OPERATION_URL, - "order_id=$order_id&order_type=2&method=Cancel", - GlobalValues.ctSso - ) - - val addCodeOrigin = Requests.post( - URLManager.LIBRARY_RESERVE_ADDCODE_URL, - ReserveUtils.constructParaForAddCode(seat_id), - GlobalValues.ctVCard - ) - val addCode = ReserveData.getAddCode(addCodeOrigin) - Requests.post( - URLManager.LIBRART_RESERVE_FINAL_URL, - ReserveUtils.constructParaForFinalReserve(addCode), - GlobalValues.ctVCard - ) - recreate() - } - .setNegativeButton(R.string.no) { _, _ -> } - .setCancelable(false) - .create() - .show() - } - tempReset.setOnClickListener { - StrictMode.setThreadPolicy( - StrictMode.ThreadPolicy.Builder() - .detectDiskReads().detectDiskWrites().detectNetwork() - .penaltyLog().build() - ) - StrictMode.setVmPolicy( - StrictMode.VmPolicy.Builder() - .detectLeakedSqlLiteObjects().detectLeakedClosableObjects() - .penaltyLog().penaltyDeath().build() - ) - AlertDialog.Builder(this@DetailActivity) - .setMessage(R.string.confirmReset) - .setTitle(R.string.library) - .setPositiveButton(R.string.ok) { _, _ -> - val roomCode = ReserveUtils.getResetRoomCode(space_name).toString() - val targetSeat = "\"seat_label\":\"$seat_label\"" - var seat_id = "" - - val availableMap = ReserveUtils.formatAvailableMap( - Requests.get( - URLManager.constructAvailableUrl( - TimeUtils.getToday("/", false), - roomCode - ) - ) - ) - val amList = availableMap.split(",") - - for (element in amList) { - if (element == targetSeat) { - if (amList[amList.indexOf(element) + 4] == Constants.RESERVE_VALID || amList[amList.indexOf( - element - ) + 4] == Constants.RESERVE_HAS_PERSON - ) { - seat_id = - amList[amList.indexOf(element) - 1].replace( - "\"seat_id\":", - "" - ) - .replace("\"", "") - break - } - } - } - - Requests.post( - URLManager.LIBRARY_ORDER_OPERATION_URL, - "order_id=$order_id&order_type=2&method=Release", - GlobalValues.ctSso - ) - - val addCodeOrigin = Requests.post( - URLManager.LIBRARY_RESERVE_ADDCODE_URL, - ReserveUtils.constructParaForAddCode(seat_id), - GlobalValues.ctVCard - ) - val addCode = ReserveData.getAddCode(addCodeOrigin) - Requests.post( - URLManager.LIBRART_RESERVE_FINAL_URL, - ReserveUtils.constructParaForFinalReserve(addCode), - GlobalValues.ctVCard - ) - recreate() - } - .setNegativeButton(R.string.no) { _, _ -> } - .setCancelable(false) - .create() - .show() - } - textView.text = - "order_id: $order_id\n\n$order_process\n\n$space_name\n$seat_label\n$order_date\n$back_time" - Looper.loop() - } else { - AlertDialog.Builder(this@DetailActivity) - .setMessage(R.string.loginTimeout) - .setTitle(R.string.error) - .setPositiveButton(R.string.ok) { _, _ -> this@DetailActivity.finish() } - .setCancelable(false) - .create() - .show() - Looper.loop() - } - } - } -} diff --git a/app/src/main/java/com/qhy040404/libraryonetap/ui/MainActivity.kt b/app/src/main/java/com/qhy040404/libraryonetap/ui/MainActivity.kt deleted file mode 100644 index 26b03c10..00000000 --- a/app/src/main/java/com/qhy040404/libraryonetap/ui/MainActivity.kt +++ /dev/null @@ -1,145 +0,0 @@ -package com.qhy040404.libraryonetap.ui - -import android.animation.ObjectAnimator -import android.content.Intent -import android.os.Looper -import android.view.View -import android.widget.Button -import android.widget.ImageView -import android.widget.TextView -import android.widget.Toast -import androidx.appcompat.app.AlertDialog -import com.qhy040404.libraryonetap.LibraryOneTapApp -import com.qhy040404.libraryonetap.R -import com.qhy040404.libraryonetap.base.BaseActivity -import com.qhy040404.libraryonetap.constant.Constants -import com.qhy040404.libraryonetap.constant.GlobalValues -import com.qhy040404.libraryonetap.ui.secret.SecretActivity -import com.qhy040404.libraryonetap.ui.tools.ToolsInitActivity -import com.qhy040404.libraryonetap.ui.tools.VCardActivity -import kotlin.system.exitProcess - -class MainActivity : BaseActivity() { - override fun init() { - handleIntentFromShortcuts(intent) - supportActionBar?.setDisplayHomeAsUpEnabled(false) - initView() - } - - override fun getLayoutId(): Int = R.layout.activity_main - - override fun onNewIntent(intent: Intent) { - super.onNewIntent(intent) - handleIntentFromShortcuts(intent) - } - - private fun initView() { - if (!GlobalValues.initialized) { - AlertDialog.Builder(this) - .setTitle(R.string.welcome) - .setMessage(R.string.welcome_message) - .setPositiveButton(R.string.ok) { _, _ -> - startActivity(Intent(this, SettingsActivity::class.java)) - } - .setNegativeButton(R.string.no) { _, _ -> } - .setCancelable(false) - .create() - .show() - GlobalValues.initialized = true - } - Thread(ShowVersion()).start() - } - - private fun handleIntentFromShortcuts(intent: Intent) { - when (intent.action) { - Constants.SHORTCUT_DETAIL -> startActivity(Intent(this, DetailActivity::class.java)) - Constants.SHORTCUT_TOOLS -> startActivity(Intent(this, ToolsInitActivity::class.java)) - Constants.SHORTCUT_VCARD -> startActivity(Intent(this, VCardActivity::class.java)) - } - } - - private inner class ShowVersion : Runnable { - override fun run() { - Looper.prepare() - - var counter = 0 - var dogCounter = 0 - var b1 = true - var b2 = true - var b3 = true - var b4 = true - var b5 = true - - val versionView: TextView = findViewById(R.id.textView5) - val detail: Button = findViewById(R.id.button) - val yxj: Button = findViewById(R.id.button8) - val tools: Button = findViewById(R.id.button13) - val settings: Button = findViewById(R.id.button2) - val dog: ImageView = findViewById(R.id.imageView4) - val exit: Button = findViewById(R.id.button3) - - versionView.post { versionView.text = GlobalValues.version } - - versionView.setOnClickListener { - counter += 1 - if (counter in 1..10 && b1) { - b1 = false - Toast.makeText(this@MainActivity, "没做检查更新,别点啦~", Toast.LENGTH_SHORT).show() - } else if (counter in 11..20 && b2) { - b2 = false - dog.visibility = View.VISIBLE - ObjectAnimator.ofFloat(dog, "alpha", 0F, 0.1F).setDuration(500).start() - Toast.makeText(this@MainActivity, "真的没做,骗你干嘛,别点啦~", Toast.LENGTH_SHORT).show() - } else if (counter in 20..30 && b3) { - b3 = false - ObjectAnimator.ofFloat(dog, "alpha", 0.1F, 0.3F).setDuration(1000).start() - Toast.makeText(this@MainActivity, "没有东西了啊,别点了啊喂", Toast.LENGTH_SHORT).show() - } else if (counter in 31..40 && b4) { - b4 = false - ObjectAnimator.ofFloat(dog, "alpha", 0.3F, 0.5F).setDuration(1000).start() - Toast.makeText(this@MainActivity, "你赢了,但是真的啥也没有哈哈哈哈哈哈", Toast.LENGTH_SHORT) - .show() - } else if (counter > 40 && b5) { - b5 = false - ObjectAnimator.ofFloat(dog, "alpha", 0.5F, 1F).setDuration(2500).start() - } - } - - dog.setOnClickListener { - if (counter >= 40) { - dogCounter += 1 - if (dogCounter >= 5) { - startActivity(Intent(this@MainActivity, SecretActivity::class.java)) - } - } - } - - detail.setOnClickListener { - startActivity(Intent(this@MainActivity, DetailActivity::class.java)) - } - - yxj.setOnClickListener { - startActivity(Intent(this@MainActivity, YanxiujianActivity::class.java)) - } - - tools.setOnClickListener { - startActivity(Intent(this@MainActivity, ToolsInitActivity::class.java)) - } - - settings.setOnClickListener { - startActivity(Intent(this@MainActivity, SettingsActivity::class.java)) - this@MainActivity.finish() - } - - exit.setOnClickListener { - LibraryOneTapApp.instance?.exit() - } - - exit.setOnLongClickListener { - LibraryOneTapApp.instance?.exit() - exitProcess(0) - } - Looper.loop() - } - } -} \ No newline at end of file diff --git a/app/src/main/java/com/qhy040404/libraryonetap/ui/SettingsActivity.kt b/app/src/main/java/com/qhy040404/libraryonetap/ui/SettingsActivity.kt deleted file mode 100644 index 48f46e5e..00000000 --- a/app/src/main/java/com/qhy040404/libraryonetap/ui/SettingsActivity.kt +++ /dev/null @@ -1,34 +0,0 @@ -package com.qhy040404.libraryonetap.ui - -import android.content.Intent -import android.view.KeyEvent -import android.view.MenuItem -import com.qhy040404.libraryonetap.R -import com.qhy040404.libraryonetap.base.BaseActivity -import com.qhy040404.libraryonetap.fragment.SettingsFragment - -class SettingsActivity : BaseActivity() { - override fun init() { - supportFragmentManager - .beginTransaction() - .replace(R.id.settings, SettingsFragment()) - .commit() - supportActionBar?.setDisplayHomeAsUpEnabled(true) - } - - override fun getLayoutId(): Int = R.layout.settings_activity - - override fun onKeyDown(keyCode: Int, event: KeyEvent?): Boolean { - if (keyCode == KeyEvent.KEYCODE_BACK) { - startActivity(Intent(this, MainActivity::class.java)) - finish() - } - return super.onKeyDown(keyCode, event) - } - - override fun onOptionsItemSelected(item: MenuItem): Boolean { - startActivity(Intent(this, MainActivity::class.java)) - finish() - return super.onOptionsItemSelected(item) - } -} \ No newline at end of file diff --git a/app/src/main/java/com/qhy040404/libraryonetap/ui/AboutActivity.kt b/app/src/main/java/com/qhy040404/libraryonetap/ui/about/AboutActivity.kt similarity index 82% rename from app/src/main/java/com/qhy040404/libraryonetap/ui/AboutActivity.kt rename to app/src/main/java/com/qhy040404/libraryonetap/ui/about/AboutActivity.kt index cf4beb43..d99bc07b 100644 --- a/app/src/main/java/com/qhy040404/libraryonetap/ui/AboutActivity.kt +++ b/app/src/main/java/com/qhy040404/libraryonetap/ui/about/AboutActivity.kt @@ -1,4 +1,4 @@ -package com.qhy040404.libraryonetap.ui +package com.qhy040404.libraryonetap.ui.about import android.content.Intent import android.graphics.drawable.ColorDrawable @@ -8,7 +8,6 @@ import android.widget.TextView import android.widget.Toast import androidx.appcompat.widget.Toolbar import coil.load -import com.drakeet.about.AbsAboutActivity import com.drakeet.about.Category import com.drakeet.about.Contributor import com.drakeet.about.License @@ -16,10 +15,11 @@ import com.qhy040404.libraryonetap.LibraryOneTapApp import com.qhy040404.libraryonetap.R import com.qhy040404.libraryonetap.constant.URLManager import com.qhy040404.libraryonetap.ui.secret.SecretActivity +import com.qhy040404.libraryonetap.utils.AppUtils import com.qhy040404.libraryonetap.utils.PackageUtils @Suppress("SpellCheckingInspection") -class AboutActivity : AbsAboutActivity() { +class AboutActivity : AbsAboutActivityProxy() { private var headCount = 0 override fun onCreate(savedInstanceState: Bundle?) { @@ -28,7 +28,7 @@ class AboutActivity : AbsAboutActivity() { } override fun onCreateHeader(icon: ImageView, slogan: TextView, version: TextView) { - icon.load(R.mipmap.launcher_lol) + icon.load(R.drawable.ic_about_foreground) slogan.text = getString(R.string.about_slogan) version.text = String.format( "%s v%s (%d)", @@ -132,14 +132,6 @@ class AboutActivity : AbsAboutActivity() { "https://github.com/RikkaApps/RikkaX" ) ) - add( - License( - "Gson", - "Google", - License.APACHE_2, - "https://github.com/google/gson" - ) - ) add( License( "OkHttp", @@ -156,6 +148,30 @@ class AboutActivity : AbsAboutActivity() { "https://github.com/coil-kt/coil" ) ) + add( + License( + "Moshi", + "Square", + License.APACHE_2, + "https://github.com/square/moshi" + ) + ) + add( + License( + "libraries", + "zhaobozhen", + License.MIT, + "https://github.com/zhaobozhen/libraries" + ) + ) + add( + License( + "AppIconLoader", + "zhanghai", + License.APACHE_2, + "https://github.com/zhanghai/AppIconLoader" + ) + ) } } @@ -164,8 +180,13 @@ class AboutActivity : AbsAboutActivity() { findViewById(com.drakeet.about.R.id.toolbar)?.background = null - setHeaderBackground(ColorDrawable(getColor(R.color.black))) - setHeaderContentScrim(ColorDrawable(getColor(R.color.black))) + val color = getColor(if (AppUtils.currentIsNightMode(this)) { + R.color.black + } else { + R.color.library_500 + }) + setHeaderBackground(ColorDrawable(color)) + setHeaderContentScrim(ColorDrawable(color)) } companion object { diff --git a/app/src/main/java/com/qhy040404/libraryonetap/ui/about/AbsAboutActivityProxy.java b/app/src/main/java/com/qhy040404/libraryonetap/ui/about/AbsAboutActivityProxy.java new file mode 100644 index 00000000..a9c76db6 --- /dev/null +++ b/app/src/main/java/com/qhy040404/libraryonetap/ui/about/AbsAboutActivityProxy.java @@ -0,0 +1,311 @@ +package com.qhy040404.libraryonetap.ui.about; + +import android.content.res.TypedArray; +import android.graphics.drawable.Drawable; +import android.os.Build; +import android.os.Bundle; +import android.view.MenuItem; +import android.view.View; +import android.view.Window; +import android.widget.ImageView; +import android.widget.LinearLayout; +import android.widget.TextView; + +import androidx.annotation.ColorInt; +import androidx.annotation.DrawableRes; +import androidx.annotation.LayoutRes; +import androidx.annotation.NonNull; +import androidx.annotation.Nullable; +import androidx.annotation.RequiresApi; +import androidx.appcompat.app.ActionBar; +import androidx.appcompat.widget.Toolbar; +import androidx.core.content.ContextCompat; +import androidx.core.graphics.Insets; +import androidx.core.view.OnApplyWindowInsetsListener; +import androidx.core.view.ViewCompat; +import androidx.core.view.WindowCompat; +import androidx.core.view.WindowInsetsCompat; +import androidx.recyclerview.widget.RecyclerView; + +import com.drakeet.about.Card; +import com.drakeet.about.CardViewBinder; +import com.drakeet.about.Category; +import com.drakeet.about.CategoryViewBinder; +import com.drakeet.about.Contributor; +import com.drakeet.about.ImageLoader; +import com.drakeet.about.License; +import com.drakeet.about.LicenseViewBinder; +import com.drakeet.about.Line; +import com.drakeet.about.LineViewBinder; +import com.drakeet.about.OnContributorClickedListener; +import com.drakeet.about.OnRecommendationClickedListener; +import com.drakeet.about.R; +import com.drakeet.multitype.MultiTypeAdapter; +import com.google.android.material.appbar.AppBarLayout; +import com.google.android.material.appbar.CollapsingToolbarLayout; + +import java.util.ArrayList; +import java.util.List; + +import rikka.material.app.MaterialActivity; + +/** + * @author drakeet + */ +@SuppressWarnings("ALL") +public abstract class AbsAboutActivityProxy extends MaterialActivity { + + private Toolbar toolbar; + private CollapsingToolbarLayout collapsingToolbar; + private LinearLayout headerContentLayout; + + private List items; + private MultiTypeAdapter adapter; + private TextView slogan, version; + private RecyclerView recyclerView; + private @Nullable + ImageLoader imageLoader; + private boolean initialized; + private @Nullable + OnRecommendationClickedListener onRecommendationClickedListener; + private @Nullable + OnContributorClickedListener onContributorClickedListener; + private boolean givenInsetsToDecorView = false; + + protected abstract void onCreateHeader(@NonNull ImageView icon, @NonNull TextView slogan, @NonNull TextView version); + + protected abstract void onItemsCreated(@NonNull List items); + + protected void onTitleViewCreated(@NonNull CollapsingToolbarLayout collapsingToolbar) { + } + + public @Nullable + ImageLoader getImageLoader() { + return imageLoader; + } + + public void setImageLoader(@NonNull ImageLoader imageLoader) { + this.imageLoader = imageLoader; + if (initialized) { + adapter.notifyDataSetChanged(); + } + } + + @LayoutRes + protected int layoutRes() { + return R.layout.about_page_main_activity; + } + + @Override + protected void onCreate(Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + setContentView(layoutRes()); + toolbar = findViewById(R.id.toolbar); + ImageView icon = findViewById(R.id.icon); + slogan = findViewById(R.id.slogan); + version = findViewById(R.id.version); + collapsingToolbar = findViewById(R.id.collapsing_toolbar); + headerContentLayout = findViewById(R.id.header_content_layout); + onTitleViewCreated(collapsingToolbar); + onCreateHeader(icon, slogan, version); + + setSupportActionBar(toolbar); + ActionBar actionBar = getSupportActionBar(); + if (actionBar != null) { + actionBar.setDisplayHomeAsUpEnabled(true); + actionBar.setDisplayShowHomeEnabled(true); + } + onApplyPresetAttrs(); + recyclerView = findViewById(R.id.list); + if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) { + applyEdgeToEdge(); + } + } + + @RequiresApi(api = Build.VERSION_CODES.LOLLIPOP) + private void applyEdgeToEdge() { + Window window = getWindow(); + int navigationBarColor = ContextCompat.getColor(this, R.color.about_page_navigationBarColor); + window.setNavigationBarColor(navigationBarColor); + + final AppBarLayout appBarLayout = findViewById(R.id.header_layout); + final View decorView = window.getDecorView(); + final int originalRecyclerViewPaddingBottom = recyclerView.getPaddingBottom(); + + givenInsetsToDecorView = false; + WindowCompat.setDecorFitsSystemWindows(window, false); + ViewCompat.setOnApplyWindowInsetsListener(decorView, new OnApplyWindowInsetsListener() { + @Override + public WindowInsetsCompat onApplyWindowInsets(View v, WindowInsetsCompat windowInsets) { + Insets navigationBarsInsets = windowInsets.getInsets(WindowInsetsCompat.Type.navigationBars()); + boolean isGestureNavigation = navigationBarsInsets.bottom <= 20 * getResources().getDisplayMetrics().density; + + if (!isGestureNavigation) { + ViewCompat.onApplyWindowInsets(decorView, windowInsets); + givenInsetsToDecorView = true; + } else if (givenInsetsToDecorView) { + ViewCompat.onApplyWindowInsets( + decorView, + new WindowInsetsCompat.Builder() + .setInsets( + WindowInsetsCompat.Type.navigationBars(), + Insets.of(navigationBarsInsets.left, navigationBarsInsets.top, navigationBarsInsets.right, 0) + ) + .build() + ); + } + decorView.setPadding(windowInsets.getSystemWindowInsetLeft(), decorView.getPaddingTop(), windowInsets.getSystemWindowInsetRight(), decorView.getPaddingBottom()); + appBarLayout.setPadding(appBarLayout.getPaddingLeft(), windowInsets.getSystemWindowInsetTop(), appBarLayout.getPaddingRight(), appBarLayout.getPaddingBottom()); + recyclerView.setPadding(recyclerView.getPaddingLeft(), recyclerView.getPaddingTop(), recyclerView.getPaddingRight(), originalRecyclerViewPaddingBottom + navigationBarsInsets.bottom); + return windowInsets; + } + }); + } + + @Override + @SuppressWarnings("deprecation") + protected void onPostCreate(@Nullable Bundle savedInstanceState) { + super.onPostCreate(savedInstanceState); + adapter = new MultiTypeAdapter(); + adapter.register(Category.class, new CategoryViewBinder()); + adapter.register(Card.class, new CardViewBinder()); + adapter.register(Line.class, new LineViewBinder()); + adapter.register(Contributor.class, new ContributorViewBinder(this)); + adapter.register(License.class, new LicenseViewBinder()); + items = new ArrayList<>(); + onItemsCreated(items); + adapter.setItems(items); + adapter.setHasStableIds(true); + recyclerView.addItemDecoration(new DividerItemDecoration(adapter)); + recyclerView.setAdapter(adapter); + initialized = true; + } + + private void onApplyPresetAttrs() { + final TypedArray a = obtainStyledAttributes(R.styleable.AbsAboutActivity); + Drawable headerBackground = a.getDrawable(R.styleable.AbsAboutActivity_aboutPageHeaderBackground); + if (headerBackground != null) { + setHeaderBackground(headerBackground); + } + Drawable headerContentScrim = a.getDrawable(R.styleable.AbsAboutActivity_aboutPageHeaderContentScrim); + if (headerContentScrim != null) { + setHeaderContentScrim(headerContentScrim); + } + @ColorInt + int headerTextColor = a.getColor(R.styleable.AbsAboutActivity_aboutPageHeaderTextColor, -1); + if (headerTextColor != -1) { + setHeaderTextColor(headerTextColor); + } + Drawable navigationIcon = a.getDrawable(R.styleable.AbsAboutActivity_aboutPageNavigationIcon); + if (navigationIcon != null) { + setNavigationIcon(navigationIcon); + } + a.recycle(); + } + + /** + * Use {@link #setHeaderBackground(int)} instead. + * + * @param resId The resource id of header background + */ + @Deprecated + public void setHeaderBackgroundResource(@DrawableRes int resId) { + setHeaderBackground(resId); + } + + public void setHeaderBackground(@DrawableRes int resId) { + setHeaderBackground(ContextCompat.getDrawable(this, resId)); + } + + public void setHeaderBackground(@NonNull Drawable drawable) { + ViewCompat.setBackground(headerContentLayout, drawable); + } + + /** + * Set the drawable to use for the content scrim from resources. Providing null will disable + * the scrim functionality. + * + * @param drawable the drawable to display + */ + public void setHeaderContentScrim(@NonNull Drawable drawable) { + collapsingToolbar.setContentScrim(drawable); + } + + public void setHeaderContentScrim(@DrawableRes int resId) { + setHeaderContentScrim(ContextCompat.getDrawable(this, resId)); + } + + public void setHeaderTextColor(@ColorInt int color) { + collapsingToolbar.setCollapsedTitleTextColor(color); + slogan.setTextColor(color); + version.setTextColor(color); + } + + /** + * Set the icon to use for the toolbar's navigation button. + * + * @param resId Resource ID of a drawable to set + */ + public void setNavigationIcon(@DrawableRes int resId) { + toolbar.setNavigationIcon(resId); + } + + public void setNavigationIcon(@NonNull Drawable drawable) { + toolbar.setNavigationIcon(drawable); + } + + @Override + public boolean onOptionsItemSelected(MenuItem menuItem) { + if (menuItem.getItemId() == android.R.id.home) { + onBackPressed(); + } + return super.onOptionsItemSelected(menuItem); + } + + @Override + public void setTitle(@NonNull CharSequence title) { + collapsingToolbar.setTitle(title); + } + + public Toolbar getToolbar() { + return toolbar; + } + + public CollapsingToolbarLayout getCollapsingToolbar() { + return collapsingToolbar; + } + + public List getItems() { + return items; + } + + public MultiTypeAdapter getAdapter() { + return adapter; + } + + public TextView getSloganTextView() { + return slogan; + } + + public TextView getVersionTextView() { + return version; + } + + public @Nullable + OnRecommendationClickedListener getOnRecommendationClickedListener() { + return onRecommendationClickedListener; + } + + public void setOnRecommendationClickedListener(@Nullable OnRecommendationClickedListener listener) { + this.onRecommendationClickedListener = listener; + } + + public @Nullable + OnContributorClickedListener getOnContributorClickedListener() { + return onContributorClickedListener; + } + + public void setOnContributorClickedListener(@Nullable OnContributorClickedListener listener) { + this.onContributorClickedListener = listener; + } +} diff --git a/app/src/main/java/com/qhy040404/libraryonetap/ui/about/ContributorViewBinder.java b/app/src/main/java/com/qhy040404/libraryonetap/ui/about/ContributorViewBinder.java new file mode 100644 index 00000000..15e2de4d --- /dev/null +++ b/app/src/main/java/com/qhy040404/libraryonetap/ui/about/ContributorViewBinder.java @@ -0,0 +1,88 @@ +package com.qhy040404.libraryonetap.ui.about; + +import static android.net.Uri.parse; + +import android.content.ActivityNotFoundException; +import android.content.Intent; +import android.view.LayoutInflater; +import android.view.View; +import android.view.ViewGroup; +import android.widget.ImageView; +import android.widget.TextView; + +import androidx.annotation.NonNull; +import androidx.recyclerview.widget.RecyclerView; + +import com.drakeet.about.Contributor; +import com.drakeet.about.OnContributorClickedListener; +import com.drakeet.about.R; +import com.drakeet.multitype.ItemViewBinder; + +/** + * @author drakeet + */ +@SuppressWarnings("WeakerAccess") +public class ContributorViewBinder extends ItemViewBinder { + + private @NonNull + final AbsAboutActivityProxy activity; + + public ContributorViewBinder(@NonNull AbsAboutActivityProxy activity) { + this.activity = activity; + } + + @Override + @NonNull + public ViewHolder onCreateViewHolder(@NonNull LayoutInflater inflater, @NonNull ViewGroup parent) { + return new ViewHolder(inflater.inflate(R.layout.about_page_item_contributor, parent, false), activity); + } + + @Override + public void onBindViewHolder(@NonNull ViewHolder holder, @NonNull Contributor contributor) { + holder.avatar.setImageResource(contributor.avatarResId); + holder.name.setText(contributor.name); + holder.desc.setText(contributor.desc); + holder.data = contributor; + } + + @Override + public long getItemId(@NonNull Contributor item) { + return item.hashCode(); + } + + public static class ViewHolder extends RecyclerView.ViewHolder implements View.OnClickListener { + + public final ImageView avatar; + public final TextView name; + public final TextView desc; + protected @NonNull + final AbsAboutActivityProxy activity; + public Contributor data; + + public ViewHolder(View itemView, @NonNull AbsAboutActivityProxy activity) { + super(itemView); + this.activity = activity; + avatar = itemView.findViewById(R.id.avatar); + name = itemView.findViewById(R.id.name); + desc = itemView.findViewById(R.id.desc); + itemView.setOnClickListener(this); + } + + @Override + public void onClick(View v) { + OnContributorClickedListener listener = activity.getOnContributorClickedListener(); + if (listener != null && listener.onContributorClicked(v, data)) { + return; + } + if (data.url != null) { + Intent intent = new Intent(Intent.ACTION_VIEW); + intent.setData(parse(data.url)); + try { + v.getContext().startActivity(intent); + } catch (ActivityNotFoundException e) { + e.printStackTrace(); + } + } + } + } +} diff --git a/app/src/main/java/com/qhy040404/libraryonetap/ui/about/DividerItemDecoration.java b/app/src/main/java/com/qhy040404/libraryonetap/ui/about/DividerItemDecoration.java new file mode 100644 index 00000000..3fd82fbd --- /dev/null +++ b/app/src/main/java/com/qhy040404/libraryonetap/ui/about/DividerItemDecoration.java @@ -0,0 +1,55 @@ +package com.qhy040404.libraryonetap.ui.about; + +import android.graphics.Rect; +import android.view.View; + +import androidx.annotation.NonNull; +import androidx.recyclerview.widget.LinearLayoutManager; +import androidx.recyclerview.widget.RecyclerView; + +import com.drakeet.about.License; +import com.drakeet.about.Recommendation; +import com.drakeet.multitype.MultiTypeAdapter; + +import java.util.List; + +/** + * @author drakeet + */ +class DividerItemDecoration extends RecyclerView.ItemDecoration { + + private final @NonNull + MultiTypeAdapter adapter; + private final Class[] dividerClasses = {License.class, Recommendation.class}; + + /** + * Creates a divider {@link RecyclerView.ItemDecoration} that can be used with a + * {@link LinearLayoutManager}. + * + * @param adapter The MultiTypeAdapter + */ + DividerItemDecoration(@NonNull MultiTypeAdapter adapter) { + this.adapter = adapter; + } + + @Override + public void getItemOffsets(@NonNull Rect outRect, @NonNull View view, @NonNull RecyclerView parent, @NonNull RecyclerView.State state) { + if (adapter.getItemCount() == 0) { + outRect.set(0, 0, 0, 0); + return; + } + List items = adapter.getItems(); + int position = parent.getChildAdapterPosition(view); + boolean should = false; + for (int i = 0; !should && i < dividerClasses.length; i++) { + should = position + 1 < items.size() + && items.get(position).getClass().isAssignableFrom(dividerClasses[i]) + && (items.get(position + 1).getClass().isAssignableFrom(dividerClasses[i])); + } + if (should) { + outRect.set(0, 0, 0, 1); + } else { + outRect.set(0, 0, 0, 0); + } + } +} diff --git a/app/src/main/java/com/qhy040404/libraryonetap/ui/dialog/ReserveDialog.kt b/app/src/main/java/com/qhy040404/libraryonetap/ui/dialog/ReserveDialog.kt index f7292f48..14b97bfe 100644 --- a/app/src/main/java/com/qhy040404/libraryonetap/ui/dialog/ReserveDialog.kt +++ b/app/src/main/java/com/qhy040404/libraryonetap/ui/dialog/ReserveDialog.kt @@ -9,12 +9,12 @@ import android.widget.AdapterView import android.widget.ArrayAdapter import android.widget.Spinner import android.widget.Toast -import androidx.appcompat.app.AlertDialog +import com.google.android.material.dialog.MaterialAlertDialogBuilder import com.qhy040404.libraryonetap.R import com.qhy040404.libraryonetap.constant.GlobalValues import com.qhy040404.libraryonetap.constant.URLManager -import com.qhy040404.libraryonetap.datamodel.ReserveData -import com.qhy040404.libraryonetap.datamodel.SessionData +import com.qhy040404.libraryonetap.data.ReserveData +import com.qhy040404.libraryonetap.data.SessionData import com.qhy040404.libraryonetap.utils.ReserveUtils import com.qhy040404.libraryonetap.utils.RoomUtils import com.qhy040404.libraryonetap.utils.des.DesEncryptUtils @@ -66,12 +66,12 @@ class ReserveDialog { override fun onNothingSelected(p0: AdapterView<*>?) {} } - AlertDialog.Builder(ctx) + MaterialAlertDialogBuilder(ctx) .setTitle(R.string.library) .setView(view) .setPositiveButton(R.string.ok) { _, _ -> reserveSeat(ctx, targetRoom) - AlertDialog.Builder(ctx) + MaterialAlertDialogBuilder(ctx) .setTitle(R.string.library) .setMessage(R.string.reserved) .setPositiveButton(R.string.ok) { _, _ -> ctx.recreate() } @@ -102,18 +102,22 @@ class ReserveDialog { var loginSuccess = false while (!loginSuccess) { val ltResponse: String = Requests.get(URLManager.LIBRARY_SSO_URL) - val ltData: String = "LT" + ltResponse.split("LT")[1].split("cas")[0] + "cas" + val ltData: String = try { + "LT" + ltResponse.split("LT")[1].split("cas")[0] + "cas" + } catch (e: Exception) { + "" + } - val rawData = "${GlobalValues.id}${GlobalValues.passwd}$ltData" - val rsa: String = des.strEnc(rawData, "1", "2", "3") + if (ltData != "") { + val rawData = "${GlobalValues.id}${GlobalValues.passwd}$ltData" + val rsa: String = des.strEnc(rawData, "1", "2", "3") - Requests.post( - URLManager.LIBRARY_SSO_URL, - Requests.loginPostData(GlobalValues.id, GlobalValues.passwd, ltData, rsa), - GlobalValues.ctSso - ) - - Requests.get(URLManager.LIBRARY_LOGIN_DIRECT_URL) + Requests.post( + URLManager.LIBRARY_SSO_URL, + Requests.loginPostData(GlobalValues.id, GlobalValues.passwd, ltData, rsa), + GlobalValues.ctSso + ) + } val session: String = Requests.post( URLManager.LIBRARY_SESSION_URL, "", diff --git a/app/src/main/java/com/qhy040404/libraryonetap/ui/main/INavViewContainer.kt b/app/src/main/java/com/qhy040404/libraryonetap/ui/main/INavViewContainer.kt new file mode 100644 index 00000000..8f982b29 --- /dev/null +++ b/app/src/main/java/com/qhy040404/libraryonetap/ui/main/INavViewContainer.kt @@ -0,0 +1,8 @@ +package com.qhy040404.libraryonetap.ui.main + +interface INavViewContainer { + fun showNavigationView() + fun hideNavigationView() + fun showProgressBar() + fun hideProgressBar() +} \ No newline at end of file diff --git a/app/src/main/java/com/qhy040404/libraryonetap/ui/main/MainBottomActivity.kt b/app/src/main/java/com/qhy040404/libraryonetap/ui/main/MainBottomActivity.kt new file mode 100644 index 00000000..c8a7a2a3 --- /dev/null +++ b/app/src/main/java/com/qhy040404/libraryonetap/ui/main/MainBottomActivity.kt @@ -0,0 +1,199 @@ +package com.qhy040404.libraryonetap.ui.main + +import android.content.Intent +import android.content.pm.PackageManager +import android.net.Uri +import android.provider.Settings +import android.view.View +import androidx.coordinatorlayout.widget.CoordinatorLayout +import androidx.fragment.app.Fragment +import androidx.lifecycle.lifecycleScope +import androidx.viewpager2.adapter.FragmentStateAdapter +import androidx.viewpager2.widget.ViewPager2 +import com.google.android.material.behavior.HideBottomViewOnScrollBehavior +import com.google.android.material.bottomnavigation.BottomNavigationView +import com.google.android.material.dialog.MaterialAlertDialogBuilder +import com.qhy040404.libraryonetap.R +import com.qhy040404.libraryonetap.base.BaseActivity +import com.qhy040404.libraryonetap.constant.Constants +import com.qhy040404.libraryonetap.constant.GlobalValues +import com.qhy040404.libraryonetap.databinding.ActivityMainBottomBinding +import com.qhy040404.libraryonetap.fragment.IAppBarContainer +import com.qhy040404.libraryonetap.fragment.SettingsFragment +import com.qhy040404.libraryonetap.fragment.library.DetailFragment +import com.qhy040404.libraryonetap.fragment.library.YanxiujianFragment +import com.qhy040404.libraryonetap.fragment.tools.ToolsInitFragment +import com.qhy040404.libraryonetap.ui.tools.VCardActivity +import com.qhy040404.libraryonetap.utils.AppUtils +import com.qhy040404.libraryonetap.utils.extensions.ViewExtensions.setCurrentItem +import kotlinx.coroutines.delay +import kotlinx.coroutines.launch + +class MainBottomActivity : BaseActivity(), INavViewContainer, + IAppBarContainer { + private val navViewBehavior by lazy { HideBottomViewOnScrollBehavior() } + + override fun init() { + setSupportActionBar(binding.toolbar) + supportActionBar?.title = AppUtils.setTitle(this) + if (!GlobalValues.md3) { + binding.toolbar.setTitleTextColor(getColor(R.color.white)) + } + + binding.apply { + root.bringChildToFront(binding.appbar) + viewpager.apply { + adapter = object : FragmentStateAdapter(this@MainBottomActivity) { + override fun getItemCount(): Int { + return 4 + } + + override fun createFragment(position: Int): Fragment { + return when (position) { + 0 -> DetailFragment() + 1 -> YanxiujianFragment() + 2 -> ToolsInitFragment() + else -> SettingsFragment() + } + } + } + + registerOnPageChangeCallback(object : ViewPager2.OnPageChangeCallback() { + override fun onPageSelected(position: Int) { + super.onPageSelected(position) + binding.navView.menu.getItem(position).isChecked = true + } + }) + + isUserInputEnabled = false + offscreenPageLimit = 2 + } + + navView.apply { + (layoutParams as CoordinatorLayout.LayoutParams).also { + it.behavior = navViewBehavior + } + requestLayout() + setOnItemSelectedListener { + fun performClickNavigationItem(index: Int) { + if (binding.viewpager.currentItem != index) { + if (!binding.viewpager.isFakeDragging) { + binding.viewpager.setCurrentItem(index, 300L) + } + } else { + val clickFlag = + binding.viewpager.getTag(R.id.viewpager_tab_click) as? Boolean + ?: false + if (!clickFlag) { + binding.viewpager.setTag(R.id.viewpager_tab_click, true) + + lifecycleScope.launch { + delay(200) + binding.viewpager.setTag(R.id.viewpager_tab_click, false) + } + } + } + } + + when (it.itemId) { + R.id.navigation_qr -> performClickNavigationItem(0) + R.id.navigation_yxj -> performClickNavigationItem(1) + R.id.navigation_tools -> performClickNavigationItem(2) + R.id.navigation_settings -> performClickNavigationItem(3) + } + true + } + } + } + handleIntentFromShortcuts(intent) + showWelcomeDialog() + } + + override fun onNewIntent(intent: Intent) { + super.onNewIntent(intent) + handleIntentFromShortcuts(intent) + } + + override fun showNavigationView() { + navViewBehavior.slideUp(binding.navView) + } + + override fun hideNavigationView() { + navViewBehavior.slideDown(binding.navView) + } + + override fun showProgressBar() { + binding.progressHorizontal.show() + } + + override fun hideProgressBar() { + binding.progressHorizontal.hide() + } + + override fun scheduleAppbarLiftingStatus(isLifted: Boolean, from: String) { + binding.appbar.isLifted = isLifted + } + + override fun setLiftOnScrollTargetView(targetView: View) { + binding.appbar.setLiftOnScrollTargetView(targetView) + } + + private fun handleIntentFromShortcuts(intent: Intent) { + when (intent.action) { + Constants.SHORTCUT_DETAIL -> binding.viewpager.setCurrentItem(0, false) + Constants.SHORTCUT_TOOLS -> binding.viewpager.setCurrentItem(2, false) + Constants.SHORTCUT_VCARD -> startActivity(Intent(this, VCardActivity::class.java)) + } + } + + override fun onRequestPermissionsResult( + requestCode: Int, permissions: Array, + grantResults: IntArray, + ) { + super.onRequestPermissionsResult(requestCode, permissions, grantResults) + if (requestCode == 100) { + for (i in permissions.indices) { + if (grantResults[i] == PackageManager.PERMISSION_GRANTED) { + MaterialAlertDialogBuilder(this) + .setMessage(R.string.gotPermission) + .setTitle(R.string.bath_title) + .setPositiveButton(R.string.ok) { _, _ -> } + .setCancelable(true) + .create() + .show() + } else { + MaterialAlertDialogBuilder(this) + .setMessage(R.string.failPermission) + .setTitle(R.string.error) + .setPositiveButton(R.string.ok) { _, _ -> + val intent = Intent(Settings.ACTION_APPLICATION_DETAILS_SETTINGS) + val uri = Uri.fromParts("package", packageName, null) + intent.data = uri + startActivity(intent) + } + .setCancelable(false) + .create() + .show() + } + } + } + } + + private fun showWelcomeDialog() { + if (GlobalValues.initialized) { + return + } else { + MaterialAlertDialogBuilder(this) + .setTitle(R.string.welcome) + .setMessage(R.string.welcome_message) + .setPositiveButton(R.string.ok) { _, _ -> + this.binding.viewpager.setCurrentItem(3, true) + } + .setNegativeButton(R.string.no) { _, _ -> } + .setCancelable(false) + .create() + .show() + GlobalValues.initialized = true + } + } +} \ No newline at end of file diff --git a/app/src/main/java/com/qhy040404/libraryonetap/ui/secret/SecretActivity.kt b/app/src/main/java/com/qhy040404/libraryonetap/ui/secret/SecretActivity.kt index d92734d8..e1a7be8a 100644 --- a/app/src/main/java/com/qhy040404/libraryonetap/ui/secret/SecretActivity.kt +++ b/app/src/main/java/com/qhy040404/libraryonetap/ui/secret/SecretActivity.kt @@ -1,14 +1,25 @@ package com.qhy040404.libraryonetap.ui.secret import android.net.Uri +import android.view.ViewGroup import com.qhy040404.libraryonetap.R import com.qhy040404.libraryonetap.base.BaseActivity +import com.qhy040404.libraryonetap.constant.GlobalValues +import com.qhy040404.libraryonetap.databinding.ActivitySecretBinding import com.qhy040404.libraryonetap.view.ModifiedVideoView -class SecretActivity : BaseActivity() { - override fun init() = Thread(Play()).start() +class SecretActivity : BaseActivity() { + override fun init() { + setSupportActionBar(binding.toolbar) + (binding.root as ViewGroup).bringChildToFront(binding.appbar) + supportActionBar?.setDisplayHomeAsUpEnabled(true) + binding.toolbar.title = getString(R.string.vcardTitle) + if (!GlobalValues.md3) { + binding.toolbar.setTitleTextColor(getColor(R.color.white)) + } - override fun getLayoutId(): Int = R.layout.activity_secret + Thread(Play()).start() + } private inner class Play : Runnable { override fun run() { diff --git a/app/src/main/java/com/qhy040404/libraryonetap/ui/tools/BathReserveActivity.kt b/app/src/main/java/com/qhy040404/libraryonetap/ui/tools/BathReserveActivity.kt index e6ed27b5..e2a1a9ab 100644 --- a/app/src/main/java/com/qhy040404/libraryonetap/ui/tools/BathReserveActivity.kt +++ b/app/src/main/java/com/qhy040404/libraryonetap/ui/tools/BathReserveActivity.kt @@ -3,21 +3,29 @@ package com.qhy040404.libraryonetap.ui.tools import android.os.Looper import android.os.StrictMode import android.view.View +import android.view.ViewGroup import android.widget.* import com.qhy040404.libraryonetap.R import com.qhy040404.libraryonetap.base.BaseActivity import com.qhy040404.libraryonetap.constant.GlobalValues import com.qhy040404.libraryonetap.constant.URLManager +import com.qhy040404.libraryonetap.databinding.ActivityBathReserveBinding import com.qhy040404.libraryonetap.utils.des.DesEncryptUtils import com.qhy040404.libraryonetap.utils.tools.BathUtils import com.qhy040404.libraryonetap.utils.web.Requests -class BathReserveActivity : BaseActivity() { +class BathReserveActivity : BaseActivity() { override fun init() = initView() - override fun getLayoutId(): Int = R.layout.activity_bath_reserve - private fun initView() { + setSupportActionBar(binding.toolbar) + (binding.root as ViewGroup).bringChildToFront(binding.appbar) + supportActionBar?.setDisplayHomeAsUpEnabled(true) + binding.toolbar.title = getString(R.string.vcardTitle) + if (!GlobalValues.md3) { + binding.toolbar.setTitleTextColor(getColor(R.color.white)) + } + val textViewBath: TextView = findViewById(R.id.textView3) textViewBath.visibility = View.VISIBLE Thread(BathReserve()).start() @@ -70,39 +78,38 @@ class BathReserveActivity : BaseActivity() { GlobalValues.ctSso ) - Requests.get(URLManager.BATH_DIRECT_URL) - - textViewBath.text = getString(R.string.loaded) - - reserve.setOnClickListener { - StrictMode.setThreadPolicy( - StrictMode.ThreadPolicy.Builder() - .detectDiskReads().detectDiskWrites().detectNetwork() - .penaltyLog().build() - ) - StrictMode.setVmPolicy( - StrictMode.VmPolicy.Builder() - .detectLeakedSqlLiteObjects().detectLeakedClosableObjects() - .penaltyLog().penaltyDeath().build() - ) - @Suppress("SpellCheckingInspection") - val savePostData = "mealorder=0&goodsid=$targetRoom&goodsnum=1&addlocation=1" - - @Suppress("SpellCheckingInspection") - val cartPostData = "goodsShopcarId=$targetRoom&rulesid=$time" - - @Suppress("SpellCheckingInspection") - val mainPostData = "goodsid=$targetRoom%2C&ruleid=$time" - - @Suppress("SpellCheckingInspection") - val payPostData = "goodis=$targetRoom&payway=nopay" - - Requests.post(URLManager.BATH_SAVE_CART_URL, savePostData, GlobalValues.ctSso) - Requests.post(URLManager.BATH_UPDATE_CART_URL, cartPostData, GlobalValues.ctSso) - Requests.post(URLManager.BATH_MAIN_FUNC_URL, mainPostData, GlobalValues.ctSso) - Requests.post(URLManager.BATH_PAY_URL, payPostData, GlobalValues.ctSso) - textViewBath.text = getString(R.string.sentRequest) - Looper.loop() + textViewBath.post { textViewBath.text = getString(R.string.loaded) } + + reserve.post { + reserve.setOnClickListener { + StrictMode.setThreadPolicy( + StrictMode.ThreadPolicy.Builder() + .detectDiskReads().detectDiskWrites().detectNetwork() + .penaltyLog().build() + ) + StrictMode.setVmPolicy( + StrictMode.VmPolicy.Builder() + .detectLeakedSqlLiteObjects().detectLeakedClosableObjects() + .penaltyLog().penaltyDeath().build() + ) + @Suppress("SpellCheckingInspection") + val savePostData = "mealorder=0&goodsid=$targetRoom&goodsnum=1&addlocation=1" + + @Suppress("SpellCheckingInspection") + val cartPostData = "goodsShopcarId=$targetRoom&rulesid=$time" + + @Suppress("SpellCheckingInspection") + val mainPostData = "goodsid=$targetRoom%2C&ruleid=$time" + + @Suppress("SpellCheckingInspection") + val payPostData = "goodis=$targetRoom&payway=nopay" + + Requests.post(URLManager.BATH_SAVE_CART_URL, savePostData, GlobalValues.ctSso) + Requests.post(URLManager.BATH_UPDATE_CART_URL, cartPostData, GlobalValues.ctSso) + Requests.post(URLManager.BATH_MAIN_FUNC_URL, mainPostData, GlobalValues.ctSso) + Requests.post(URLManager.BATH_PAY_URL, payPostData, GlobalValues.ctSso) + textViewBath.post { textViewBath.text = getString(R.string.sentRequest) } + } } spinner.onItemSelectedListener = object : AdapterView.OnItemSelectedListener { @@ -118,6 +125,7 @@ class BathReserveActivity : BaseActivity() { override fun onNothingSelected(p0: AdapterView<*>?) {} } + Looper.loop() } } } \ No newline at end of file diff --git a/app/src/main/java/com/qhy040404/libraryonetap/ui/tools/ToolsInitActivity.kt b/app/src/main/java/com/qhy040404/libraryonetap/ui/tools/ToolsInitActivity.kt deleted file mode 100644 index 83f5c6bc..00000000 --- a/app/src/main/java/com/qhy040404/libraryonetap/ui/tools/ToolsInitActivity.kt +++ /dev/null @@ -1,55 +0,0 @@ -package com.qhy040404.libraryonetap.ui.tools - -import android.content.Intent -import android.content.pm.PackageManager -import android.net.Uri -import android.provider.Settings -import androidx.appcompat.app.AlertDialog -import com.qhy040404.libraryonetap.R -import com.qhy040404.libraryonetap.base.BaseActivity -import com.qhy040404.libraryonetap.fragment.tools.ToolsInitFragment - -class ToolsInitActivity : BaseActivity() { - override fun init() { - supportFragmentManager - .beginTransaction() - .replace(R.id.tools_list_screen, ToolsInitFragment()) - .commit() - supportActionBar?.setDisplayHomeAsUpEnabled(true) - } - - override fun getLayoutId(): Int = R.layout.activity_tools_init - - override fun onRequestPermissionsResult( - requestCode: Int, permissions: Array, - grantResults: IntArray, - ) { - super.onRequestPermissionsResult(requestCode, permissions, grantResults) - if (requestCode == 100) { - for (i in permissions.indices) { - if (grantResults[i] == PackageManager.PERMISSION_GRANTED) { - AlertDialog.Builder(this) - .setMessage(R.string.gotPermission) - .setTitle(R.string.bath_title) - .setPositiveButton(R.string.ok) { _, _ -> } - .setCancelable(true) - .create() - .show() - } else { - AlertDialog.Builder(this) - .setMessage(R.string.failPermission) - .setTitle(R.string.error) - .setPositiveButton(R.string.ok) { _, _ -> - val intent = Intent(Settings.ACTION_APPLICATION_DETAILS_SETTINGS) - val uri = Uri.fromParts("package", packageName, null) - intent.data = uri - startActivity(intent) - } - .setCancelable(false) - .create() - .show() - } - } - } - } -} \ No newline at end of file diff --git a/app/src/main/java/com/qhy040404/libraryonetap/ui/tools/VCardActivity.kt b/app/src/main/java/com/qhy040404/libraryonetap/ui/tools/VCardActivity.kt index 263a38f9..f066d02c 100644 --- a/app/src/main/java/com/qhy040404/libraryonetap/ui/tools/VCardActivity.kt +++ b/app/src/main/java/com/qhy040404/libraryonetap/ui/tools/VCardActivity.kt @@ -5,6 +5,7 @@ import android.os.Looper import android.os.StrictMode import android.util.Base64 import android.view.View +import android.view.ViewGroup import android.widget.Button import android.widget.ImageView import android.widget.ProgressBar @@ -13,15 +14,22 @@ import com.qhy040404.libraryonetap.R import com.qhy040404.libraryonetap.base.BaseActivity import com.qhy040404.libraryonetap.constant.GlobalValues import com.qhy040404.libraryonetap.constant.URLManager +import com.qhy040404.libraryonetap.databinding.ActivityVcardBinding import com.qhy040404.libraryonetap.utils.tools.QRUtils import com.qhy040404.libraryonetap.utils.web.Requests -class VCardActivity : BaseActivity() { +class VCardActivity : BaseActivity() { override fun init() = initView() - override fun getLayoutId(): Int = R.layout.activity_vcard - private fun initView() { + setSupportActionBar(binding.toolbar) + (binding.root as ViewGroup).bringChildToFront(binding.appbar) + supportActionBar?.setDisplayHomeAsUpEnabled(true) + binding.toolbar.title = getString(R.string.vcardTitle) + if (!GlobalValues.md3) { + binding.toolbar.setTitleTextColor(getColor(R.color.white)) + } + val textView: TextView = findViewById(R.id.textView4) textView.visibility = View.VISIBLE Thread(VCard()).start() @@ -75,29 +83,31 @@ class VCardActivity : BaseActivity() { val bitmap = BitmapFactory.decodeByteArray(qr, 0, qr.size) progressBar.post { progressBar.visibility = View.INVISIBLE } imageView.post { imageView.setImageBitmap(QRUtils.toGrayscale(bitmap)) } - textView.text = qrInformation - refresh.setOnClickListener { - StrictMode.setThreadPolicy( - StrictMode.ThreadPolicy.Builder() - .detectDiskReads().detectDiskWrites().detectNetwork() - .penaltyLog().build() - ) - StrictMode.setVmPolicy( - StrictMode.VmPolicy.Builder() - .detectLeakedSqlLiteObjects().detectLeakedClosableObjects() - .penaltyLog().penaltyDeath().build() - ) - val newQrPage = Requests.getVCard(qrUrl) - val newQrInformation = newQrPage.split("

")[1].split("

")[0] + textView.post { textView.text = qrInformation } + refresh.post { + refresh.setOnClickListener { + StrictMode.setThreadPolicy( + StrictMode.ThreadPolicy.Builder() + .detectDiskReads().detectDiskWrites().detectNetwork() + .penaltyLog().build() + ) + StrictMode.setVmPolicy( + StrictMode.VmPolicy.Builder() + .detectLeakedSqlLiteObjects().detectLeakedClosableObjects() + .penaltyLog().penaltyDeath().build() + ) + val newQrPage = Requests.getVCard(qrUrl) + val newQrInformation = newQrPage.split("

")[1].split("

")[0] - @Suppress("SpellCheckingInspection") - val newQrBase64 = newQrPage - .split("")[0] - val newQr = Base64.decode(newQrBase64, Base64.DEFAULT) - val newBitmap = BitmapFactory.decodeByteArray(newQr, 0, newQr.size) - imageView.post { imageView.setImageBitmap(QRUtils.toGrayscale(newBitmap)) } - textView.text = newQrInformation + @Suppress("SpellCheckingInspection") + val newQrBase64 = newQrPage + .split("")[0] + val newQr = Base64.decode(newQrBase64, Base64.DEFAULT) + val newBitmap = BitmapFactory.decodeByteArray(newQr, 0, newQr.size) + imageView.post { imageView.setImageBitmap(QRUtils.toGrayscale(newBitmap)) } + textView.text = newQrInformation + } } Looper.loop() } diff --git a/app/src/main/java/com/qhy040404/libraryonetap/utils/AppUtils.kt b/app/src/main/java/com/qhy040404/libraryonetap/utils/AppUtils.kt new file mode 100644 index 00000000..b52083c8 --- /dev/null +++ b/app/src/main/java/com/qhy040404/libraryonetap/utils/AppUtils.kt @@ -0,0 +1,96 @@ +package com.qhy040404.libraryonetap.utils + +import android.app.ActivityManager +import android.app.Application +import android.content.Context +import android.content.res.Configuration +import android.text.Spannable +import android.text.SpannableStringBuilder +import androidx.core.content.edit +import androidx.core.text.toSpannable +import com.google.android.material.dialog.MaterialAlertDialogBuilder +import com.qhy040404.libraryonetap.R +import com.qhy040404.libraryonetap.constant.Constants +import com.qhy040404.libraryonetap.constant.GlobalValues +import rikka.material.app.DayNightDelegate +import java.util.* + +object AppUtils { + fun getNightMode(modeString: String): Int { + return when (modeString) { + "on" -> DayNightDelegate.MODE_NIGHT_YES + "off" -> DayNightDelegate.MODE_NIGHT_NO + else -> DayNightDelegate.MODE_NIGHT_FOLLOW_SYSTEM + } + } + + var locale: Locale = Locale.getDefault() + get() { + val tag = GlobalValues.locale + if (tag.isEmpty() || "system" == tag) { + return Locale.getDefault() + } + return Locale.forLanguageTag(tag) + } + set(value) { + field = value + SPUtils.sp.edit { putString(Constants.PREF_LOCALE, value.toLanguageTag()) } + } + + fun setTitle(ctx: Context): Spannable { + val sb = SpannableStringBuilder(ctx.getString(R.string.app_name)) + return sb.toSpannable() + } + + fun getThemeID(theme: String): Int { + return when (theme) { + "purple" -> R.style.Theme_Purple_NoActionBar + "library" -> R.style.Theme_Main_NoActionBar + "blue" -> R.style.Theme_Blue_NoActionBar + "pink" -> R.style.Theme_Pink_NoActionBar + "green" -> R.style.Theme_Green_NoActionBar + "orange" -> R.style.Theme_Orange_NoActionBar + "red" -> R.style.Theme_Red_NoActionBar + "simple" -> R.style.Theme_Simple_NoActionBar + else -> getThemeID(RandomDataUtils.randomTheme) + } + } + + fun checkData(id: String, passwd: String): Boolean { + return id != "Error" && passwd != "Error" + } + + fun checkDataAndDialog( + ctx: Context, + id: String, + passwd: String, + titleResId: Int, + messageResId: Int, + ): Boolean { + return if (id == "Error" || passwd == "Error") { + MaterialAlertDialogBuilder(ctx) + .setTitle(titleResId) + .setMessage(messageResId) + .setPositiveButton(R.string.ok) { _, _ -> } + .setCancelable(true) + .create() + .show() + false + } else { + true + } + } + + fun clearAppData(app: Application) { + val am = app.getSystemService(Context.ACTIVITY_SERVICE) as ActivityManager + am.clearApplicationUserData() + } + + fun currentIsNightMode(ctx: Context): Boolean { + val uiMode = ctx.resources.configuration.uiMode + return when (uiMode and Configuration.UI_MODE_NIGHT_MASK) { + Configuration.UI_MODE_NIGHT_YES -> true + else -> false + } + } +} \ No newline at end of file diff --git a/app/src/main/java/com/qhy040404/libraryonetap/utils/CacheUtils.kt b/app/src/main/java/com/qhy040404/libraryonetap/utils/CacheUtils.kt new file mode 100644 index 00000000..1c68e9c4 --- /dev/null +++ b/app/src/main/java/com/qhy040404/libraryonetap/utils/CacheUtils.kt @@ -0,0 +1,84 @@ +package com.qhy040404.libraryonetap.utils + +import com.qhy040404.libraryonetap.LibraryOneTapApp +import java.text.DecimalFormat + + +object CacheUtils { + private val externalCache = LibraryOneTapApp.app.externalCacheDir + private val cache = LibraryOneTapApp.app.cacheDir + private val codeCache = LibraryOneTapApp.app.codeCacheDir + + fun getCacheSize(): String { + return formatFileSize( + FileUtils.getFileSize(externalCache!!) + + FileUtils.getFileSize(cache) + + FileUtils.getFileSize(codeCache) + ) + } + + private fun formatFileSize(fileSize: Long): String { + if (fileSize == 0L) { + return "0.00 K" + } + val df = DecimalFormat("#.00") + return if (fileSize < 1024) { + df.format(fileSize.toDouble()) + " B" + } else if (fileSize < 1024 * 1024) { + df.format(fileSize.toDouble() / 1024) + " K" + } else if (fileSize < 1024 * 1024 * 1024) { + df.format(fileSize.toDouble() / 1024 * 1024) + " M" + } else { + df.format(fileSize.toDouble() / 1024 * 1024 * 1024) + " G" + } + } + + fun trimCaches() { + trimCache() + trimCodeCache() + trimExternalCache() + } + + private fun trimCache(): Boolean { + return try { + if (cache != null && cache.isDirectory && cache.listFiles()!!.isNotEmpty()) { + FileUtils.delete(cache) + } else { + false + } + } catch (e: Exception) { + e.printStackTrace() + false + } + } + + private fun trimCodeCache(): Boolean { + return try { + if (codeCache != null && codeCache.isDirectory && codeCache.listFiles()!! + .isNotEmpty() + ) { + FileUtils.delete(codeCache) + } else { + false + } + } catch (e: Exception) { + e.printStackTrace() + false + } + } + + private fun trimExternalCache(): Boolean { + return try { + if (externalCache != null && externalCache.isDirectory && externalCache.listFiles()!! + .isNotEmpty() + ) { + FileUtils.delete(externalCache) + } else { + false + } + } catch (e: Exception) { + e.printStackTrace() + false + } + } +} \ No newline at end of file diff --git a/app/src/main/java/com/qhy040404/libraryonetap/utils/FileUtils.kt b/app/src/main/java/com/qhy040404/libraryonetap/utils/FileUtils.kt new file mode 100644 index 00000000..e5e75419 --- /dev/null +++ b/app/src/main/java/com/qhy040404/libraryonetap/utils/FileUtils.kt @@ -0,0 +1,45 @@ +package com.qhy040404.libraryonetap.utils + +import java.io.File +import java.nio.file.Files +import java.nio.file.Paths + +object FileUtils { + fun delete(file: File?): Boolean { + if (file == null) return false + return if (file.isDirectory) { + deleteDir(file) + } else deleteFile(file) + } + + private fun deleteDir(dir: File?): Boolean { + if (dir == null) return false + if (!dir.exists()) return true + if (!dir.isDirectory) return false + val files = dir.listFiles() + if (files != null && files.isNotEmpty()) { + for (file in files) { + if (file.isFile) { + if (!file.delete()) return false + } else if (file.isDirectory) { + if (!deleteDir(file)) return false + } + } + } + return dir.delete() + } + + private fun deleteFile(file: File?): Boolean { + return file != null && (!file.exists() || file.isFile && file.delete()) + } + + fun getFileSize(file: File): Long { + return getFileSize(file.path) + } + + fun getFileSize(path: String): Long { + return runCatching { + Files.size(Paths.get(path)) + }.getOrDefault(0L) + } +} \ No newline at end of file diff --git a/app/src/main/java/com/qhy040404/libraryonetap/utils/OsUtils.kt b/app/src/main/java/com/qhy040404/libraryonetap/utils/OsUtils.kt index 878e63a6..35bde923 100644 --- a/app/src/main/java/com/qhy040404/libraryonetap/utils/OsUtils.kt +++ b/app/src/main/java/com/qhy040404/libraryonetap/utils/OsUtils.kt @@ -8,4 +8,9 @@ object OsUtils { fun atLeastT(): Boolean { return Build.VERSION.SDK_INT >= 33 } + + @ChecksSdkIntAtLeast(api = Build.VERSION_CODES.Q) + fun atLeastQ(): Boolean { + return Build.VERSION.SDK_INT >= 29 + } } \ No newline at end of file diff --git a/app/src/main/java/com/qhy040404/libraryonetap/utils/RandomDataUtils.kt b/app/src/main/java/com/qhy040404/libraryonetap/utils/RandomDataUtils.kt index e5cb299a..d1b9626d 100644 --- a/app/src/main/java/com/qhy040404/libraryonetap/utils/RandomDataUtils.kt +++ b/app/src/main/java/com/qhy040404/libraryonetap/utils/RandomDataUtils.kt @@ -14,11 +14,14 @@ object RandomDataUtils { } val randomTheme by ResettableLazyUtils.resettableLazy(GlobalManager.lazyMgr) { - when (getNum(5)) { + when (getNum(8)) { 0 -> "purple" - 1 -> "blue" - 2 -> "pink" - 3 -> "green" + 1 -> "library" + 2 -> "blue" + 3 -> "pink" + 4 -> "green" + 5 -> "orange" + 6 -> "red" else -> "simple" } } diff --git a/app/src/main/java/com/qhy040404/libraryonetap/utils/ReserveUtils.kt b/app/src/main/java/com/qhy040404/libraryonetap/utils/ReserveUtils.kt index 2d656e75..cc4bcde4 100644 --- a/app/src/main/java/com/qhy040404/libraryonetap/utils/ReserveUtils.kt +++ b/app/src/main/java/com/qhy040404/libraryonetap/utils/ReserveUtils.kt @@ -20,7 +20,9 @@ object ReserveUtils { } fun formatAvailableMap(am: String): String { - return am.replace("\r\n\r\n[[", "").replace("]]\r\n\r\n\r\n\r\n", "") - .replace("{", "").replace("}", "") + return am.replace("\r\n\r\n[[", "") + .replace("]]\r\n\r\n\r\n\r\n", "") + .replace("{", "") + .replace("}", "") } } \ No newline at end of file diff --git a/app/src/main/java/com/qhy040404/libraryonetap/utils/SPUtils.kt b/app/src/main/java/com/qhy040404/libraryonetap/utils/SPUtils.kt index 885edff9..6e6271db 100644 --- a/app/src/main/java/com/qhy040404/libraryonetap/utils/SPUtils.kt +++ b/app/src/main/java/com/qhy040404/libraryonetap/utils/SPUtils.kt @@ -6,7 +6,7 @@ import com.qhy040404.libraryonetap.LibraryOneTapApp import com.qhy040404.libraryonetap.constant.GlobalValues.SP_NAME object SPUtils { - private val sp: SharedPreferences by lazy { + val sp: SharedPreferences by lazy { LibraryOneTapApp.app.getSharedPreferences( SP_NAME, Context.MODE_PRIVATE diff --git a/app/src/main/java/com/qhy040404/libraryonetap/utils/extensions/CompatExtensions.kt b/app/src/main/java/com/qhy040404/libraryonetap/utils/extensions/CompatExtensions.kt new file mode 100644 index 00000000..5494767b --- /dev/null +++ b/app/src/main/java/com/qhy040404/libraryonetap/utils/extensions/CompatExtensions.kt @@ -0,0 +1,17 @@ +package com.qhy040404.libraryonetap.utils.extensions + +import android.view.LayoutInflater +import androidx.lifecycle.LifecycleOwner +import androidx.viewbinding.ViewBinding +import java.lang.reflect.ParameterizedType + +object CompatExtensions { + @Suppress("UNCHECKED_CAST") + fun LifecycleOwner.inflateBinding(inflater: LayoutInflater): T { + return (javaClass.genericSuperclass as ParameterizedType).actualTypeArguments + .filterIsInstance>() + .first() + .getDeclaredMethod("inflate", LayoutInflater::class.java) + .invoke(null, inflater) as T + } +} \ No newline at end of file diff --git a/app/src/main/java/com/qhy040404/libraryonetap/utils/extensions/ViewExtensions.kt b/app/src/main/java/com/qhy040404/libraryonetap/utils/extensions/ViewExtensions.kt new file mode 100644 index 00000000..7668a003 --- /dev/null +++ b/app/src/main/java/com/qhy040404/libraryonetap/utils/extensions/ViewExtensions.kt @@ -0,0 +1,44 @@ +package com.qhy040404.libraryonetap.utils.extensions + +import android.animation.Animator +import android.animation.TimeInterpolator +import android.animation.ValueAnimator +import android.content.res.Resources +import android.view.animation.AccelerateDecelerateInterpolator +import androidx.viewpager2.widget.ViewPager2 + +object ViewExtensions { + val Number.dp: Int get() = (toInt() * Resources.getSystem().displayMetrics.density).toInt() + + fun ViewPager2.setCurrentItem( + item: Int, + duration: Long, + interpolator: TimeInterpolator = AccelerateDecelerateInterpolator(), + pagePxWidth: Int = width, + ) { + val pxToDrag: Int = pagePxWidth * (item - currentItem) + val animator = ValueAnimator.ofInt(0, pxToDrag) + var previousValue = 0 + animator.addUpdateListener { valueAnimator -> + val currentValue = valueAnimator.animatedValue as Int + val currentPxToDrag = (currentValue - previousValue).toFloat() + fakeDragBy(-currentPxToDrag) + previousValue = currentValue + } + animator.addListener(object : Animator.AnimatorListener { + override fun onAnimationStart(animation: Animator) { + beginFakeDrag() + } + + override fun onAnimationEnd(animation: Animator) { + endFakeDrag() + } + + override fun onAnimationCancel(animation: Animator) {} + override fun onAnimationRepeat(animation: Animator) {} + }) + animator.interpolator = interpolator + animator.duration = duration + animator.start() + } +} \ No newline at end of file diff --git a/app/src/main/java/com/qhy040404/libraryonetap/utils/tools/GetPortalData.kt b/app/src/main/java/com/qhy040404/libraryonetap/utils/tools/GetPortalData.kt index f4295630..b38bc051 100644 --- a/app/src/main/java/com/qhy040404/libraryonetap/utils/tools/GetPortalData.kt +++ b/app/src/main/java/com/qhy040404/libraryonetap/utils/tools/GetPortalData.kt @@ -28,16 +28,22 @@ object GetPortalData { while (!loginSuccess) { val ltResponse: String = Requests.get(URLManager.PORTAL_SSO_URL) - val ltData: String = "LT" + ltResponse.split("LT")[1].split("cas")[0] + "cas" + val ltData: String = try { + "LT" + ltResponse.split("LT")[1].split("cas")[0] + "cas" + } catch (e: Exception) { + "" + } - val rawData = "$id$passwd$ltData" - val rsa: String = des.strEnc(rawData, "1", "2", "3") + if (ltData != "") { + val rawData = "$id$passwd$ltData" + val rsa: String = des.strEnc(rawData, "1", "2", "3") - Requests.post( - URLManager.PORTAL_SSO_URL, - Requests.loginPostData(id, passwd, ltData, rsa), - GlobalValues.ctSso - ) + Requests.post( + URLManager.PORTAL_SSO_URL, + Requests.loginPostData(id, passwd, ltData, rsa), + GlobalValues.ctSso + ) + } val session = Requests.get(URLManager.PORTAL_SSO_URL) if (!session.contains("统一身份")) { diff --git a/app/src/main/java/com/qhy040404/libraryonetap/utils/web/Requests.kt b/app/src/main/java/com/qhy040404/libraryonetap/utils/web/Requests.kt index d1f95d89..a5ae94d8 100644 --- a/app/src/main/java/com/qhy040404/libraryonetap/utils/web/Requests.kt +++ b/app/src/main/java/com/qhy040404/libraryonetap/utils/web/Requests.kt @@ -9,6 +9,8 @@ import java.util.concurrent.TimeUnit @Suppress("SpellCheckingInspection") object Requests { val client = OkHttpClient.Builder() + .followRedirects(false) + .followSslRedirects(false) .connectTimeout(30, TimeUnit.SECONDS) .readTimeout(60, TimeUnit.SECONDS) .writeTimeout(60, TimeUnit.SECONDS) @@ -32,44 +34,87 @@ object Requests { @Throws(IOException::class) fun get(url: String): String { - val request: Request = Request.Builder() + val request = Request.Builder() .url(url) .get() .build() - client.newCall(request).execute().use { response -> return response.body!!.string() } + client.newCall(request).execute().use { response -> + if (response.code == 302) { + return get(response.headers["Location"].toString()) + } + return response.body!!.string() + } + } + + @Throws(IOException::class) + fun getRedirectURL(url: String): String { + val request = Request.Builder() + .url(url) + .get() + .build() + client.newCall(request).execute().use { response -> + return response.headers["Location"].toString() + } } @Throws(IOException::class) fun getVCard(url: String): String { - val request: Request = Request.Builder() + val request = Request.Builder() .url(url) .removeHeader("User-Agent") .addHeader("User-Agent", "weishao") .get() .build() - client.newCall(request).execute().use { response -> return response.body!!.string() } + client.newCall(request).execute().use { response -> + if (response.code == 302) { + return getVCard(response.headers["Location"].toString()) + } + return response.body!!.string() + } } @Throws(IOException::class) fun post(url: String, form: String, FORM: MediaType): String { - val body: RequestBody = form.toRequestBody(FORM) - val request: Request = Request.Builder() + val body = form.toRequestBody(FORM) + val request = Request.Builder() .url(url) .post(body) .build() - client.newCall(request).execute().use { response -> return response.body!!.string() } + client.newCall(request).execute().use { response -> + if (response.code == 302) { + return get(response.headers["Location"].toString()) + } + return response.body!!.string() + } + } + + @Throws(IOException::class) + fun postRedirectURL(url: String, form: String, FORM: MediaType): String { + val body = form.toRequestBody(FORM) + val request = Request.Builder() + .url(url) + .post(body) + .build() + client.newCall(request).execute().use { response -> + return response.headers["Location"].toString() + } } @Throws(IOException::class) fun postVCard(url: String, form: String, FORM: MediaType): String { - val body: RequestBody = form.toRequestBody(FORM) - val request: Request = Request.Builder() + val body = form.toRequestBody(FORM) + val request = Request.Builder() .url(url) .removeHeader("User-Agent") .addHeader("User-Agent", "weishao") .post(body) .build() - client.newCall(request).execute().use { response -> return response.body!!.string() } + client.newCall(request).execute().use { response -> + if (response.code == 302) { + return getVCard(response.headers["Location"].toString()) + } + return response.body!!.string() + } } fun loginPostData(id: String, passwd: String, ltData: String, rsa: String): String { diff --git a/app/src/main/res/drawable/ic_about_foreground.xml b/app/src/main/res/drawable/ic_about_foreground.xml new file mode 100644 index 00000000..e66a918d --- /dev/null +++ b/app/src/main/res/drawable/ic_about_foreground.xml @@ -0,0 +1,71 @@ + + + + + + + + + + + + + + + diff --git a/app/src/main/res/drawable/ic_bath.xml b/app/src/main/res/drawable/ic_bath.xml new file mode 100644 index 00000000..3d679a8d --- /dev/null +++ b/app/src/main/res/drawable/ic_bath.xml @@ -0,0 +1,35 @@ + + + + + + + + diff --git a/app/src/main/res/drawable/ic_cache.xml b/app/src/main/res/drawable/ic_cache.xml new file mode 100644 index 00000000..7585769c --- /dev/null +++ b/app/src/main/res/drawable/ic_cache.xml @@ -0,0 +1,42 @@ + + + + + + + + + diff --git a/app/src/main/res/drawable/ic_elec.xml b/app/src/main/res/drawable/ic_elec.xml new file mode 100644 index 00000000..2e9ec251 --- /dev/null +++ b/app/src/main/res/drawable/ic_elec.xml @@ -0,0 +1,10 @@ + + + diff --git a/app/src/main/res/drawable/ic_launcher_foreground.xml b/app/src/main/res/drawable/ic_launcher_foreground.xml new file mode 100644 index 00000000..b3b18aa3 --- /dev/null +++ b/app/src/main/res/drawable/ic_launcher_foreground.xml @@ -0,0 +1,72 @@ + + + + + + + + + + + + + + + + diff --git a/app/src/main/res/drawable/ic_material.xml b/app/src/main/res/drawable/ic_material.xml new file mode 100644 index 00000000..860aecb8 --- /dev/null +++ b/app/src/main/res/drawable/ic_material.xml @@ -0,0 +1,12 @@ + + + + \ No newline at end of file diff --git a/app/src/main/res/drawable/ic_multi.xml b/app/src/main/res/drawable/ic_multi.xml new file mode 100644 index 00000000..61db258f --- /dev/null +++ b/app/src/main/res/drawable/ic_multi.xml @@ -0,0 +1,37 @@ + + + + + + + + diff --git a/app/src/main/res/drawable/ic_single.xml b/app/src/main/res/drawable/ic_single.xml new file mode 100644 index 00000000..7eddde00 --- /dev/null +++ b/app/src/main/res/drawable/ic_single.xml @@ -0,0 +1,15 @@ + + + + diff --git a/app/src/main/res/drawable/ic_tools.xml b/app/src/main/res/drawable/ic_tools.xml new file mode 100644 index 00000000..21c01f4f --- /dev/null +++ b/app/src/main/res/drawable/ic_tools.xml @@ -0,0 +1,82 @@ + + + + + + + + + + + + + + + + + diff --git a/app/src/main/res/drawable/ic_volunteer.xml b/app/src/main/res/drawable/ic_volunteer.xml new file mode 100644 index 00000000..29fcc6c9 --- /dev/null +++ b/app/src/main/res/drawable/ic_volunteer.xml @@ -0,0 +1,11 @@ + + + diff --git a/app/src/main/res/drawable/simplepage_card.xml b/app/src/main/res/drawable/simplepage_card.xml new file mode 100644 index 00000000..62fea474 --- /dev/null +++ b/app/src/main/res/drawable/simplepage_card.xml @@ -0,0 +1,12 @@ + + + + + + + + + + + + diff --git a/app/src/main/res/layout/activity_bath_reserve.xml b/app/src/main/res/layout/activity_bath_reserve.xml index 11de059e..0680b427 100644 --- a/app/src/main/res/layout/activity_bath_reserve.xml +++ b/app/src/main/res/layout/activity_bath_reserve.xml @@ -4,8 +4,29 @@ xmlns:tools="http://schemas.android.com/tools" android:layout_width="match_parent" android:layout_height="match_parent" + android:fitsSystemWindows="false" + app:consumeSystemWindowsInsets="start|end" + app:edgeToEdge="true" + app:fitsSystemWindowsInsets="start|end" tools:context=".ui.tools.BathReserveActivity"> + + + + + + - - -