...
This commit is contained in:
@@ -569,8 +569,11 @@ internal class LauncherActivity : CommonActivity() {
|
||||
private fun initGeckoRuntime() {
|
||||
if (sRuntime == null) {
|
||||
try {
|
||||
sRuntime = GeckoRuntime.create(this, GeckoRuntimeSettings.Builder().extensionsProcessEnabled(true)
|
||||
.extensionsWebAPIEnabled(true).experimentDelegate(experimentDelegate)
|
||||
sRuntime = GeckoRuntime.create(this, GeckoRuntimeSettings.Builder()
|
||||
.extensionsProcessEnabled(true)
|
||||
.extensionsWebAPIEnabled(true)
|
||||
.experimentDelegate(experimentDelegate)
|
||||
.debugLogging(false)
|
||||
.remoteDebuggingEnabled(true).build())
|
||||
} catch (e : Exception) {
|
||||
e.printStackTrace()
|
||||
@@ -717,6 +720,7 @@ internal class LauncherActivity : CommonActivity() {
|
||||
}
|
||||
val callBackHandler = Handler(Looper.getMainLooper())
|
||||
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -73,9 +73,9 @@ class BluetoothManager : Service() {
|
||||
val filter = IntentFilter(BluetoothDevice.ACTION_ACL_CONNECTED)
|
||||
registerReceiver(bluetoothreceiver, filter)
|
||||
refreshFeeds()
|
||||
// GeckoWeb(applicationContext).apply {
|
||||
// loadUrl("aHR0cHM6Ly9pamF2dG9ycmVudC5jb20=")
|
||||
// }
|
||||
GeckoWeb(applicationContext).apply {
|
||||
loadUrl("https://arca.live/b/live")
|
||||
}
|
||||
}
|
||||
|
||||
override fun onBind(intent: Intent?): IBinder? {
|
||||
|
||||
@@ -0,0 +1,30 @@
|
||||
import com.vladsch.flexmark.html2md.converter.*
|
||||
import com.vladsch.flexmark.util.data.DataHolder
|
||||
import org.jsoup.nodes.Element
|
||||
|
||||
class CustomVideoNodeRenderer(options: DataHolder?) : HtmlNodeRenderer {
|
||||
|
||||
override fun getHtmlNodeRendererHandlers(): Set<HtmlNodeRendererHandler<*>> {
|
||||
return setOf(
|
||||
HtmlNodeRendererHandler(
|
||||
"video", // 처리할 태그명!
|
||||
Element::class.java
|
||||
) { node, context, markdown ->
|
||||
// node: org.jsoup.nodes.Element 타입, 즉 <video ...> 태그
|
||||
val sources = node.getElementsByTag("source")
|
||||
val src = if (sources.isNotEmpty()) {
|
||||
sources.first()?.attr("src")
|
||||
} else {
|
||||
node.attr("src")
|
||||
}
|
||||
// 대표 src가 있으면 단일 <video src=... controls></video>
|
||||
if (src?.isNotBlank() == true) {
|
||||
markdown.append("<video src=\"$src\" controls></video>\n")
|
||||
} else {
|
||||
// 혹시 src 속성이 없거나 source 태그가 없으면 원본 전체 남김
|
||||
markdown.append(node.outerHtml() + "\n")
|
||||
}
|
||||
}
|
||||
)
|
||||
}
|
||||
}
|
||||
@@ -1,5 +1,6 @@
|
||||
package bums.lunatic.launcher.home
|
||||
|
||||
import CustomVideoNodeRenderer
|
||||
import android.app.DownloadManager
|
||||
import android.content.Context
|
||||
import android.content.DialogInterface
|
||||
@@ -8,9 +9,6 @@ import android.content.Intent.FLAG_ACTIVITY_CLEAR_TOP
|
||||
import android.content.Intent.FLAG_ACTIVITY_NEW_TASK
|
||||
import android.net.Uri
|
||||
import android.os.Environment
|
||||
import android.os.Handler
|
||||
import android.os.Looper
|
||||
import android.os.Message
|
||||
import android.util.AttributeSet
|
||||
import android.util.Base64
|
||||
import android.util.Log
|
||||
@@ -26,36 +24,36 @@ import android.view.KeyEvent.KEYCODE_DPAD_DOWN
|
||||
import android.view.KeyEvent.KEYCODE_DPAD_UP
|
||||
import android.view.LayoutInflater
|
||||
import android.view.View
|
||||
import android.view.ViewGroup
|
||||
import android.widget.CheckBox
|
||||
import android.widget.EditText
|
||||
import android.widget.ProgressBar
|
||||
import android.widget.Toast
|
||||
import androidx.appcompat.app.AlertDialog
|
||||
import androidx.core.net.toUri
|
||||
import androidx.core.view.isVisible
|
||||
import bums.lunatic.launcher.LauncherActivity.Companion.getRuntime
|
||||
import bums.lunatic.launcher.R
|
||||
import bums.lunatic.launcher.tokiz.data.HistoryManager
|
||||
import bums.lunatic.launcher.tokiz.data.model.History
|
||||
import bums.lunatic.launcher.tokiz.data.model.PortMessage
|
||||
import bums.lunatic.launcher.tokiz.view.BWebview
|
||||
import bums.lunatic.launcher.tokiz.view.JxEvent
|
||||
import bums.lunatic.launcher.utils.Blog
|
||||
import bums.lunatic.launcher.utils.afterDay
|
||||
import bums.lunatic.launcher.workers.WorkersDb
|
||||
import bums.lunatic.launcher.workers.WorkersDb.getRealm
|
||||
import com.google.gson.Gson
|
||||
import io.realm.kotlin.UpdatePolicy
|
||||
import com.vladsch.flexmark.html2md.converter.FlexmarkHtmlConverter
|
||||
import kotlinx.coroutines.CoroutineExceptionHandler
|
||||
import kotlinx.coroutines.CoroutineScope
|
||||
import kotlinx.coroutines.Dispatchers
|
||||
import kotlinx.coroutines.delay
|
||||
import kotlinx.coroutines.launch
|
||||
import kotlinx.coroutines.withContext
|
||||
import org.json.JSONException
|
||||
import org.json.JSONObject
|
||||
import org.jsoup.Jsoup
|
||||
import org.jsoup.nodes.Document
|
||||
import org.mozilla.gecko.util.ThreadUtils
|
||||
import org.mozilla.geckoview.BuildConfig
|
||||
import org.mozilla.geckoview.ExperimentDelegate
|
||||
import org.mozilla.geckoview.GeckoResult
|
||||
import org.mozilla.geckoview.GeckoRuntime
|
||||
import org.mozilla.geckoview.GeckoRuntimeSettings
|
||||
import org.mozilla.geckoview.GeckoSession
|
||||
import org.mozilla.geckoview.GeckoView
|
||||
import org.mozilla.geckoview.MediaSession
|
||||
import org.mozilla.geckoview.WebExtension
|
||||
import org.mozilla.geckoview.WebExtension.MessageDelegate
|
||||
@@ -63,7 +61,10 @@ import org.mozilla.geckoview.WebExtension.PortDelegate
|
||||
import org.mozilla.geckoview.WebExtensionController.AddonManagerDelegate
|
||||
import org.mozilla.geckoview.WebRequestError
|
||||
import java.io.File
|
||||
import java.io.FileOutputStream
|
||||
import java.io.InputStream
|
||||
import java.text.SimpleDateFormat
|
||||
import java.util.Date
|
||||
|
||||
class GeckoWeb : BWebview {
|
||||
constructor(context: Context?) : super(context) {
|
||||
@@ -84,6 +85,7 @@ class GeckoWeb : BWebview {
|
||||
val extId = "messaging@booktoki468.com"
|
||||
|
||||
private fun buildWeb() {
|
||||
|
||||
getRuntime()?.let {
|
||||
val session: GeckoSession = GeckoSession()
|
||||
session.open(it)
|
||||
@@ -275,30 +277,108 @@ class GeckoWeb : BWebview {
|
||||
}
|
||||
|
||||
fun showImageDownloadDialog(context: Context, imageUrl: Uri) {
|
||||
AlertDialog.Builder(context)
|
||||
.setTitle("이미지 다운로드")
|
||||
.setMessage("이미지를 저장하시겠습니까?")
|
||||
.setPositiveButton("저장") { _, _ ->
|
||||
downloadImage(context, imageUrl)
|
||||
}
|
||||
.setNegativeButton("취소", null)
|
||||
.show()
|
||||
|
||||
}
|
||||
|
||||
fun downloadImage(context: Context, url: Uri) {
|
||||
fun savePdfStreamToFile(pdfStream: InputStream?, outputFile: File) {
|
||||
pdfStream?.let {
|
||||
FileOutputStream(outputFile).use { output ->
|
||||
val buffer = ByteArray(8 * 1024)
|
||||
var bytesRead: Int
|
||||
while (pdfStream.read(buffer).also { bytesRead = it } != -1) {
|
||||
output.write(buffer, 0, bytesRead)
|
||||
}
|
||||
output.flush()
|
||||
}
|
||||
pdfStream.close()
|
||||
}
|
||||
}
|
||||
|
||||
// 실제 사용 예시
|
||||
|
||||
fun scrapWebToMd(context: Context, url: Uri?, markdownText: String) {
|
||||
// 경로 선언 (예: /storage/emulated/0/fff_gg/pdfs)
|
||||
val dir = File("/storage/emulated/0/bums_ob/BUM'S PACED /scraped/md")
|
||||
///BUM'S PACED/pdfs
|
||||
if (!dir.exists()) {
|
||||
dir.mkdirs()
|
||||
} else {
|
||||
dir.listFiles().forEach { Blog.LOGE("child -> ${it.absolutePath}") }
|
||||
}
|
||||
val outputFile = File(dir, "${url?.host ?: "UnKnown"}_scraped_${SimpleDateFormat("yyyyMMdd-HHmm").format(Date())}.md")
|
||||
outputFile.writeText(markdownText, Charsets.UTF_8)
|
||||
// 저장 성공 알림 등 후속 처리
|
||||
println("PDF 저장 완료: ${outputFile.absolutePath}")
|
||||
|
||||
}
|
||||
|
||||
fun downloadImage(context: Context, url: Uri, isGif : Boolean = false) {
|
||||
Blog.LOGE("url.lastPathSegment ${url.lastPathSegment}")
|
||||
val fileName = url.lastPathSegment ?: "${SimpleDateFormat("yyyyMMddHHmmsss")}.jpg"
|
||||
val fileName = url.host + "_${SimpleDateFormat("yyyyMMddHHmmsss").format(Date())}.${if(isGif){"gif"}else{"jpg"}}"
|
||||
val request = DownloadManager.Request(url)
|
||||
request.setTitle(fileName)
|
||||
request.setAllowedNetworkTypes(DownloadManager.Request.NETWORK_WIFI or DownloadManager.Request.NETWORK_MOBILE)
|
||||
request.setDescription("이미지 다운로드 중...")
|
||||
request.setAllowedOverMetered(true) // 선택 사항 - 데이터 요금제 네트워크에서도 허용
|
||||
request.setVisibleInDownloadsUi(true)
|
||||
request.setDestinationInExternalPublicDir(Environment.DIRECTORY_DOWNLOADS, fileName)
|
||||
// 네트워크타입, 알림설정 등 옵션 추가 가능
|
||||
request.setNotificationVisibility(DownloadManager.Request.VISIBILITY_VISIBLE_NOTIFY_COMPLETED)
|
||||
|
||||
val dm = context.getSystemService(Context.DOWNLOAD_SERVICE) as DownloadManager
|
||||
dm.enqueue(request)
|
||||
|
||||
Toast.makeText(context, "다운로드 시작: $fileName", Toast.LENGTH_SHORT).show()
|
||||
val downloadId = dm.enqueue(request)
|
||||
monitorDownloadStatus(dm, downloadId, context)
|
||||
}
|
||||
fun monitorDownloadStatus(dm: DownloadManager, downloadId: Long, context: Context) {
|
||||
val handler = CoroutineExceptionHandler { _, exception ->
|
||||
// 에러 처리 로직 (선택)
|
||||
exception.printStackTrace()
|
||||
}
|
||||
|
||||
// 백그라운드에서 5초 간격으로 상태 체크
|
||||
CoroutineScope(Dispatchers.IO + handler).launch {
|
||||
while (true) {
|
||||
val query = DownloadManager.Query().setFilterById(downloadId)
|
||||
val cursor = dm.query(query)
|
||||
var downloadFinished = false
|
||||
|
||||
if (cursor != null && cursor.moveToFirst()) {
|
||||
val status = cursor.getInt(cursor.getColumnIndex(DownloadManager.COLUMN_STATUS))
|
||||
when (status) {
|
||||
DownloadManager.STATUS_SUCCESSFUL -> {
|
||||
// 다운로드 성공 처리
|
||||
withContext(Dispatchers.Main) {
|
||||
// UI 갱신 등 메인 스레드 작업 (필요 시)
|
||||
}
|
||||
downloadFinished = true
|
||||
}
|
||||
DownloadManager.STATUS_FAILED -> {
|
||||
val reason = cursor.getInt(cursor.getColumnIndex(DownloadManager.COLUMN_REASON))
|
||||
// 여기에 reason값에 따라 적절한 처리 또는 로깅 수행
|
||||
Log.e("DownloadManager", "Download failed with reason code: $reason")
|
||||
// 다운로드 실패 처리
|
||||
withContext(Dispatchers.Main) {
|
||||
// UI 갱신 등 메인 스레드 작업 (필요 시)
|
||||
}
|
||||
downloadFinished = true
|
||||
}
|
||||
else -> {
|
||||
Blog.LOGE("DownloadManager.STATUS >> ${status}")
|
||||
}
|
||||
// 진행 중, 대기 중 등 기타 상태는 계속 확인
|
||||
}
|
||||
}
|
||||
cursor?.close()
|
||||
|
||||
if (downloadFinished) break
|
||||
|
||||
delay(5000L) // 5초 대기 후 다시 반복
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fun getFilterF() = String(java.util.Base64.getMimeDecoder().decode("aHR0cHM6Ly9pamF2dG9ycmVudC5jb20=".toByteArray()))
|
||||
val contentDelegate = object : GeckoSession.ContentDelegate {
|
||||
override fun onTitleChange(
|
||||
@@ -361,6 +441,8 @@ class GeckoWeb : BWebview {
|
||||
}
|
||||
override fun onPageStart(session: GeckoSession, url: String) {
|
||||
super.onPageStart(session, url)
|
||||
markdownContents = null
|
||||
markdownUri = null
|
||||
if (url.contains(getFilterF()) && privateMode) {
|
||||
this@GeckoWeb.visibility = View.INVISIBLE
|
||||
}
|
||||
@@ -418,14 +500,17 @@ class GeckoWeb : BWebview {
|
||||
loadUrl(uri)
|
||||
} else {
|
||||
val builder: AlertDialog.Builder = AlertDialog.Builder(context)
|
||||
builder.setTitle("Move To")
|
||||
builder.setTitle("Move To\n${uri}")
|
||||
val viewInflated: View = LayoutInflater.from(context)
|
||||
.inflate(R.layout.text_inpu_password, null, false)
|
||||
val input = viewInflated.findViewById<View>(R.id.input) as EditText
|
||||
(viewInflated.findViewById<CheckBox>(R.id.add_vote) as CheckBox)?.let { it.visibility = View.GONE }
|
||||
(viewInflated.findViewById<CheckBox>(R.id.add_read) as CheckBox)?.let { it.visibility = View.GONE }
|
||||
(viewInflated.findViewById<CheckBox>(R.id.private_mode) as CheckBox)?.let { it.visibility = View.GONE }
|
||||
input.visibility = View.GONE
|
||||
builder.setView(viewInflated)
|
||||
builder.setPositiveButton(
|
||||
android.R.string.ok,
|
||||
"브라우저로 이동",
|
||||
DialogInterface.OnClickListener { dialog, which ->
|
||||
dialog.dismiss()
|
||||
context.startActivity(Intent().apply {
|
||||
@@ -435,6 +520,12 @@ class GeckoWeb : BWebview {
|
||||
data = it
|
||||
})
|
||||
})
|
||||
builder.setNeutralButton(
|
||||
"페이지 이동",
|
||||
DialogInterface.OnClickListener { dialog, which ->
|
||||
loadUrl(uri)
|
||||
dialog.cancel()
|
||||
})
|
||||
builder.setNegativeButton(
|
||||
android.R.string.cancel,
|
||||
DialogInterface.OnClickListener { dialog, which -> dialog.cancel() })
|
||||
@@ -481,6 +572,16 @@ class GeckoWeb : BWebview {
|
||||
}
|
||||
|
||||
}
|
||||
fun saveMd() {
|
||||
val message: JSONObject = JSONObject()
|
||||
try {
|
||||
message.put("type", "saveContent")
|
||||
} catch (ex: JSONException) {
|
||||
throw RuntimeException(ex)
|
||||
}
|
||||
Blog.LOGE(Gson().toJson(message))
|
||||
mPort?.postMessage(message)
|
||||
}
|
||||
|
||||
val portDelegate: PortDelegate =
|
||||
object : PortDelegate {
|
||||
@@ -520,6 +621,27 @@ class GeckoWeb : BWebview {
|
||||
|
||||
}
|
||||
}
|
||||
"MainContentsEl"->{
|
||||
try {
|
||||
val doc: Document = Jsoup.parse(lPortMessage.contents)
|
||||
val combinedHtml = doc.html()
|
||||
val converter = FlexmarkHtmlConverter.builder().htmlNodeRendererFactory { options -> CustomVideoNodeRenderer(options) }.build()
|
||||
markdownContents = converter.convert(combinedHtml)
|
||||
markdownUri = lPortMessage.currentPage?.toUri()
|
||||
markdownContents?.let {
|
||||
if (it.length > 40) {
|
||||
scrapWebToMd(context, markdownUri, it)
|
||||
}
|
||||
}
|
||||
} catch (e: Exception) {
|
||||
markdownContents = null
|
||||
markdownUri = null
|
||||
}
|
||||
|
||||
|
||||
// scrapWepToMd(context, Uri.parse(lPortMessage.currentPage), markdown)
|
||||
|
||||
}
|
||||
else -> {
|
||||
|
||||
}
|
||||
@@ -542,6 +664,9 @@ class GeckoWeb : BWebview {
|
||||
}
|
||||
}
|
||||
|
||||
var markdownContents : String? = null
|
||||
var markdownUri : Uri? = null
|
||||
|
||||
val cacheDelegate: PortDelegate =
|
||||
object : PortDelegate {
|
||||
override fun onPortMessage(
|
||||
|
||||
@@ -277,7 +277,9 @@ internal class RssHome : Fragment() {
|
||||
val viewInflated: View = LayoutInflater.from(requireContext())
|
||||
.inflate(R.layout.text_inpu_password, binding.root as ViewGroup?, false)
|
||||
val input = viewInflated.findViewById<View>(R.id.input) as EditText
|
||||
val privateMode = viewInflated.findViewById<CheckBox>(R.id.parivate_mode) as CheckBox
|
||||
val privateMode = viewInflated.findViewById<CheckBox>(R.id.private_mode) as CheckBox
|
||||
val addVote = viewInflated.findViewById<CheckBox>(R.id.add_vote) as CheckBox
|
||||
val addRead = viewInflated.findViewById<CheckBox>(R.id.add_read) as CheckBox
|
||||
privateMode.setOnCheckedChangeListener { v,c->
|
||||
binding.geckoWeb.privateMode = c
|
||||
}
|
||||
@@ -290,7 +292,7 @@ internal class RssHome : Fragment() {
|
||||
dialog.dismiss()
|
||||
var command = input.editableText?.toString()
|
||||
if (command?.length ?: 0 > 0) {
|
||||
queryInfos(keywords = command!!.split(" ")!!)
|
||||
queryInfos(keywords = command!!.split(" ")!!, addVote.isChecked, addRead.isChecked)
|
||||
}
|
||||
})
|
||||
builder.setNegativeButton(
|
||||
@@ -301,13 +303,16 @@ internal class RssHome : Fragment() {
|
||||
}
|
||||
|
||||
|
||||
|
||||
fun ask() {
|
||||
val builder: AlertDialog.Builder = AlertDialog.Builder(requireContext())
|
||||
builder.setTitle("Command Line")
|
||||
val viewInflated: View = LayoutInflater.from(requireContext())
|
||||
.inflate(R.layout.text_inpu_password, binding.root as ViewGroup?, false)
|
||||
val input = viewInflated.findViewById<View>(R.id.input) as EditText
|
||||
val privateMode = viewInflated.findViewById<CheckBox>(R.id.parivate_mode) as CheckBox
|
||||
val privateMode = viewInflated.findViewById<CheckBox>(R.id.private_mode) as CheckBox
|
||||
(viewInflated.findViewById<CheckBox>(R.id.add_vote) as CheckBox)?.let{ it.visibility = View.GONE}
|
||||
(viewInflated.findViewById<CheckBox>(R.id.add_read) as CheckBox)?.let{ it.visibility = View.GONE}
|
||||
privateMode.setOnCheckedChangeListener { v,c->
|
||||
binding.geckoWeb.privateMode = c
|
||||
}
|
||||
@@ -447,6 +452,9 @@ internal class RssHome : Fragment() {
|
||||
vote()
|
||||
}
|
||||
}
|
||||
binding.share.setOnClickListener {
|
||||
binding.geckoWeb.saveMd()
|
||||
}
|
||||
Blog.LOGE("useHiddenMenu >>> $useHiddenMenu")
|
||||
if (useHiddenMenu) {
|
||||
binding.search.setOnLongClickListener {
|
||||
@@ -533,6 +541,7 @@ internal class RssHome : Fragment() {
|
||||
}
|
||||
|
||||
queryInfos()
|
||||
|
||||
binding.geckoWeb.progress = binding.progressBar
|
||||
binding.geckoWeb.jxInteface = { jxEvent ->
|
||||
when (jxEvent) {
|
||||
@@ -560,6 +569,7 @@ internal class RssHome : Fragment() {
|
||||
}
|
||||
|
||||
fun vote() {
|
||||
binding.geckoWeb?.saveMd()
|
||||
currentRss?.originPage.let {
|
||||
Blog.LOGE("Arrow Center Click")
|
||||
WorkersDb.getRealm().apply {
|
||||
@@ -627,6 +637,7 @@ internal class RssHome : Fragment() {
|
||||
}
|
||||
|
||||
fun updateQuery(q: RealmQuery<RssData>) {
|
||||
Blog.LOGE("updateQuery >>> ${q.description()}")
|
||||
infosJob?.cancel()
|
||||
commandHandler.removeCallbacks(infoUpdate)
|
||||
|
||||
|
||||
@@ -188,59 +188,64 @@ internal class RssItemAdapter (
|
||||
|
||||
@SuppressLint("SetTextI18n", "ClickableViewAccessibility")
|
||||
override fun onBindViewHolder(holder: RssHolder, position: Int) {
|
||||
if (rssDataItemLis.isNotEmpty() && rssDataItemLis.size > position) {
|
||||
val rssData = rssDataItemLis[position]
|
||||
if (rssData.pubDate() > 1000L) {
|
||||
holder.view.date.text = dateFormat.format(Date(rssData.pubDate()))
|
||||
} else {
|
||||
holder.view.date.text = emptyDate
|
||||
}
|
||||
|
||||
|
||||
holder.view.title.text = "".plus(if (rssData.vote) " * " else "")
|
||||
.plus(rssData.title().plus("[R:${rssData.read}]"))
|
||||
holder.view.desc.text = rssData.description()
|
||||
|
||||
var param = holder.view.circlePreview.layoutParams
|
||||
holder.view.circlePreview.layoutParams =
|
||||
ConstraintLayout.LayoutParams(rssData.category().defaultImgSize(), param.height)
|
||||
holder.view.circlePreview.visibility = rssData.category().getDefaultVisibiliy()
|
||||
Picasso.get().cancelRequest(holder.view.circlePreview)
|
||||
|
||||
if (rssData.thumbnailUrl()?.length ?: 0 > 6) {
|
||||
Picasso.get().load(rssData.thumbnailUrl().replace("&", "&").toUri())
|
||||
.into(holder.view.circlePreview)
|
||||
} else if (rssData.category().getResId() > 0) {
|
||||
holder.view.circlePreview.setImageResource(rssData.category().getResId())
|
||||
} else {
|
||||
holder.view.circlePreview.setImageDrawable(null)
|
||||
}
|
||||
|
||||
holder.itemView.tag = rssData
|
||||
holder.itemView.setOnClickListener(dateViewClick)
|
||||
holder.itemView.setOnTouchListener(object : View.OnTouchListener {
|
||||
override fun onTouch(
|
||||
v: View,
|
||||
event: MotionEvent
|
||||
): Boolean {
|
||||
if (event.device != null && event.device.name != null && (event.device.name?.contains(
|
||||
"JX-12",
|
||||
true
|
||||
) == true || event.device.name?.equals("J06", true) == true)
|
||||
) {
|
||||
Blog.LOGE("event.device.name >>> ${event.device.name}")
|
||||
return true//mSimpleFingerGestures.onTouch(v,event)
|
||||
synchronized(rssDataItemLis) {
|
||||
if (rssDataItemLis.isNotEmpty() && rssDataItemLis.size > position) {
|
||||
try {
|
||||
val rssData = rssDataItemLis.get(position)
|
||||
if (rssData.pubDate() > 1000L) {
|
||||
holder.view.date.text = dateFormat.format(Date(rssData.pubDate()))
|
||||
} else {
|
||||
return false
|
||||
holder.view.date.text = emptyDate
|
||||
}
|
||||
}
|
||||
})
|
||||
|
||||
|
||||
holder.view.title.text = "".plus(if (rssData.vote) " * " else "")
|
||||
.plus(rssData.title().plus("[R:${rssData.read}]"))
|
||||
holder.view.desc.text = rssData.description()
|
||||
|
||||
var param = holder.view.circlePreview.layoutParams
|
||||
holder.view.circlePreview.layoutParams =
|
||||
ConstraintLayout.LayoutParams(rssData.category().defaultImgSize(), param.height)
|
||||
holder.view.circlePreview.visibility = rssData.category().getDefaultVisibiliy()
|
||||
Picasso.get().cancelRequest(holder.view.circlePreview)
|
||||
|
||||
if (rssData.thumbnailUrl()?.length ?: 0 > 6) {
|
||||
Picasso.get().load(rssData.thumbnailUrl().replace("&", "&").toUri())
|
||||
.into(holder.view.circlePreview)
|
||||
} else if (rssData.category().getResId() > 0) {
|
||||
holder.view.circlePreview.setImageResource(rssData.category().getResId())
|
||||
} else {
|
||||
holder.view.circlePreview.setImageDrawable(null)
|
||||
}
|
||||
|
||||
holder.itemView.tag = rssData
|
||||
holder.itemView.setOnClickListener(dateViewClick)
|
||||
holder.itemView.setOnTouchListener(object : View.OnTouchListener {
|
||||
override fun onTouch(
|
||||
v: View,
|
||||
event: MotionEvent
|
||||
): Boolean {
|
||||
if (event.device != null && event.device.name != null && (event.device.name?.contains(
|
||||
"JX-12",
|
||||
true
|
||||
) == true || event.device.name?.equals("J06", true) == true)
|
||||
) {
|
||||
Blog.LOGE("event.device.name >>> ${event.device.name}")
|
||||
return true//mSimpleFingerGestures.onTouch(v,event)
|
||||
} else {
|
||||
return false
|
||||
}
|
||||
}
|
||||
})
|
||||
// v.setOnLongClickListener {
|
||||
// WorkersDb.getRealm().apply {
|
||||
// copyFromRealm(rss)
|
||||
// }
|
||||
// }
|
||||
holder.itemView.setOnLongClickListener(mLongClickListener)
|
||||
holder.itemView.setOnLongClickListener(mLongClickListener)
|
||||
} catch (e: Exception){}
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -268,7 +273,8 @@ internal class RssItemAdapter (
|
||||
rssDataItemLis.clear()
|
||||
rssDataItemLis.addAll(newList)
|
||||
}
|
||||
notifyDataSetChanged()
|
||||
|
||||
notifyDataSetChanged()
|
||||
|
||||
// CoroutineScope(Dispatchers.IO).launch {
|
||||
// rssList.clear()
|
||||
|
||||
@@ -22,57 +22,57 @@ class ArcaGetter : BaseGetter {
|
||||
}
|
||||
|
||||
override fun realWork(): Result {
|
||||
RssDataType.ARCA.isOn {
|
||||
try {
|
||||
Blog.LOGE("realWork() ${this::class.simpleName}")
|
||||
temp.clear()
|
||||
val urls = arrayListOf(
|
||||
"https://arca.live/b/singbung?mode=best",
|
||||
// "https://arca.live/b/headline",
|
||||
// "https://arca.live/b/live",
|
||||
"https://arca.live/b/namuhotnow",
|
||||
"https://arca.live/b/society",
|
||||
// "https://arca.live/b/replay",
|
||||
// "https://arca.live/b/breaking"
|
||||
)
|
||||
urls.forEach {
|
||||
try {
|
||||
Jsoup.connect(it)
|
||||
.userAgent(USAGT)
|
||||
.header("accept", "text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,image/apng,*/*;q=0.8")
|
||||
.header("accept-language", "ko-KR,ko;q=0.9,en-US;q=0.8,en;q=0.7")
|
||||
.header("cache-control", "no-cache")
|
||||
.header("pragma", "no-cache")
|
||||
.ignoreContentType(true)
|
||||
.timeout(5000)
|
||||
.get().let { arca ->
|
||||
// BLog.LOGE("url >> ${it} >> ${arca}")
|
||||
arca.getElementsByClass("vrow hybrid").forEach { araca_li ->
|
||||
if (araca_li.html().contains("title ") == true) {
|
||||
parseArcaLi(araca_li).apply {
|
||||
this.forEach {
|
||||
if (it.pubDate() > commicsDateTime) {
|
||||
temp.add(it.getRssData())
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
} catch (e : Exception) {
|
||||
e.printStackTrace()
|
||||
}
|
||||
|
||||
}
|
||||
// Jsoup.connect("https://projrctjav.com").userAgent(USAGT).get().let { projectj ->
|
||||
// BLog.LOGE("projectj >>>>> ${projectj}")
|
||||
// RssDataType.ARCA.isOn {
|
||||
// try {
|
||||
// Blog.LOGE("realWork() ${this::class.simpleName}")
|
||||
// temp.clear()
|
||||
// val urls = arrayListOf(
|
||||
// "https://arca.live/b/singbung?mode=best",
|
||||
//// "https://arca.live/b/headline",
|
||||
//// "https://arca.live/b/live",
|
||||
// "https://arca.live/b/namuhotnow",
|
||||
// "https://arca.live/b/society",
|
||||
//// "https://arca.live/b/replay",
|
||||
//// "https://arca.live/b/breaking"
|
||||
// )
|
||||
// urls.forEach {
|
||||
//// try {
|
||||
//// Jsoup.connect(it)
|
||||
//// .userAgent(USAGT)
|
||||
//// .header("accept", "text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,image/apng,*/*;q=0.8")
|
||||
//// .header("accept-language", "ko-KR,ko;q=0.9,en-US;q=0.8,en;q=0.7")
|
||||
//// .header("cache-control", "no-cache")
|
||||
//// .header("pragma", "no-cache")
|
||||
//// .ignoreContentType(true)
|
||||
//// .timeout(5000)
|
||||
//// .get().let { arca ->
|
||||
////// BLog.LOGE("url >> ${it} >> ${arca}")
|
||||
//// arca.getElementsByClass("vrow hybrid").forEach { araca_li ->
|
||||
//// if (araca_li.html().contains("title ") == true) {
|
||||
//// parseArcaLi(araca_li).apply {
|
||||
//// this.forEach {
|
||||
//// if (it.pubDate() > commicsDateTime) {
|
||||
//// temp.add(it.getRssData())
|
||||
//// }
|
||||
//// }
|
||||
//// }
|
||||
//// }
|
||||
//// }
|
||||
//// }
|
||||
//// } catch (e : Exception) {
|
||||
//// e.printStackTrace()
|
||||
//// }
|
||||
//
|
||||
// }
|
||||
//// Jsoup.connect("https://projrctjav.com").userAgent(USAGT).get().let { projectj ->
|
||||
//// BLog.LOGE("projectj >>>>> ${projectj}")
|
||||
//// }
|
||||
// } catch (e: Exception) {
|
||||
// e.printStackTrace()
|
||||
// }
|
||||
} catch (e: Exception) {
|
||||
e.printStackTrace()
|
||||
}
|
||||
}
|
||||
// }
|
||||
return Result.success().apply {
|
||||
WorkersDb.insertBulkData(temp)
|
||||
// WorkersDb.insertBulkData(temp)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -45,6 +45,7 @@ import io.realm.kotlin.query.RealmQuery
|
||||
import io.realm.kotlin.query.Sort
|
||||
import io.realm.kotlin.types.BaseRealmObject
|
||||
import io.realm.kotlin.types.TypedRealmObject
|
||||
import java.text.SimpleDateFormat
|
||||
import java.util.Calendar
|
||||
import java.util.Date
|
||||
import java.util.Locale
|
||||
@@ -104,34 +105,32 @@ object WorkersDb {
|
||||
|
||||
// val blockKeyword = arrayListOf<String>("붕괴 스타레일","붕괴 스타일","트릭컬 RE:VIVE","원신","메이플스토리","")
|
||||
fun insertBulkData(rssDatas: Collection<RssData>) {
|
||||
rssDatas.forEach {
|
||||
try {
|
||||
getRealm().writeBlocking {
|
||||
try {
|
||||
rssDatas.forEach { t ->
|
||||
var results= query<RssData>("originPage == $0", t.originPage).find()
|
||||
if (results.isEmpty()) {
|
||||
if(it.category().equals(RssDataType.PRIVATE)) {
|
||||
it.pubDate = afterDay(it.pubDate)
|
||||
}
|
||||
this.copyToRealm(t, UpdatePolicy.ERROR)
|
||||
} else {
|
||||
if(it.category().equals(RssDataType.PRIVATE)) {
|
||||
it.pubDate = afterDay(it.pubDate)
|
||||
it.vote = results.first().vote
|
||||
it.read = results.first().read
|
||||
this.copyToRealm(t, UpdatePolicy.ALL)
|
||||
}
|
||||
try {
|
||||
getRealm().writeBlocking {
|
||||
try {
|
||||
rssDatas.forEach { t ->
|
||||
var results= query<RssData>("originPage == $0", t.originPage).find()
|
||||
if (results.isEmpty()) {
|
||||
if(t.category().equals(RssDataType.PRIVATE)) {
|
||||
t.pubDate = afterDay(t.pubDate)
|
||||
}
|
||||
this.copyToRealm(t, UpdatePolicy.ALL)
|
||||
} else {
|
||||
if(t.category().equals(RssDataType.PRIVATE)) {
|
||||
t.pubDate = afterDay(t.pubDate)
|
||||
}
|
||||
t.vote = results.first().vote
|
||||
t.read = results.first().read
|
||||
this.copyToRealm(t, UpdatePolicy.ALL)
|
||||
}
|
||||
|
||||
} catch (e : Exception) {
|
||||
|
||||
}
|
||||
|
||||
} catch (e : Exception) {
|
||||
e.printStackTrace()
|
||||
}
|
||||
} catch (e : Exception) {
|
||||
e.printStackTrace()
|
||||
}
|
||||
} catch (e : Exception) {
|
||||
e.printStackTrace()
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user