* Rename .java to .kt

* Initial Workmanager migration

* Fix notification

* *

* Add timepicker

* Fix TimePicker layout

* Use 12H clock

* *

* Fixup
This commit is contained in:
tarsin authored and GitHub committed 2023-02-17 11:39:42 +08:00
1 parent 6e7e668d39
commit 4939ce37c3
12 files changed
+171 -95

No files matched your search

@@ -21,10 +21,6 @@ import android.app.Activity
import android.app.ActivityManager
import android.app.Application
import android.content.ComponentCallbacks2
import android.text.Html
import android.text.method.LinkMovementMethod
import android.view.View
import android.widget.TextView
import androidx.appcompat.app.AppCompatDelegate
import androidx.collection.LruCache
import androidx.core.content.getSystemService
@@ -34,15 +30,11 @@ import androidx.lifecycle.ProcessLifecycleOwner
import coil.ImageLoader
import coil.ImageLoaderFactory
import com.hippo.Native
import com.hippo.app.BaseDialogBuilder
import com.hippo.ehviewer.client.EhCookieStore
import com.hippo.ehviewer.client.EhDns
import com.hippo.ehviewer.client.EhRequestBuilder
import com.hippo.ehviewer.client.EhSSLSocketFactory
import com.hippo.ehviewer.client.EhTagDatabase
import com.hippo.ehviewer.client.EhUrl
import com.hippo.ehviewer.client.data.GalleryDetail
import com.hippo.ehviewer.client.parser.EventPaneParser
import com.hippo.ehviewer.dao.buildMainDB
import com.hippo.ehviewer.download.DownloadManager
import com.hippo.ehviewer.ui.CommonOperations
@@ -56,7 +48,6 @@ import eu.kanade.tachiyomi.ui.reader.setting.ReaderPreferences
import eu.kanade.tachiyomi.util.lang.launchIO
import kotlinx.coroutines.DelicateCoroutinesApi
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.ExperimentalCoroutinesApi
import okhttp3.OkHttpClient
import java.net.Proxy
import java.security.KeyStore
@@ -111,9 +102,6 @@ class EhApplication : Application(), DefaultLifecycleObserver, ImageLoaderFactor
launchIO {
cleanupDownload()
}
launchIO {
theDawnOfNewDay()
}
}
mIdGenerator.setNextId(Settings.getInt(KEY_GLOBAL_STUFF_NEXT_ID, 0))
}
@@ -140,54 +128,6 @@ class EhApplication : Application(), DefaultLifecycleObserver, ImageLoaderFactor
}
}
private fun theDawnOfNewDay() {
if (!Settings.getRequestNews()) {
return
}
if (ehCookieStore.hasSignedIn()) {
val referer = EhUrl.REFERER_E
val request = EhRequestBuilder(EhUrl.HOST_E + "news.php", referer).build()
val call = okHttpClient.newCall(request)
try {
call.execute().use { response ->
val responseBody = response.body
val body = responseBody.string()
val html = EventPaneParser.parse(body)
if (html != null) {
showEventPane(html)
}
}
} catch (e: Throwable) {
e.printStackTrace()
}
}
}
fun showEventPane(html: String) {
if (Settings.getHideHvEvents() && html.contains("You have encountered a monster!")) {
return
}
val activity = topActivity
activity?.runOnUiThread {
val dialog = BaseDialogBuilder(activity)
.setMessage(Html.fromHtml(html, Html.FROM_HTML_MODE_LEGACY))
.setPositiveButton(android.R.string.ok, null)
.create()
dialog.setOnShowListener {
val messageView = dialog.findViewById<View>(android.R.id.message)
if (messageView is TextView) {
messageView.movementMethod = LinkMovementMethod.getInstance()
}
}
try {
dialog.show()
} catch (t: Throwable) {
// ignore
}
}
}
private fun clearTempDir() {
var dir = AppConfig.getTempDir()
if (null != dir) {
@@ -243,7 +183,6 @@ class EhApplication : Application(), DefaultLifecycleObserver, ImageLoaderFactor
locked = true
}
@OptIn(ExperimentalCoroutinesApi::class)
override fun newImageLoader(): ImageLoader {
return ImageLoader.Builder(this).apply {
okHttpClient(okHttpClient)
@@ -63,6 +63,9 @@ public class Settings {
public static final String KEY_EXCLUDED_TAG_NAMESPACES = "excluded_tag_namespaces";
public static final String KEY_EXCLUDED_LANGUAGES = "excluded_languages";
public static final String KEY_REQUEST_NEWS = "request_news";
public static final String KEY_REQUEST_NEWS_TIMER = "request_news_timer";
public static final String KEY_REQUEST_NEWS_TIMER_HOUR = "request_news_timer_hour";
public static final String KEY_REQUEST_NEWS_TIMER_MINUTE = "request_news_timer_minute";
public static final String KEY_HIDE_HV_EVENTS = "hide_hv_events";
public static final String[] SIGN_IN_REQUIRED = {
KEY_IMAGE_LIMITS,
@@ -205,7 +208,7 @@ public class Settings {
private static final int DEFAULT_CLIPBOARD_TEXT_HASH_CODE = 0;
private static final String KEY_DOWNLOAD_DELAY = "download_delay";
private static final int DEFAULT_DOWNLOAD_DELAY = 0;
private static final boolean DEFAULT_REQUEST_NEWS = true;
private static final boolean DEFAULT_REQUEST_NEWS = false;
private static final String KEY_ARCHIVE_PASSWDS = "archive_passwds";
private static final String KEY_QS_SAVE_PROGRESS = "qs_save_progress";
private static final boolean DEFAULT_QS_SAVE_PROGRESS = true;
@@ -20,7 +20,6 @@ import android.util.Log
import android.util.Pair
import com.hippo.ehviewer.AppConfig
import com.hippo.ehviewer.EhApplication
import com.hippo.ehviewer.EhApplication.Companion.application
import com.hippo.ehviewer.GetText
import com.hippo.ehviewer.R
import com.hippo.ehviewer.Settings
@@ -31,7 +30,6 @@ import com.hippo.ehviewer.client.data.PreviewSet
import com.hippo.ehviewer.client.exception.EhException
import com.hippo.ehviewer.client.exception.ParseException
import com.hippo.ehviewer.client.parser.ArchiveParser
import com.hippo.ehviewer.client.parser.EventPaneParser
import com.hippo.ehviewer.client.parser.FavoritesParser
import com.hippo.ehviewer.client.parser.ForumsParser
import com.hippo.ehviewer.client.parser.GalleryApiParser
@@ -322,10 +320,6 @@ object EhEngine {
code = response.code
headers = response.headers
body = response.body.string()
val html = EventPaneParser.parse(body)
if (html != null) {
application.showEventPane(html)
}
return GalleryDetailParser.parse(body!!)
}
} catch (e: Throwable) {
@@ -15,31 +15,12 @@
* You should have received a copy of the GNU General Public License along with EhViewer.
* If not, see <https://www.gnu.org/licenses/>.
*/
package com.hippo.ehviewer.client.parser
package com.hippo.ehviewer.client.parser;
import org.jsoup.Jsoup
import com.hippo.util.ExceptionUtils;
import org.jsoup.Jsoup;
import org.jsoup.nodes.Document;
import org.jsoup.nodes.Element;
public class EventPaneParser {
public static String parse(String body) {
String event = null;
try {
Document d = Jsoup.parse(body);
Element eventpane = d.getElementById("eventpane");
if (eventpane != null) {
event = eventpane.html();
}
} catch (Throwable e) {
ExceptionUtils.throwIfFatal(e);
e.printStackTrace();
}
return event;
object EventPaneParser {
fun parse(body: String): String? {
return Jsoup.parse(body).getElementById("eventpane")?.html()
}
}
@@ -0,0 +1,112 @@
package com.hippo.ehviewer.dailycheck
import android.annotation.SuppressLint
import android.content.Context
import android.text.Html
import androidx.core.app.NotificationChannelCompat
import androidx.core.app.NotificationCompat
import androidx.core.app.NotificationManagerCompat
import androidx.work.Constraints
import androidx.work.ExistingPeriodicWorkPolicy
import androidx.work.NetworkType
import androidx.work.PeriodicWorkRequest
import androidx.work.PeriodicWorkRequestBuilder
import androidx.work.WorkManager
import androidx.work.Worker
import androidx.work.WorkerParameters
import com.hippo.ehviewer.EhApplication
import com.hippo.ehviewer.R
import com.hippo.ehviewer.Settings
import com.hippo.ehviewer.client.EhRequestBuilder
import com.hippo.ehviewer.client.EhUrl
import com.hippo.ehviewer.client.parser.EventPaneParser
import java.time.Duration
import java.time.LocalDateTime
private val signedIn
get() = EhApplication.ehCookieStore.hasSignedIn()
private const val CHANNEL_ID = "DailyCheckNotification"
class DailyCheckWork(val context: Context, workerParams: WorkerParameters) :
Worker(context, workerParams) {
override fun doWork(): Result {
runCatching {
if (signedIn) {
val referer = EhUrl.REFERER_E
val request = EhRequestBuilder(EhUrl.HOST_E + "news.php", referer).build()
val call = EhApplication.okHttpClient.newCall(request)
call.execute().use { response ->
val responseBody = response.body
val body = responseBody.string()
EventPaneParser.parse(body)?.let { showEventPane(it) }
}
}
}.onFailure {
it.printStackTrace()
return Result.retry()
}
return Result.success()
}
@SuppressLint("MissingPermission")
private fun showEventPane(html: String) {
if (Settings.getHideHvEvents() && html.contains("You have encountered a monster!")) {
return
}
val notificationManager = NotificationManagerCompat.from(context)
val chan = NotificationChannelCompat
.Builder(CHANNEL_ID, NotificationManagerCompat.IMPORTANCE_LOW)
.setName(CHANNEL_ID)
.build()
notificationManager.createNotificationChannel(chan)
val msg = NotificationCompat.Builder(context, CHANNEL_ID)
.setSmallIcon(R.drawable.ic_launcher_monochrome)
.setContentText(Html.fromHtml(html, Html.FROM_HTML_MODE_LEGACY))
.setStyle(NotificationCompat.BigTextStyle())
.build()
runCatching {
notificationManager.notify(1, msg)
}.onFailure {
it.printStackTrace()
}
}
}
val schedHour
get() = Settings.getInt(Settings.KEY_REQUEST_NEWS_TIMER_HOUR, -1).takeUnless { it == -1 }
val schedMinute
get() = Settings.getInt(Settings.KEY_REQUEST_NEWS_TIMER_MINUTE, -1).takeUnless { it == -1 }
private val whenToWork
get() = LocalDateTime.now()
.run { withHour(schedHour ?: hour) }
.run { withMinute(schedMinute ?: minute) }
private val initialDelay
get() = Duration.between(LocalDateTime.now(), whenToWork)
private fun getDailyCheckWorkRequest(): PeriodicWorkRequest {
val constraints = Constraints.Builder()
.setRequiredNetworkType(NetworkType.CONNECTED)
.build()
return PeriodicWorkRequestBuilder<DailyCheckWork>(Duration.ofDays(1))
.setConstraints(constraints)
.setInitialDelay(initialDelay)
.build()
}
private const val workName = "DailyCheckWork"
fun updateDailyCheckWork(context: Context) {
if (Settings.getRequestNews()) {
WorkManager.getInstance(context).enqueueUniquePeriodicWork(
workName,
ExistingPeriodicWorkPolicy.UPDATE,
getDailyCheckWorkRequest()
)
} else {
WorkManager.getInstance(context).cancelUniqueWork(workName)
}
}
@@ -23,12 +23,17 @@ import androidx.appcompat.app.AppCompatDelegate
import androidx.lifecycle.lifecycleScope
import androidx.preference.ListPreference
import androidx.preference.Preference
import com.google.android.material.timepicker.MaterialTimePicker
import com.google.android.material.timepicker.TimeFormat.CLOCK_12H
import com.hippo.ehviewer.EhApplication
import com.hippo.ehviewer.R
import com.hippo.ehviewer.Settings
import com.hippo.ehviewer.client.EhCookieStore
import com.hippo.ehviewer.client.EhEngine
import com.hippo.ehviewer.client.EhTagDatabase
import com.hippo.ehviewer.dailycheck.schedHour
import com.hippo.ehviewer.dailycheck.schedMinute
import com.hippo.ehviewer.dailycheck.updateDailyCheckWork
import eu.kanade.tachiyomi.util.lang.launchNonCancellable
class EhFragment : BasePreferenceFragment() {
@@ -67,6 +72,27 @@ class EhFragment : BasePreferenceFragment() {
preferenceScreen.removePreference(preference!!)
}
}
findPreference<Preference>(Settings.KEY_REQUEST_NEWS_TIMER)!!.apply {
setOnPreferenceClickListener {
MaterialTimePicker.Builder()
.apply {
schedHour?.let { setHour(it) }
schedMinute?.let { setMinute(it) }
}
.setTimeFormat(CLOCK_12H)
.build()
.apply {
addOnPositiveButtonClickListener {
Settings.putInt(Settings.KEY_REQUEST_NEWS_TIMER_HOUR, hour)
Settings.putInt(Settings.KEY_REQUEST_NEWS_TIMER_MINUTE, minute)
updateDailyCheckWork(requireContext())
}
}
.show(childFragmentManager, null)
false
}
}
}
override fun onPreferenceChange(preference: Preference, newValue: Any): Boolean {
@@ -105,6 +131,10 @@ class EhFragment : BasePreferenceFragment() {
EhApplication.application.recreateAllActivity()
}
return true
} else if (Settings.KEY_REQUEST_NEWS == key) {
updateDailyCheckWork(requireContext())
} else if (Settings.KEY_REQUEST_NEWS_TIMER == key) {
updateDailyCheckWork(requireContext())
}
return true
}