Merge branch 'main' of https://dev.lunaticbum.kr/lun_admin/android_multiviewwer
# Conflicts: # app/src/main/kotlin/bums/lunatic/launcher/home/RssHome.kt # app/src/main/kotlin/bums/lunatic/launcher/utils/JsoupUtils.kt ...
This commit is contained in:
commit
f56c43d82b
@ -5,6 +5,7 @@ plugins {
|
|||||||
id ("com.android.application")
|
id ("com.android.application")
|
||||||
id ("kotlin-android")
|
id ("kotlin-android")
|
||||||
id ("io.realm.kotlin")
|
id ("io.realm.kotlin")
|
||||||
|
id ("kotlin-kapt")
|
||||||
}
|
}
|
||||||
|
|
||||||
android {
|
android {
|
||||||
@ -110,6 +111,7 @@ dependencies {
|
|||||||
implementation("com.github.delight-im:Android-AdvancedWebView:v3.2.1")
|
implementation("com.github.delight-im:Android-AdvancedWebView:v3.2.1")
|
||||||
implementation(project(":library"))
|
implementation(project(":library"))
|
||||||
implementation(project(":utils"))
|
implementation(project(":utils"))
|
||||||
|
implementation( "com.github.bumptech.glide:glide:4.11.0")
|
||||||
// implementation("org.mozilla.geckoview:geckoview:139.0.20250523173407")
|
// implementation("org.mozilla.geckoview:geckoview:139.0.20250523173407")
|
||||||
// https://mvnrepository.com/artifact/org.mozilla.geckoview/geckoview
|
// https://mvnrepository.com/artifact/org.mozilla.geckoview/geckoview
|
||||||
implementation("org.mozilla.geckoview:geckoview:139.0.20250523173407")
|
implementation("org.mozilla.geckoview:geckoview:139.0.20250523173407")
|
||||||
|
|||||||
@ -1,40 +1,65 @@
|
|||||||
|
//const port = browser.runtime.connectNative("browser");
|
||||||
browser.webRequest.onHeadersReceived.addListener(
|
//// 모든 요청을 가로챔
|
||||||
function(details) {
|
//browser.webRequest.onCompleted.addListener(async (details) => {
|
||||||
let headers = details.responseHeaders || [];
|
// // 원래 요청 URL
|
||||||
// Cache-Control 헤더가 없거나 no-store, no-cache 등일 때 수정
|
// const url = details.url;
|
||||||
let found = false;
|
// try {
|
||||||
for (let header of headers) {
|
// // 실제 데이터 fetch (credentials, 쿠키 등 필요시 옵션 맞춤)
|
||||||
if (header.name.toLowerCase() === "cache-control") {
|
// const res = await fetch(url, {credentials: "include"});
|
||||||
header.value = "public, max-age=31536000"; // 1년 캐시
|
// const blob = await res.blob();
|
||||||
found = true;
|
// // 데이터 -> ArrayBuffer
|
||||||
}
|
// const arrayBuffer = await blob.arrayBuffer();
|
||||||
}
|
// // base64로 변환
|
||||||
if (!found) {
|
// const base64 = btoa(String.fromCharCode(...new Uint8Array(arrayBuffer)));
|
||||||
headers.push({name: "Cache-Control", value: "public, max-age=31536000"});
|
// // 네이티브 앱에게 전달
|
||||||
}
|
// port.postMessage(JSON.stringify({type:"CACAHE",msg:msg , url: url, data: base64}));
|
||||||
return {responseHeaders: headers};
|
//// browser.runtime.sendNativeMessage(
|
||||||
},
|
//// "browser", // 등록한 네이티브 앱 id
|
||||||
{urls: ["*://*/*.gif"], types: ["image"]},
|
//// { url: url, data: base64 }
|
||||||
["blocking", "responseHeaders"]
|
//// );
|
||||||
);
|
// } catch(e) {
|
||||||
//const originalLog = console.log;
|
// // 에러 처리
|
||||||
//console.log = function(...args) {
|
// console.error(e);
|
||||||
// // 메시지 가공 또는 네이티브로 전달
|
|
||||||
// originalLog.apply(console, args);
|
|
||||||
// browser.runtime.sendNativeMessage("browser", args);
|
|
||||||
//};
|
|
||||||
|
|
||||||
browser.webRequest.onBeforeRequest.addListener(
|
|
||||||
function(details) {
|
|
||||||
return { cancel: true };
|
|
||||||
},
|
|
||||||
{ urls: ["*://*/*.gif"], types: ["image"] },
|
|
||||||
["blocking"]
|
|
||||||
);
|
|
||||||
//window.addEventListener('error', function(event) {
|
|
||||||
// if (event.message && event.message.includes('No impl for message: MozAfterPaint')) {
|
|
||||||
// // 앱으로 오류 신호 전달
|
|
||||||
// browser.runtime.sendMessage({ type: 'RELOAD_REQUEST' });
|
|
||||||
// }
|
// }
|
||||||
//});
|
//}, {urls: ["<all_urls>"]});
|
||||||
|
//
|
||||||
|
////
|
||||||
|
////browser.webRequest.onHeadersReceived.addListener(
|
||||||
|
//// function(details) {
|
||||||
|
//// let headers = details.responseHeaders || [];
|
||||||
|
//// // Cache-Control 헤더가 없거나 no-store, no-cache 등일 때 수정
|
||||||
|
//// let found = false;
|
||||||
|
//// for (let header of headers) {
|
||||||
|
//// if (header.name.toLowerCase() === "cache-control") {
|
||||||
|
//// header.value = "public, max-age=31536000"; // 1년 캐시
|
||||||
|
//// found = true;
|
||||||
|
//// }
|
||||||
|
//// }
|
||||||
|
//// if (!found) {
|
||||||
|
//// headers.push({name: "Cache-Control", value: "public, max-age=31536000"});
|
||||||
|
//// }
|
||||||
|
//// return {responseHeaders: headers};
|
||||||
|
//// },
|
||||||
|
//// {urls: ["*://*/*.gif"], types: ["image"]},
|
||||||
|
//// ["blocking", "responseHeaders"]
|
||||||
|
////);
|
||||||
|
//////const originalLog = console.log;
|
||||||
|
//////console.log = function(...args) {
|
||||||
|
////// // 메시지 가공 또는 네이티브로 전달
|
||||||
|
////// originalLog.apply(console, args);
|
||||||
|
////// browser.runtime.sendNativeMessage("browser", args);
|
||||||
|
//////};
|
||||||
|
////
|
||||||
|
////browser.webRequest.onBeforeRequest.addListener(
|
||||||
|
//// function(details) {
|
||||||
|
//// return { cancel: true };
|
||||||
|
//// },
|
||||||
|
//// { urls: ["*://*/*.gif"], types: ["image"] },
|
||||||
|
//// ["blocking"]
|
||||||
|
////);
|
||||||
|
////window.addEventListener('error', function(event) {
|
||||||
|
//// if (event.message && event.message.includes('No impl for message: MozAfterPaint')) {
|
||||||
|
//// // 앱으로 오류 신호 전달
|
||||||
|
//// browser.runtime.sendMessage({ type: 'RELOAD_REQUEST' });
|
||||||
|
//// }
|
||||||
|
////});
|
||||||
File diff suppressed because one or more lines are too long
@ -22,7 +22,6 @@
|
|||||||
"nativeMessagingFromContent",
|
"nativeMessagingFromContent",
|
||||||
"geckoViewAddons",
|
"geckoViewAddons",
|
||||||
"webRequest",
|
"webRequest",
|
||||||
"webRequestBlocking",
|
"webRequestBlocking"
|
||||||
"*://*/*.gif"
|
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
|
|||||||
@ -1,4 +1,4 @@
|
|||||||
|
const list = ["?page=2","?page=3","?page=4","?page=5","?page=6"];
|
||||||
const port = browser.runtime.connectNative("browser");
|
const port = browser.runtime.connectNative("browser");
|
||||||
port.onMessage.addListener(response => {
|
port.onMessage.addListener(response => {
|
||||||
var type= response["type"];
|
var type= response["type"];
|
||||||
@ -285,5 +285,126 @@ if (port) {
|
|||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (document.querySelectorAll('[class^="col-md-4 mb-4 video-item"]').length > 1) {
|
||||||
|
var datas = []
|
||||||
|
document.querySelectorAll('[class^="col-md-4 mb-4 video-item"]').forEach(function (e) {
|
||||||
|
var date = 0
|
||||||
|
try {
|
||||||
|
const dateString = e.querySelector('[class^="mb-2"]').querySelector("a").textContent.trim();
|
||||||
|
|
||||||
|
const [day, month, year] = dateString.split("/").map(Number);
|
||||||
|
date = new Date(year, month - 1, day).getTime();
|
||||||
|
}catch (e) {
|
||||||
|
|
||||||
|
}
|
||||||
|
var actor = ""
|
||||||
|
try {
|
||||||
|
actor = e.querySelector('[class^="mb-1"]').getAttribute("alt").trim()
|
||||||
|
}catch (e) {
|
||||||
|
|
||||||
|
}
|
||||||
|
var desc = ""
|
||||||
|
try {
|
||||||
|
e.querySelectorAll('[class^="badge badge-"]').forEach(function (e) {
|
||||||
|
try {
|
||||||
|
if (Number(e.textContent) > 0) {
|
||||||
|
|
||||||
|
}else {
|
||||||
|
if (desc.length > 0) {
|
||||||
|
desc += ","
|
||||||
|
}
|
||||||
|
desc += e.textContent.trim()
|
||||||
|
}
|
||||||
|
}catch (e) {}
|
||||||
|
}
|
||||||
|
)
|
||||||
|
}catch (e) {
|
||||||
|
|
||||||
|
}
|
||||||
|
var thumb = ""
|
||||||
|
try {
|
||||||
|
thumb = e.querySelector("td").querySelector("a").getAttribute('data-link')
|
||||||
|
}catch (e) {
|
||||||
|
|
||||||
|
}
|
||||||
|
var magnet = ""
|
||||||
|
try {
|
||||||
|
e.querySelectorAll("td").forEach(function (e) {
|
||||||
|
e.querySelectorAll("a").forEach(function (e) {
|
||||||
|
if(e.getAttribute("href").startsWith("magnet")) {
|
||||||
|
magnet = e.getAttribute("href").replaceAll("&", "&");
|
||||||
|
}
|
||||||
|
})
|
||||||
|
})
|
||||||
|
}catch (e) {
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
var title = "";
|
||||||
|
try {
|
||||||
|
title = e.querySelector(".name").querySelector("a").querySelector("span").textContent.trim();
|
||||||
|
}catch (e) {
|
||||||
|
|
||||||
|
}
|
||||||
|
var originPage = ""
|
||||||
|
try {
|
||||||
|
|
||||||
|
originPage = location.protocol + "//" + location.hostname + e.querySelector(".name").querySelector("a").getAttribute("href");
|
||||||
|
}catch (e) {
|
||||||
|
|
||||||
|
}
|
||||||
|
var screenshots = ""
|
||||||
|
try {
|
||||||
|
e.querySelectorAll("a").forEach(function (e) {
|
||||||
|
if(e.getAttribute("href").search("screenshots") > -1) {
|
||||||
|
screenshots = e.getAttribute("href");
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}catch (e) {
|
||||||
|
|
||||||
|
}
|
||||||
|
datas.push({
|
||||||
|
"title" : title,
|
||||||
|
"description" : desc,
|
||||||
|
"originPage" : originPage,
|
||||||
|
"magnet" : magnet,
|
||||||
|
"thumbnail" : thumb,
|
||||||
|
"pubDate" : date,
|
||||||
|
"screenshots" : screenshots,
|
||||||
|
"chosung" : "",
|
||||||
|
"category" : "PRIVATE"
|
||||||
|
});
|
||||||
|
})
|
||||||
|
sendMessage(
|
||||||
|
{
|
||||||
|
type: "PRIVATES",
|
||||||
|
privates: datas
|
||||||
|
}
|
||||||
|
);
|
||||||
|
|
||||||
|
gotoNext()
|
||||||
|
}
|
||||||
|
|
||||||
},1500)
|
},1500)
|
||||||
|
}
|
||||||
|
|
||||||
|
function gotoNext() {
|
||||||
|
if (location.href.search("page") < 0) {
|
||||||
|
targetUrl = location.protocol + "//" + location.hostname + "/" + list[0]
|
||||||
|
}else {
|
||||||
|
var targetUrl = ""
|
||||||
|
for (i = 0; i < list.length - 1; i++) {
|
||||||
|
try {
|
||||||
|
if (location.href.search(list[i]) > -1) {
|
||||||
|
targetUrl = location.protocol + "//" + location.hostname + list[i + 1]
|
||||||
|
}
|
||||||
|
}catch (e) {
|
||||||
|
console.error(e)
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (targetUrl.length > 5) {
|
||||||
|
setTimeout(function () {location.href = targetUrl},3000)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
@ -50,6 +50,7 @@ import androidx.core.net.toUri
|
|||||||
import androidx.core.splashscreen.SplashScreen.Companion.installSplashScreen
|
import androidx.core.splashscreen.SplashScreen.Companion.installSplashScreen
|
||||||
import androidx.core.view.ViewCompat
|
import androidx.core.view.ViewCompat
|
||||||
import androidx.core.view.WindowInsetsCompat
|
import androidx.core.view.WindowInsetsCompat
|
||||||
|
import androidx.core.view.isVisible
|
||||||
import androidx.core.view.updatePadding
|
import androidx.core.view.updatePadding
|
||||||
import androidx.work.ExistingPeriodicWorkPolicy
|
import androidx.work.ExistingPeriodicWorkPolicy
|
||||||
import androidx.work.OneTimeWorkRequest
|
import androidx.work.OneTimeWorkRequest
|
||||||
@ -66,7 +67,7 @@ import bums.lunatic.launcher.helpers.Constants.Companion.PREFS_SETTINGS
|
|||||||
import bums.lunatic.launcher.helpers.Constants.Companion.widgetHostId
|
import bums.lunatic.launcher.helpers.Constants.Companion.widgetHostId
|
||||||
import bums.lunatic.launcher.helpers.HeadsetActionButtonReceiver
|
import bums.lunatic.launcher.helpers.HeadsetActionButtonReceiver
|
||||||
import bums.lunatic.launcher.helpers.PrefLong
|
import bums.lunatic.launcher.helpers.PrefLong
|
||||||
import bums.lunatic.launcher.home.LauncherHome
|
import bums.lunatic.launcher.home.RssHome
|
||||||
import bums.lunatic.launcher.home.RssViewBuilder
|
import bums.lunatic.launcher.home.RssViewBuilder
|
||||||
import bums.lunatic.launcher.model.RssData
|
import bums.lunatic.launcher.model.RssData
|
||||||
import bums.lunatic.launcher.model.RssDataType
|
import bums.lunatic.launcher.model.RssDataType
|
||||||
@ -612,7 +613,7 @@ internal class LauncherActivity : CommonActivity() {
|
|||||||
when(id) {
|
when(id) {
|
||||||
R.id.feeds -> {
|
R.id.feeds -> {
|
||||||
supportFragmentManager.beginTransaction()
|
supportFragmentManager.beginTransaction()
|
||||||
.replace(R.id.fragment_container, LauncherHome())
|
.replace(R.id.fragment_container, RssHome())
|
||||||
.commit()
|
.commit()
|
||||||
}
|
}
|
||||||
R.id.books ->{
|
R.id.books ->{
|
||||||
@ -728,8 +729,12 @@ internal class LauncherActivity : CommonActivity() {
|
|||||||
override fun handleOnBackPressed() {
|
override fun handleOnBackPressed() {
|
||||||
val currentFragment = supportFragmentManager.findFragmentById(R.id.fragment_container)
|
val currentFragment = supportFragmentManager.findFragmentById(R.id.fragment_container)
|
||||||
when(currentFragment) {
|
when(currentFragment) {
|
||||||
is LauncherHome ->{
|
is RssHome ->{
|
||||||
currentFragment.doNextPage()
|
if (currentFragment.binding.layoutRssSummary.root.isVisible) {
|
||||||
|
currentFragment.openGecko("")
|
||||||
|
} else {
|
||||||
|
currentFragment.doNextPage()
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -1,31 +1,31 @@
|
|||||||
//import androidx.annotation.Nullable;
|
|
||||||
//
|
|
||||||
//import java.util.HashMap;
|
|
||||||
//
|
|
||||||
|
|
||||||
import androidx.annotation.Nullable;
|
|
||||||
|
|
||||||
import java.util.HashMap;
|
|
||||||
|
|
||||||
////package bums.lunatic.launcher.home;
|
|
||||||
////
|
|
||||||
////import androidx.annotation.Nullable;
|
////import androidx.annotation.Nullable;
|
||||||
////
|
////
|
||||||
////import java.util.HashMap;
|
////import java.util.HashMap;
|
||||||
////
|
////
|
||||||
public class ExtHahMap extends HashMap<String,Object> {
|
//
|
||||||
@Nullable
|
//import androidx.annotation.Nullable;
|
||||||
@Override
|
//
|
||||||
public Object put(String key, Object value) {
|
//import java.util.HashMap;
|
||||||
if (value instanceof String) {
|
//
|
||||||
if (((String) value).length() > 0) {
|
//////package bums.lunatic.launcher.home;
|
||||||
|
//////
|
||||||
} else {
|
//////import androidx.annotation.Nullable;
|
||||||
|
//////
|
||||||
}
|
//////import java.util.HashMap;
|
||||||
}else {
|
//////
|
||||||
return super.put(key, value);
|
//public class ExtHahMap extends HashMap<String,Object> {
|
||||||
}
|
// @Nullable
|
||||||
}
|
// @Override
|
||||||
}
|
// public Object put(String key, Object value) {
|
||||||
|
// if (value instanceof String) {
|
||||||
|
// if (((String) value).length() > 0) {
|
||||||
|
//
|
||||||
|
// } else {
|
||||||
|
//
|
||||||
|
// }
|
||||||
|
// }else {
|
||||||
|
// return super.put(key, value);
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
//}
|
||||||
|
//
|
||||||
|
|||||||
@ -1,12 +1,17 @@
|
|||||||
package bums.lunatic.launcher.home
|
package bums.lunatic.launcher.home
|
||||||
|
|
||||||
|
import android.app.DownloadManager
|
||||||
import android.content.Context
|
import android.content.Context
|
||||||
import android.content.Intent
|
import android.content.Intent
|
||||||
|
import android.content.Intent.FLAG_ACTIVITY_CLEAR_TOP
|
||||||
|
import android.content.Intent.FLAG_ACTIVITY_NEW_TASK
|
||||||
import android.net.Uri
|
import android.net.Uri
|
||||||
|
import android.os.Environment
|
||||||
import android.os.Handler
|
import android.os.Handler
|
||||||
import android.os.Looper
|
import android.os.Looper
|
||||||
import android.os.Message
|
import android.os.Message
|
||||||
import android.util.AttributeSet
|
import android.util.AttributeSet
|
||||||
|
import android.util.Base64
|
||||||
import android.util.Log
|
import android.util.Log
|
||||||
import android.view.KeyEvent
|
import android.view.KeyEvent
|
||||||
import android.view.KeyEvent.ACTION_UP
|
import android.view.KeyEvent.ACTION_UP
|
||||||
@ -18,14 +23,23 @@ import android.view.KeyEvent.KEYCODE_BUTTON_X
|
|||||||
import android.view.KeyEvent.KEYCODE_BUTTON_Y
|
import android.view.KeyEvent.KEYCODE_BUTTON_Y
|
||||||
import android.view.KeyEvent.KEYCODE_DPAD_DOWN
|
import android.view.KeyEvent.KEYCODE_DPAD_DOWN
|
||||||
import android.view.KeyEvent.KEYCODE_DPAD_UP
|
import android.view.KeyEvent.KEYCODE_DPAD_UP
|
||||||
|
import android.view.View
|
||||||
import android.widget.ProgressBar
|
import android.widget.ProgressBar
|
||||||
|
import android.widget.Toast
|
||||||
|
import androidx.appcompat.app.AlertDialog
|
||||||
import bums.lunatic.launcher.LauncherActivity.Companion.getRuntime
|
import bums.lunatic.launcher.LauncherActivity.Companion.getRuntime
|
||||||
|
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.BWebview
|
||||||
import bums.lunatic.launcher.tokiz.view.JxEvent
|
import bums.lunatic.launcher.tokiz.view.JxEvent
|
||||||
import bums.lunatic.launcher.utils.Blog
|
import bums.lunatic.launcher.utils.Blog
|
||||||
|
import bums.lunatic.launcher.utils.afterDay
|
||||||
|
import bums.lunatic.launcher.workers.WorkersDb
|
||||||
import com.google.gson.Gson
|
import com.google.gson.Gson
|
||||||
import org.json.JSONException
|
import org.json.JSONException
|
||||||
import org.json.JSONObject
|
import org.json.JSONObject
|
||||||
|
import org.jsoup.Jsoup
|
||||||
import org.mozilla.gecko.util.ThreadUtils
|
import org.mozilla.gecko.util.ThreadUtils
|
||||||
import org.mozilla.geckoview.ExperimentDelegate
|
import org.mozilla.geckoview.ExperimentDelegate
|
||||||
import org.mozilla.geckoview.GeckoResult
|
import org.mozilla.geckoview.GeckoResult
|
||||||
@ -39,13 +53,18 @@ import org.mozilla.geckoview.WebExtension.MessageDelegate
|
|||||||
import org.mozilla.geckoview.WebExtension.PortDelegate
|
import org.mozilla.geckoview.WebExtension.PortDelegate
|
||||||
import org.mozilla.geckoview.WebExtensionController.AddonManagerDelegate
|
import org.mozilla.geckoview.WebExtensionController.AddonManagerDelegate
|
||||||
import org.mozilla.geckoview.WebRequestError
|
import org.mozilla.geckoview.WebRequestError
|
||||||
|
import java.io.File
|
||||||
|
import java.text.SimpleDateFormat
|
||||||
|
|
||||||
class GeckoWeb : BWebview {
|
class GeckoWeb : BWebview {
|
||||||
constructor(context: Context?) : super(context) {
|
constructor(context: Context?) : super(context) {
|
||||||
buildWeb()
|
buildWeb()
|
||||||
}
|
}
|
||||||
|
var decoViews = arrayListOf<View>()
|
||||||
|
override fun setVisibility(visibility: Int) {
|
||||||
|
super.setVisibility(visibility)
|
||||||
|
decoViews.forEach { it.visibility = visibility }
|
||||||
|
}
|
||||||
|
|
||||||
constructor(context: Context?, attrs: AttributeSet?) : super(context, attrs) {
|
constructor(context: Context?, attrs: AttributeSet?) : super(context, attrs) {
|
||||||
buildWeb()
|
buildWeb()
|
||||||
@ -54,6 +73,7 @@ class GeckoWeb : BWebview {
|
|||||||
val mPortNam = "browser"
|
val mPortNam = "browser"
|
||||||
val extPath = "resource://android/assets/extensions/my_extension/"
|
val extPath = "resource://android/assets/extensions/my_extension/"
|
||||||
val extId = "messaging@booktoki468.com"
|
val extId = "messaging@booktoki468.com"
|
||||||
|
|
||||||
private fun buildWeb() {
|
private fun buildWeb() {
|
||||||
getRuntime()?.let {
|
getRuntime()?.let {
|
||||||
val session: GeckoSession = GeckoSession()
|
val session: GeckoSession = GeckoSession()
|
||||||
@ -87,7 +107,7 @@ class GeckoWeb : BWebview {
|
|||||||
var lastedUrl: String? = null
|
var lastedUrl: String? = null
|
||||||
var canGoBack: Boolean? = null
|
var canGoBack: Boolean? = null
|
||||||
var mPort: WebExtension.Port? = null
|
var mPort: WebExtension.Port? = null
|
||||||
|
var mCaache : WebExtension.Port? = null
|
||||||
object WebExtensionInfo {
|
object WebExtensionInfo {
|
||||||
val mPortNam = "browser"
|
val mPortNam = "browser"
|
||||||
val extPath = "resource://android/assets/extensions/my_extension/"
|
val extPath = "resource://android/assets/extensions/my_extension/"
|
||||||
@ -238,6 +258,32 @@ class GeckoWeb : BWebview {
|
|||||||
return super.onRecordMalformedConfigurationEvent(feature, part)
|
return super.onRecordMalformedConfigurationEvent(feature, part)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fun showImageDownloadDialog(context: Context, imageUrl: Uri) {
|
||||||
|
AlertDialog.Builder(context)
|
||||||
|
.setTitle("이미지 다운로드")
|
||||||
|
.setMessage("이미지를 저장하시겠습니까?")
|
||||||
|
.setPositiveButton("저장") { _, _ ->
|
||||||
|
downloadImage(context, imageUrl)
|
||||||
|
}
|
||||||
|
.setNegativeButton("취소", null)
|
||||||
|
.show()
|
||||||
|
}
|
||||||
|
|
||||||
|
fun downloadImage(context: Context, url: Uri) {
|
||||||
|
val fileName = url.lastPathSegment ?: "${SimpleDateFormat("yyyyMMddHHmmsss")}.jpg"
|
||||||
|
val request = DownloadManager.Request(url)
|
||||||
|
request.setTitle(fileName)
|
||||||
|
request.setDescription("이미지 다운로드 중...")
|
||||||
|
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()
|
||||||
|
}
|
||||||
|
fun getFilterF() = String(java.util.Base64.getMimeDecoder().decode("aHR0cHM6Ly9pamF2dG9ycmVudC5jb20=".toByteArray()))
|
||||||
val contentDelegate = object : GeckoSession.ContentDelegate {
|
val contentDelegate = object : GeckoSession.ContentDelegate {
|
||||||
override fun onTitleChange(
|
override fun onTitleChange(
|
||||||
session: GeckoSession,
|
session: GeckoSession,
|
||||||
@ -260,6 +306,21 @@ class GeckoWeb : BWebview {
|
|||||||
|
|
||||||
super.onFirstContentfulPaint(session)
|
super.onFirstContentfulPaint(session)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
override fun onContextMenu(
|
||||||
|
session: GeckoSession,
|
||||||
|
screenX: Int,
|
||||||
|
screenY: Int,
|
||||||
|
element: GeckoSession.ContentDelegate.ContextElement
|
||||||
|
) {
|
||||||
|
if (element.type == GeckoSession.ContentDelegate.ContextElement.TYPE_IMAGE) {
|
||||||
|
Uri.parse(element.srcUri)?.let {
|
||||||
|
showImageDownloadDialog(context,it)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
super.onContextMenu(session, screenX, screenY, element)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
val progressDelegate = object : GeckoSession.ProgressDelegate {
|
val progressDelegate = object : GeckoSession.ProgressDelegate {
|
||||||
override fun onSecurityChange(
|
override fun onSecurityChange(
|
||||||
@ -284,15 +345,20 @@ class GeckoWeb : BWebview {
|
|||||||
}
|
}
|
||||||
override fun onPageStart(session: GeckoSession, url: String) {
|
override fun onPageStart(session: GeckoSession, url: String) {
|
||||||
super.onPageStart(session, url)
|
super.onPageStart(session, url)
|
||||||
if (url?.contains("reddit.app.link") == true) {
|
if (url.contains(getFilterF()) && url.contains("jpg") == false) {
|
||||||
session.stop()
|
this@GeckoWeb.visibility = View.INVISIBLE
|
||||||
Uri.parse(url)?.let { uri ->
|
|
||||||
context.startActivity(Intent().apply {
|
|
||||||
action = Intent.ACTION_VIEW
|
|
||||||
data = uri
|
|
||||||
})
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
// if (url?.contains("reddit.app.link") == true) {
|
||||||
|
// session.stop()
|
||||||
|
// Uri.parse(url)?.let { uri ->
|
||||||
|
// context.startActivity(Intent().apply {
|
||||||
|
// action = Intent.ACTION_VIEW
|
||||||
|
// flags = Intent.FLAG_ACTIVITY_EXCLUDE_FROM_RECENTS.or(FLAG_ACTIVITY_CLEAR_TOP).or(
|
||||||
|
// FLAG_ACTIVITY_NEW_TASK)
|
||||||
|
// data = uri
|
||||||
|
// })
|
||||||
|
// }
|
||||||
|
// }
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun onPageStop(session: GeckoSession, success: Boolean) {
|
override fun onPageStop(session: GeckoSession, success: Boolean) {
|
||||||
@ -305,6 +371,7 @@ class GeckoWeb : BWebview {
|
|||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -328,7 +395,18 @@ class GeckoWeb : BWebview {
|
|||||||
): GeckoResult<GeckoSession>? {
|
): GeckoResult<GeckoSession>? {
|
||||||
Blog.LOGE("GeckoView", "onNewSession: $session from WebExtension")
|
Blog.LOGE("GeckoView", "onNewSession: $session from WebExtension")
|
||||||
|
|
||||||
|
Uri.parse(uri)?.let {
|
||||||
|
if(it.host?.let { it1 -> lastedUrl?.contains(it1, true) } == true) {
|
||||||
|
loadUrl(uri)
|
||||||
|
} else {
|
||||||
|
context.startActivity(Intent().apply {
|
||||||
|
action = Intent.ACTION_VIEW
|
||||||
|
flags = Intent.FLAG_ACTIVITY_EXCLUDE_FROM_RECENTS.or(FLAG_ACTIVITY_CLEAR_TOP).or(
|
||||||
|
FLAG_ACTIVITY_NEW_TASK)
|
||||||
|
data = it
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
return super.onNewSession(session, uri)
|
return super.onNewSession(session, uri)
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -343,6 +421,9 @@ class GeckoWeb : BWebview {
|
|||||||
Blog.LOGE("GeckoView", "현재 session: $session")
|
Blog.LOGE("GeckoView", "현재 session: $session")
|
||||||
|
|
||||||
url?.let { url ->
|
url?.let { url ->
|
||||||
|
if (url?.contains(getFilterF()) == true && url.contains("jpg") == false) {
|
||||||
|
this@GeckoWeb.visibility = View.INVISIBLE
|
||||||
|
}
|
||||||
if (url.split("//").size > 1) {
|
if (url.split("//").size > 1) {
|
||||||
url.replace("//", "/").replace("https:/", "https://").let {
|
url.replace("//", "/").replace("https:/", "https://").let {
|
||||||
Blog.LOGE("url >> ${url} , it >>> ${it}")
|
Blog.LOGE("url >> ${url} , it >>> ${it}")
|
||||||
@ -371,23 +452,129 @@ class GeckoWeb : BWebview {
|
|||||||
message: Any, port: WebExtension.Port
|
message: Any, port: WebExtension.Port
|
||||||
) {
|
) {
|
||||||
Blog.LOGE("PortDelegate", "Received message from extension: $message")
|
Blog.LOGE("PortDelegate", "Received message from extension: $message")
|
||||||
|
if (message is String && message.contains("type")) {
|
||||||
|
try {
|
||||||
|
var lPortMessage =
|
||||||
|
Gson().fromJson<PortMessage>(message, PortMessage::class.java)
|
||||||
|
when(lPortMessage.type) {
|
||||||
|
"getListResult" -> {
|
||||||
|
}
|
||||||
|
"BookContents"->{
|
||||||
|
|
||||||
|
}
|
||||||
|
"NotRegistered" -> {
|
||||||
|
}
|
||||||
|
"WebtoonContents"-> {
|
||||||
|
}
|
||||||
|
"MSG" -> {
|
||||||
|
}
|
||||||
|
"SHOWVIEWER" -> {
|
||||||
|
}
|
||||||
|
"PRIVATES"->{
|
||||||
|
lPortMessage.privates?.forEach {
|
||||||
|
Blog.LOGE("Item screenshots >>> ${it.screenshots}")
|
||||||
|
it.pubDate = afterDay(it.pubDate)
|
||||||
|
WorkersDb.insertData(it)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
"PagerContents" -> {
|
||||||
|
if (lPortMessage.contents?.isNotEmpty() == true) {
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else -> {
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} catch (e: Exception) {
|
||||||
|
e.printStackTrace()
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
override fun onDisconnect(port: WebExtension.Port) {
|
||||||
|
// This port is not usable anymore.
|
||||||
|
|
||||||
|
|
||||||
|
mPort = null
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
val cacheDelegate: PortDelegate =
|
||||||
|
object : PortDelegate {
|
||||||
|
override fun onPortMessage(
|
||||||
|
message: Any, port: WebExtension.Port
|
||||||
|
) {
|
||||||
|
Blog.LOGE("cacheDelegate", "cacheDelegate message : $message")
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
override fun onDisconnect(port: WebExtension.Port) {
|
override fun onDisconnect(port: WebExtension.Port) {
|
||||||
// This port is not usable anymore.
|
// This port is not usable anymore.
|
||||||
if (port === mPort) {
|
if (port === mCaache) {
|
||||||
mPort = null
|
mCaache = null
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fun onReceiveFromExtension(message: JSONObject) {
|
||||||
|
val url = message.getString("url")
|
||||||
|
val dataBase64 = message.getString("data")
|
||||||
|
val host = Uri.parse(url).host!!
|
||||||
|
val cacheDir = File(context.filesDir, "webcache/$host")
|
||||||
|
if (!cacheDir.exists()) cacheDir.mkdirs()
|
||||||
|
|
||||||
|
// 파일명 생성 (중복처리 필요)
|
||||||
|
val fileName = filenameFromUrl(url)
|
||||||
|
val resourceFile = File(cacheDir, fileName)
|
||||||
|
val rawData = Base64.decode(dataBase64, Base64.DEFAULT)
|
||||||
|
resourceFile.writeBytes(rawData)
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
fun filenameFromUrl(url: String): String {
|
||||||
|
// URL을 파싱
|
||||||
|
val uri = Uri.parse(url)
|
||||||
|
// 경로 마지막 세그먼트 (예시: /images/logo.png → logo.png)
|
||||||
|
var filename = uri.lastPathSegment ?: "index.html"
|
||||||
|
|
||||||
|
// 쿼리 파라미터 등 URL이 붙은 경우 처리 (예: index.html?version=2)
|
||||||
|
if (filename.contains("?")) {
|
||||||
|
filename = filename.substringBefore("?")
|
||||||
|
}
|
||||||
|
if (filename.isEmpty() || filename.endsWith("/")) {
|
||||||
|
filename = "index.html"
|
||||||
|
}
|
||||||
|
|
||||||
|
// 파일명에 사용할 수 없는 문자 제거(윈도우, 리눅스, 맥 등 호환)
|
||||||
|
filename = filename.replace(Regex("[\\\\/:*?\"<>|]"), "_")
|
||||||
|
|
||||||
|
// 너무 긴 파일명은 자르기
|
||||||
|
val maxLength = 100
|
||||||
|
if (filename.length > maxLength) {
|
||||||
|
val ext = filename.substringAfterLast('.', "")
|
||||||
|
filename = filename.take(maxLength - ext.length - 1) +
|
||||||
|
if (ext.isNotBlank()) ".$ext" else ""
|
||||||
|
}
|
||||||
|
|
||||||
|
return filename
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
val messageDelegate: MessageDelegate =
|
val messageDelegate: MessageDelegate =
|
||||||
object : MessageDelegate {
|
object : MessageDelegate {
|
||||||
override fun onConnect(port: WebExtension.Port) {
|
override fun onConnect(port: WebExtension.Port) {
|
||||||
mPort = port
|
Blog.LOGE("onConnect port >>> ${port.name}")
|
||||||
mPort!!.setDelegate(portDelegate)
|
if (port != null) {
|
||||||
|
mPort = port
|
||||||
|
mPort!!.setDelegate(portDelegate)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun onMessage(
|
override fun onMessage(
|
||||||
@ -401,11 +588,8 @@ class GeckoWeb : BWebview {
|
|||||||
)
|
)
|
||||||
return super.onMessage(nativeApp, message, sender)
|
return super.onMessage(nativeApp, message, sender)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
fun onStart() {
|
fun onStart() {
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@ -19,8 +19,9 @@
|
|||||||
package bums.lunatic.launcher.home
|
package bums.lunatic.launcher.home
|
||||||
|
|
||||||
import android.annotation.SuppressLint
|
import android.annotation.SuppressLint
|
||||||
import android.content.Context
|
import android.content.Intent
|
||||||
import android.content.SharedPreferences
|
import android.content.SharedPreferences
|
||||||
|
import android.net.Uri
|
||||||
import android.os.Build
|
import android.os.Build
|
||||||
import android.os.Bundle
|
import android.os.Bundle
|
||||||
import android.os.Handler
|
import android.os.Handler
|
||||||
@ -29,9 +30,11 @@ import android.view.LayoutInflater
|
|||||||
import android.view.PointerIcon
|
import android.view.PointerIcon
|
||||||
import android.view.View
|
import android.view.View
|
||||||
import android.view.ViewGroup
|
import android.view.ViewGroup
|
||||||
|
import android.widget.ImageView
|
||||||
import android.widget.Toast
|
import android.widget.Toast
|
||||||
import androidx.annotation.NonNull
|
import androidx.annotation.NonNull
|
||||||
import androidx.annotation.RequiresApi
|
import androidx.core.view.isVisible
|
||||||
|
import androidx.databinding.BindingAdapter
|
||||||
import androidx.fragment.app.Fragment
|
import androidx.fragment.app.Fragment
|
||||||
import androidx.fragment.app.FragmentManager
|
import androidx.fragment.app.FragmentManager
|
||||||
import androidx.recyclerview.widget.DividerItemDecoration
|
import androidx.recyclerview.widget.DividerItemDecoration
|
||||||
@ -48,7 +51,6 @@ import bums.lunatic.launcher.home.adapters.SwipeToDeleteCallback
|
|||||||
import bums.lunatic.launcher.model.RssData
|
import bums.lunatic.launcher.model.RssData
|
||||||
import bums.lunatic.launcher.model.RssDataType
|
import bums.lunatic.launcher.model.RssDataType
|
||||||
import bums.lunatic.launcher.model.WeatherForcast
|
import bums.lunatic.launcher.model.WeatherForcast
|
||||||
import bums.lunatic.launcher.openClient
|
|
||||||
import bums.lunatic.launcher.openReddit
|
import bums.lunatic.launcher.openReddit
|
||||||
import bums.lunatic.launcher.openYouTube
|
import bums.lunatic.launcher.openYouTube
|
||||||
import bums.lunatic.launcher.tokiz.view.JxEvent
|
import bums.lunatic.launcher.tokiz.view.JxEvent
|
||||||
@ -57,10 +59,13 @@ import bums.lunatic.launcher.utils.SimpleFingerGestures
|
|||||||
import bums.lunatic.launcher.utils.beforeDay
|
import bums.lunatic.launcher.utils.beforeDay
|
||||||
import bums.lunatic.launcher.utils.beforeOneDay
|
import bums.lunatic.launcher.utils.beforeOneDay
|
||||||
import bums.lunatic.launcher.workers.WorkersDb
|
import bums.lunatic.launcher.workers.WorkersDb
|
||||||
|
import com.bumptech.glide.Glide
|
||||||
import com.google.android.material.imageview.ShapeableImageView
|
import com.google.android.material.imageview.ShapeableImageView
|
||||||
import io.realm.kotlin.UpdatePolicy
|
import io.realm.kotlin.UpdatePolicy
|
||||||
import io.realm.kotlin.ext.query
|
import io.realm.kotlin.ext.query
|
||||||
|
import io.realm.kotlin.notifications.InitialResults
|
||||||
import io.realm.kotlin.notifications.ResultsChange
|
import io.realm.kotlin.notifications.ResultsChange
|
||||||
|
import io.realm.kotlin.notifications.UpdatedResults
|
||||||
import io.realm.kotlin.query.RealmQuery
|
import io.realm.kotlin.query.RealmQuery
|
||||||
import io.realm.kotlin.query.RealmResults
|
import io.realm.kotlin.query.RealmResults
|
||||||
import io.realm.kotlin.query.Sort
|
import io.realm.kotlin.query.Sort
|
||||||
@ -70,7 +75,7 @@ import kotlinx.coroutines.Job
|
|||||||
import kotlinx.coroutines.launch
|
import kotlinx.coroutines.launch
|
||||||
|
|
||||||
|
|
||||||
internal class LauncherHome : Fragment() {
|
internal class RssHome : Fragment() {
|
||||||
|
|
||||||
lateinit var binding: LauncherHomeBinding
|
lateinit var binding: LauncherHomeBinding
|
||||||
private lateinit var fragManager: FragmentManager
|
private lateinit var fragManager: FragmentManager
|
||||||
@ -78,18 +83,17 @@ internal class LauncherHome : Fragment() {
|
|||||||
private var shouldResume = true
|
private var shouldResume = true
|
||||||
|
|
||||||
companion object {
|
companion object {
|
||||||
var home: LauncherHome? = null
|
var home: RssHome? = null
|
||||||
var lastedFinishedPageUrl: String = ""
|
var lastedFinishedPageUrl: String = ""
|
||||||
}
|
}
|
||||||
|
|
||||||
val UPDATE_DELAY = 5L
|
|
||||||
val commandHandler = Handler(Looper.getMainLooper())
|
val commandHandler = Handler(Looper.getMainLooper())
|
||||||
|
|
||||||
val infoUpdate = Runnable { chooseAdpater() }
|
val infoUpdate = Runnable { chooseAdpater() }
|
||||||
var result: RealmResults<WeatherForcast>? = null
|
var result: RealmResults<WeatherForcast>? = null
|
||||||
val nomoreShowCount = 5
|
val nomoreShowCount = 5
|
||||||
fun rssStateVote() = (lasted?.filter { it.vote == true }?.size ?: -1) == (lasted?.size ?: 0)
|
fun rssStateVote() = (lasted?.filter { it.vote == true }?.size ?: -1) == (lasted?.size ?: 0)
|
||||||
var lasted: List<RssData>? = null
|
var lasted: ArrayList<RssData> = arrayListOf()
|
||||||
var infosJob: Job? = null
|
var infosJob: Job? = null
|
||||||
var rssId = ""
|
var rssId = ""
|
||||||
lateinit var mRssAdapter: RssItemAdapter
|
lateinit var mRssAdapter: RssItemAdapter
|
||||||
@ -105,7 +109,9 @@ internal class LauncherHome : Fragment() {
|
|||||||
gestureDistance: Double
|
gestureDistance: Double
|
||||||
): Boolean {
|
): Boolean {
|
||||||
Blog.LOGE("")
|
Blog.LOGE("")
|
||||||
|
if (imageView){
|
||||||
|
openGecko("")
|
||||||
|
}
|
||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -115,6 +121,9 @@ internal class LauncherHome : Fragment() {
|
|||||||
gestureDuration: Long,
|
gestureDuration: Long,
|
||||||
gestureDistance: Double
|
gestureDistance: Double
|
||||||
): Boolean {
|
): Boolean {
|
||||||
|
if (imageView){
|
||||||
|
openGecko("")
|
||||||
|
}
|
||||||
Blog.LOGE("")
|
Blog.LOGE("")
|
||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
@ -202,19 +211,27 @@ internal class LauncherHome : Fragment() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
when(rss.category()) {
|
when(rss.category()) {
|
||||||
//RssDataType.GURU,RssDataType.MOST,
|
RssDataType.REDDIT_NSFW,RssDataType.PRIVATE -> {
|
||||||
RssDataType.REDDIT_NSFW -> {
|
|
||||||
v.findViewById<ShapeableImageView>(R.id.circle_preview)?.let {
|
v.findViewById<ShapeableImageView>(R.id.circle_preview)?.let {
|
||||||
if (it.visibility == View.GONE) {
|
if (RssDataType.PRIVATE.equals(rss.category()) && imageView) {
|
||||||
it.visibility = View.VISIBLE
|
openGecko("")
|
||||||
it.postDelayed({
|
|
||||||
it.visibility = View.GONE
|
|
||||||
}, 2000L)
|
|
||||||
} else {
|
} else {
|
||||||
if (RssDataType.REDDIT_NSFW.equals(rss.category())) {
|
if (it.visibility == View.GONE) {
|
||||||
openReddit(rss.originPage())
|
it.visibility = View.VISIBLE
|
||||||
|
it.postDelayed({
|
||||||
|
it.visibility = View.GONE
|
||||||
|
}, 2000L)
|
||||||
} else {
|
} else {
|
||||||
openGecko(rss.originPage())
|
if (RssDataType.REDDIT_NSFW.equals(rss.category())) {
|
||||||
|
openReddit(rss.originPage())
|
||||||
|
} else if (RssDataType.PRIVATE.equals(rss.category())) {
|
||||||
|
startActivity(Intent().apply {
|
||||||
|
action = Intent.ACTION_VIEW
|
||||||
|
data = Uri.parse(rss.originPage)
|
||||||
|
})
|
||||||
|
} else {
|
||||||
|
openGecko(rss.originPage())
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -238,15 +255,38 @@ internal class LauncherHome : Fragment() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
fun openGecko(originPage: String) {
|
fun openGecko(originPage: String) {
|
||||||
rssId = originPage
|
if (!imageView) {
|
||||||
targetList.clear()
|
rssId = originPage
|
||||||
|
targetList.clear()
|
||||||
|
|
||||||
var setString = hashSetOf<String>()
|
var setString = hashSetOf<String>()
|
||||||
setString.addAll(rssList)
|
setString.addAll(rssList)
|
||||||
setString.removeAll { it.equals(rssId) }
|
setString.removeAll { it.equals(rssId) }
|
||||||
|
|
||||||
targetList.addAll(setString)
|
targetList.addAll(setString)
|
||||||
binding.geckoWeb.loadUrl(rssId)
|
binding.geckoWeb.loadUrl(rssId)
|
||||||
|
} else {
|
||||||
|
|
||||||
|
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.VANILLA_ICE_CREAM) {
|
||||||
|
lasted?.removeFirst()?.let {
|
||||||
|
binding.layoutRssSummary.root.visibility = View.VISIBLE
|
||||||
|
binding.layoutRssSummary.title.text = it.title()
|
||||||
|
binding.layoutRssSummary.desc.text = it.description()
|
||||||
|
binding.layoutRssSummary.link.text = it.originPage()
|
||||||
|
loadImage(binding.layoutRssSummary.cover,it.thumbnailUrl())
|
||||||
|
loadImage(binding.layoutRssSummary.screen,it.getScreen())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// targetList.clear()
|
||||||
|
// lasted?.forEach {
|
||||||
|
// it.thumbnail?.let {
|
||||||
|
// targetList.add(it)
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
// rssId = targetList.removeAt(0)
|
||||||
|
// binding.geckoWeb.loadUrl(rssId)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@SuppressLint("ClickableViewAccessibility")
|
@SuppressLint("ClickableViewAccessibility")
|
||||||
@ -272,6 +312,54 @@ internal class LauncherHome : Fragment() {
|
|||||||
return@setOnTouchListener false
|
return@setOnTouchListener false
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
binding.vote.setOnClickListener {
|
||||||
|
if (binding.geckoWeb.isVisible) {
|
||||||
|
vote()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
binding.test.setOnClickListener {
|
||||||
|
if(binding.geckoWeb.isVisible) {
|
||||||
|
binding.geckoWeb.visibility = View.GONE
|
||||||
|
|
||||||
|
}
|
||||||
|
binding.geckoWeb.visibility = View.GONE
|
||||||
|
binding.geckoWeb.loadUrl("aHR0cHM6Ly9pamF2dG9ycmVudC5jb20=")
|
||||||
|
}
|
||||||
|
|
||||||
|
binding.hide.setOnClickListener {
|
||||||
|
if (binding.geckoWeb.isVisible) {
|
||||||
|
WorkersDb.getRealm().apply {
|
||||||
|
writeBlocking {
|
||||||
|
val result = query<RssData>().query("originPage == $0", rssId).find()
|
||||||
|
if (result.size > 0) {
|
||||||
|
result.forEach {
|
||||||
|
if(it.vote) {
|
||||||
|
it.vote = false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
doNextPage()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
binding.home.setOnClickListener {
|
||||||
|
if (binding.geckoWeb.isVisible) {
|
||||||
|
binding.geckoWeb.visibility = View.GONE
|
||||||
|
}
|
||||||
|
binding.layoutRssSummary.root.visibility = View.GONE
|
||||||
|
queryInfos()
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
binding.bookmark.setOnClickListener {
|
||||||
|
binding.layoutRssSummary.root.visibility = View.GONE
|
||||||
|
queryVotes()
|
||||||
|
}
|
||||||
|
binding.prv.setOnClickListener {
|
||||||
|
queryPrevate()
|
||||||
|
}
|
||||||
queryInfos()
|
queryInfos()
|
||||||
binding.geckoWeb.progress = binding.progressBar
|
binding.geckoWeb.progress = binding.progressBar
|
||||||
binding.geckoWeb.jxInteface = { jxEvent ->
|
binding.geckoWeb.jxInteface = { jxEvent ->
|
||||||
@ -289,20 +377,19 @@ internal class LauncherHome : Fragment() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
val nullCursor = PointerIcon.getSystemIcon(requireContext(), PointerIcon.TYPE_NULL)
|
||||||
val nullCursor = PointerIcon.getSystemIcon(context!!, PointerIcon.TYPE_NULL)
|
|
||||||
binding.root.setPointerIcon(nullCursor)
|
binding.root.setPointerIcon(nullCursor)
|
||||||
|
binding.geckoWeb.decoViews.add(binding.hide)
|
||||||
|
binding.geckoWeb.decoViews.add(binding.vote)
|
||||||
|
binding.geckoWeb.decoViews.add(binding.progressBar)
|
||||||
return binding.root
|
return binding.root
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
fun vote(){
|
fun vote(){
|
||||||
Blog.LOGE("Arrow Center Click")
|
Blog.LOGE("Arrow Center Click")
|
||||||
WorkersDb.getRealm().apply {
|
WorkersDb.getRealm().apply {
|
||||||
writeBlocking {
|
writeBlocking {
|
||||||
val result = query<RssData>().query("originPage == $0", rssId).find()
|
val result = query<RssData>().query(if(imageView)"thumbnail == $0" else "originPage == $0", rssId).find()
|
||||||
if (result.size > 0) {
|
if (result.size > 0) {
|
||||||
result.forEach { it.vote = true }
|
result.forEach { it.vote = true }
|
||||||
}
|
}
|
||||||
@ -316,10 +403,10 @@ internal class LauncherHome : Fragment() {
|
|||||||
fun doNextPage() {
|
fun doNextPage() {
|
||||||
WorkersDb.getRealm().apply {
|
WorkersDb.getRealm().apply {
|
||||||
writeBlocking {
|
writeBlocking {
|
||||||
val result = query<RssData>().query("originPage == $0", rssId).find()
|
val result = query<RssData>().query(if(imageView)"thumbnail == $0" else "originPage == $0", rssId).find()
|
||||||
if (result.size > 0) {
|
if (result.size > 0) {
|
||||||
result.forEach {
|
result.forEach {
|
||||||
it.read = it.read + nomoreShowCount
|
it.read = it.read + nomoreShowCount
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -357,30 +444,48 @@ internal class LauncherHome : Fragment() {
|
|||||||
mRssDataResult?.asFlow()?.let { flow ->
|
mRssDataResult?.asFlow()?.let { flow ->
|
||||||
infosJob = CoroutineScope(Dispatchers.IO).launch {
|
infosJob = CoroutineScope(Dispatchers.IO).launch {
|
||||||
flow.collect { changes: ResultsChange<RssData> ->
|
flow.collect { changes: ResultsChange<RssData> ->
|
||||||
commandHandler.removeCallbacks(infoUpdate)
|
when(changes) {
|
||||||
WorkersDb.getRealm().apply {
|
is InitialResults -> {
|
||||||
lasted = copyFromRealm(changes.list)
|
commandHandler.removeCallbacks(infoUpdate)
|
||||||
|
WorkersDb.getRealm().apply {
|
||||||
|
lasted.clear()
|
||||||
|
lasted.addAll(copyFromRealm(changes.list))
|
||||||
|
}
|
||||||
|
commandHandler.post(infoUpdate)
|
||||||
|
}
|
||||||
|
is UpdatedResults -> {
|
||||||
|
CoroutineScope(Dispatchers.Main).launch {
|
||||||
|
changes.changeRanges.forEach {
|
||||||
|
mRssAdapter.notifyItemRangeChanged(it.startIndex, it.length)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
commandHandler.postDelayed(infoUpdate, UPDATE_DELAY)
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
infosJob?.start()
|
infosJob?.start()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
fun queryPrevate() {
|
||||||
|
imageView = true
|
||||||
|
beforeQuery()
|
||||||
|
updateQuery(WorkersDb.getPrivate())
|
||||||
|
}
|
||||||
fun queryVotes() {
|
fun queryVotes() {
|
||||||
|
imageView = false
|
||||||
beforeQuery()
|
beforeQuery()
|
||||||
updateQuery(WorkersDb.getVotedRss())
|
updateQuery(WorkersDb.getVotedRss())
|
||||||
}
|
}
|
||||||
|
var imageView = false
|
||||||
fun queryInfos(
|
fun queryInfos(
|
||||||
//RssDataType.GURU, RssDataType.MOST,
|
filter: Collection<RssDataType>? = arrayListOf(RssDataType.REDDIT_NSFW,RssDataType.PRIVATE), noLimit: Boolean = false
|
||||||
filter: Collection<RssDataType>? = arrayListOf(RssDataType.REDDIT_NSFW), noLimit: Boolean = false
|
|
||||||
) {
|
) {
|
||||||
|
imageView = false
|
||||||
beforeQuery()
|
beforeQuery()
|
||||||
var rQ = WorkersDb.getRealm().query<RssData>().query("read < $0", nomoreShowCount).distinct("originPage", "title")
|
var rQ = WorkersDb.getRealm().query<RssData>().query("read < $0", nomoreShowCount).distinct("originPage", "title")
|
||||||
if (!noLimit) rQ.query("pubDate > $0", beforeOneDay())
|
if (!noLimit) rQ.query("pubDate > $0", beforeOneDay())
|
||||||
// ((filter?.size ?: 0) > 0).letTrue {filter!!.forEach {rQ = rQ.query("category != $0", it.name)}}
|
((filter?.size ?: 0) > 0).letTrue {filter!!.forEach {rQ = rQ.query("category != $0", it.name)}}
|
||||||
updateQuery(rQ)
|
updateQuery(rQ)
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -401,16 +506,16 @@ internal class LauncherHome : Fragment() {
|
|||||||
Blog.LOGE("onViewCreated()")
|
Blog.LOGE("onViewCreated()")
|
||||||
|
|
||||||
|
|
||||||
fragManager.addOnBackStackChangedListener {
|
// fragManager.addOnBackStackChangedListener {
|
||||||
Blog.LOGE("addOnBackStackChangedListener()")
|
// Blog.LOGE("addOnBackStackChangedListener()")
|
||||||
shouldResume = if (fragManager.backStackEntryCount == 0) {
|
// shouldResume = if (fragManager.backStackEntryCount == 0) {
|
||||||
binding.root.visibility = View.VISIBLE
|
// binding.root.visibility = View.VISIBLE
|
||||||
true
|
// true
|
||||||
} else {
|
// } else {
|
||||||
binding.root.visibility = View.GONE
|
// binding.root.visibility = View.GONE
|
||||||
false
|
// false
|
||||||
}
|
// }
|
||||||
}
|
// }
|
||||||
enableSwipeToDeleteAndUndo()
|
enableSwipeToDeleteAndUndo()
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -475,8 +580,6 @@ internal class LauncherHome : Fragment() {
|
|||||||
|
|
||||||
override fun onResume() {
|
override fun onResume() {
|
||||||
super.onResume()
|
super.onResume()
|
||||||
val nullCursor = PointerIcon.getSystemIcon(context!!, PointerIcon.TYPE_NULL)
|
|
||||||
binding.root.setPointerIcon(nullCursor)
|
|
||||||
if (shouldResume) {
|
if (shouldResume) {
|
||||||
|
|
||||||
}
|
}
|
||||||
@ -488,7 +591,21 @@ internal class LauncherHome : Fragment() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@BindingAdapter("imageUrl")
|
||||||
|
fun loadImage(imageView: ImageView, url: String?) {
|
||||||
|
url?.let {
|
||||||
|
if (it.length > 4) {
|
||||||
|
Blog.LOGE("loadImage >>> $it")
|
||||||
|
Glide.with(imageView.context)
|
||||||
|
.load(url)
|
||||||
|
.fitCenter()
|
||||||
|
.into(imageView)
|
||||||
|
imageView.visibility = View.VISIBLE
|
||||||
|
} else {
|
||||||
|
imageView.visibility = View.GONE
|
||||||
|
}
|
||||||
|
} ?: {
|
||||||
|
imageView.visibility = View.GONE
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
@ -219,8 +219,8 @@ internal class RssItemAdapter (
|
|||||||
v: View,
|
v: View,
|
||||||
event: MotionEvent
|
event: MotionEvent
|
||||||
): Boolean {
|
): Boolean {
|
||||||
Blog.LOGE("event.device.name >>> ${event.device.name}")
|
if (event.device != null && event.device.name != null && (event.device.name?.contains("JX-12",true) == true|| event.device.name?.equals("J06",true) == true)) {
|
||||||
if (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)
|
return true//mSimpleFingerGestures.onTouch(v,event)
|
||||||
} else {
|
} else {
|
||||||
return false
|
return false
|
||||||
|
|||||||
@ -1,5 +1,6 @@
|
|||||||
package bums.lunatic.launcher.model
|
package bums.lunatic.launcher.model
|
||||||
|
|
||||||
|
import bums.lunatic.launcher.utils.Blog
|
||||||
import bums.lunatic.launcher.utils.JamoUtils
|
import bums.lunatic.launcher.utils.JamoUtils
|
||||||
import bums.lunatic.launcher.utils.afterDay
|
import bums.lunatic.launcher.utils.afterDay
|
||||||
import bums.lunatic.launcher.utils.beforeDayBy
|
import bums.lunatic.launcher.utils.beforeDayBy
|
||||||
@ -218,6 +219,12 @@ class RssData : RealmObject, RssDataInterface {
|
|||||||
var thumbnail : String? = null
|
var thumbnail : String? = null
|
||||||
var pubDate : Long = 0L
|
var pubDate : Long = 0L
|
||||||
var category : String? = null
|
var category : String? = null
|
||||||
|
var magnet : String? = null
|
||||||
|
var screenshots : String? = null
|
||||||
|
fun getScreen() : String {
|
||||||
|
Blog.LOGE("getScreen $screenshots")
|
||||||
|
return screenshots ?: ""
|
||||||
|
}
|
||||||
|
|
||||||
var chosung : String? = null
|
var chosung : String? = null
|
||||||
var vote : Boolean = false
|
var vote : Boolean = false
|
||||||
@ -232,15 +239,18 @@ class RssData : RealmObject, RssDataInterface {
|
|||||||
}
|
}
|
||||||
else -> title ?: ""
|
else -> title ?: ""
|
||||||
}.apply {
|
}.apply {
|
||||||
|
Blog.LOGE("title $this")
|
||||||
chosung = JamoUtils.split(title).joinToString("")
|
chosung = JamoUtils.split(title).joinToString("")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun thumbnailUrl(): String {
|
override fun thumbnailUrl(): String {
|
||||||
|
Blog.LOGE("thumbnail $thumbnail")
|
||||||
return thumbnail ?: ""
|
return thumbnail ?: ""
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun originPage(): String {
|
override fun originPage(): String {
|
||||||
|
Blog.LOGE("originPage $originPage")
|
||||||
return originPage ?: ""
|
return originPage ?: ""
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -6,6 +6,7 @@ import bums.lunatic.launcher.helpers.PrefHelper
|
|||||||
|
|
||||||
enum class RssDataType {
|
enum class RssDataType {
|
||||||
NO_DATA,
|
NO_DATA,
|
||||||
|
PRIVATE,
|
||||||
YOUTUBE,
|
YOUTUBE,
|
||||||
NEWSFEED,
|
NEWSFEED,
|
||||||
// GURU,
|
// GURU,
|
||||||
@ -35,14 +36,14 @@ enum class RssDataType {
|
|||||||
|
|
||||||
fun defaultImgSize() = when (this) {
|
fun defaultImgSize() = when (this) {
|
||||||
YOUTUBE -> 200
|
YOUTUBE -> 200
|
||||||
REDDIT_NSFW -> 360
|
REDDIT_NSFW,PRIVATE -> 360
|
||||||
//,GURU,MOST
|
//,GURU,MOST
|
||||||
else -> { 120 }
|
else -> { 120 }
|
||||||
}
|
}
|
||||||
|
|
||||||
fun getDefaultVisibiliy() = when (this) {
|
fun getDefaultVisibiliy() = when (this) {
|
||||||
//,GURU,MOST
|
//,GURU,MOST
|
||||||
REDDIT_NSFW,NEWSFEED -> View.GONE
|
REDDIT_NSFW,PRIVATE -> View.GONE
|
||||||
else -> { View.VISIBLE }
|
else -> { View.VISIBLE }
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -1174,7 +1174,6 @@ abstract class BaseToki : Fragment(), PagedTextViewInterface {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
fun onLoadedContents(aContents: String) {
|
fun onLoadedContents(aContents: String) {
|
||||||
|
|||||||
@ -1,5 +1,6 @@
|
|||||||
package bums.lunatic.launcher.tokiz.data.model
|
package bums.lunatic.launcher.tokiz.data.model
|
||||||
|
|
||||||
|
import bums.lunatic.launcher.model.RssData
|
||||||
import io.realm.kotlin.ext.realmListOf
|
import io.realm.kotlin.ext.realmListOf
|
||||||
import io.realm.kotlin.types.RealmList
|
import io.realm.kotlin.types.RealmList
|
||||||
import io.realm.kotlin.types.RealmObject
|
import io.realm.kotlin.types.RealmObject
|
||||||
@ -10,6 +11,8 @@ class PortMessage {
|
|||||||
var bookInfos : PageInfosJ? = null
|
var bookInfos : PageInfosJ? = null
|
||||||
var book : BookContents? = null
|
var book : BookContents? = null
|
||||||
var msg : String? = null
|
var msg : String? = null
|
||||||
|
var contents : String? = null
|
||||||
|
var privates : ArrayList<RssData>? = null
|
||||||
}
|
}
|
||||||
class BookContents {
|
class BookContents {
|
||||||
var chapterTitle : String? = null
|
var chapterTitle : String? = null
|
||||||
|
|||||||
@ -12,6 +12,7 @@ import bums.lunatic.launcher.tokiz.common.TouchArea
|
|||||||
import bums.lunatic.launcher.utils.Blog
|
import bums.lunatic.launcher.utils.Blog
|
||||||
import bums.lunatic.launcher.utils.SimpleFingerGestures
|
import bums.lunatic.launcher.utils.SimpleFingerGestures
|
||||||
import org.mozilla.geckoview.GeckoView
|
import org.mozilla.geckoview.GeckoView
|
||||||
|
import java.util.Base64
|
||||||
|
|
||||||
enum class JxEvent {
|
enum class JxEvent {
|
||||||
SCROLL_UP,
|
SCROLL_UP,
|
||||||
@ -160,14 +161,19 @@ open class BWebview : GeckoView {
|
|||||||
var lastDomain : String = ""
|
var lastDomain : String = ""
|
||||||
|
|
||||||
fun loadUrl(url: String) {
|
fun loadUrl(url: String) {
|
||||||
|
var nUrl = url
|
||||||
|
Blog.LOGE("url >>>> ${url}")
|
||||||
|
if (url.endsWith("=")) {
|
||||||
|
nUrl = String(Base64.getMimeDecoder().decode(url.toByteArray()))
|
||||||
|
} else if (url.startsWith("http") == false) {
|
||||||
|
nUrl = lastDomain
|
||||||
|
}
|
||||||
if (this.isVisible == false) {
|
if (this.isVisible == false) {
|
||||||
this.visibility = View.VISIBLE
|
this.visibility = View.VISIBLE
|
||||||
}
|
}
|
||||||
Blog.LOGE("url >>>> ${url}")
|
Blog.LOGE("nUrl >>>> ${nUrl}")
|
||||||
var nUrl = url
|
|
||||||
if (url.startsWith("http") == false) {
|
|
||||||
nUrl = lastDomain
|
|
||||||
}
|
|
||||||
nUrl?.let { url ->
|
nUrl?.let { url ->
|
||||||
if (url.split("//").size > 1) {
|
if (url.split("//").size > 1) {
|
||||||
url.replace("//","/").replace("https:/","https://").let {
|
url.replace("//","/").replace("https:/","https://").let {
|
||||||
|
|||||||
@ -8,6 +8,14 @@ import android.provider.ContactsContract.PhoneLookup
|
|||||||
import java.util.Calendar
|
import java.util.Calendar
|
||||||
import java.util.Date
|
import java.util.Date
|
||||||
|
|
||||||
|
fun afterDay(date: Long): Long {
|
||||||
|
val cal: Calendar = Calendar.getInstance()
|
||||||
|
cal.setTime(Date(date))
|
||||||
|
cal.add(Calendar.HOUR_OF_DAY, 23)
|
||||||
|
cal.add(Calendar.MINUTE, 53)
|
||||||
|
return cal.timeInMillis
|
||||||
|
}
|
||||||
|
|
||||||
fun before30Min(date: Date): Long {
|
fun before30Min(date: Date): Long {
|
||||||
val cal: Calendar = Calendar.getInstance()
|
val cal: Calendar = Calendar.getInstance()
|
||||||
cal.setTime(date)
|
cal.setTime(date)
|
||||||
|
|||||||
@ -1,6 +1,6 @@
|
|||||||
package bums.lunatic.launcher.utils
|
package bums.lunatic.launcher.utils
|
||||||
|
|
||||||
import bums.lunatic.launcher.home.LauncherHome.Companion.lastedFinishedPageUrl
|
import bums.lunatic.launcher.home.RssHome.Companion.lastedFinishedPageUrl
|
||||||
import bums.lunatic.launcher.model.RssData
|
import bums.lunatic.launcher.model.RssData
|
||||||
import bums.lunatic.launcher.model.RssDataType
|
import bums.lunatic.launcher.model.RssDataType
|
||||||
import bums.lunatic.launcher.model.dateFormat
|
import bums.lunatic.launcher.model.dateFormat
|
||||||
|
|||||||
@ -23,6 +23,7 @@ import bums.lunatic.launcher.model.LocationLog
|
|||||||
import bums.lunatic.launcher.model.NotificationItem
|
import bums.lunatic.launcher.model.NotificationItem
|
||||||
import bums.lunatic.launcher.model.RssData
|
import bums.lunatic.launcher.model.RssData
|
||||||
import bums.lunatic.launcher.model.RssDataInterface
|
import bums.lunatic.launcher.model.RssDataInterface
|
||||||
|
import bums.lunatic.launcher.model.RssDataType
|
||||||
import bums.lunatic.launcher.model.TelegramBotUpdate
|
import bums.lunatic.launcher.model.TelegramBotUpdate
|
||||||
import bums.lunatic.launcher.model.TelegramChat
|
import bums.lunatic.launcher.model.TelegramChat
|
||||||
import bums.lunatic.launcher.model.TelegramData
|
import bums.lunatic.launcher.model.TelegramData
|
||||||
@ -33,6 +34,7 @@ import bums.lunatic.launcher.utils.Blog
|
|||||||
import bums.lunatic.launcher.utils.JamoUtils
|
import bums.lunatic.launcher.utils.JamoUtils
|
||||||
import bums.lunatic.launcher.utils.beforeDay
|
import bums.lunatic.launcher.utils.beforeDay
|
||||||
import bums.lunatic.launcher.utils.beforeOneDay
|
import bums.lunatic.launcher.utils.beforeOneDay
|
||||||
|
import com.google.gson.Gson
|
||||||
import io.realm.kotlin.Realm
|
import io.realm.kotlin.Realm
|
||||||
import io.realm.kotlin.RealmConfiguration
|
import io.realm.kotlin.RealmConfiguration
|
||||||
import io.realm.kotlin.UpdatePolicy
|
import io.realm.kotlin.UpdatePolicy
|
||||||
@ -86,9 +88,21 @@ object WorkersDb {
|
|||||||
getRealm().apply {
|
getRealm().apply {
|
||||||
this.writeBlocking {
|
this.writeBlocking {
|
||||||
try {
|
try {
|
||||||
if (query<RssData>("originPage == $0", rssData.originPage).find().isEmpty()) {
|
if (rssData.category().equals(RssDataType.PRIVATE)) {
|
||||||
this.copyToRealm(rssData, UpdatePolicy.ERROR)
|
this.copyToRealm(rssData, UpdatePolicy.ALL)
|
||||||
|
Blog.LOGE("rssData >> $rssData ${rssData.getScreen()}")
|
||||||
|
} else {
|
||||||
|
if (query<RssData>("originPage == $0", rssData.originPage).find()
|
||||||
|
.isEmpty()
|
||||||
|
) {
|
||||||
|
this.copyToRealm(rssData, UpdatePolicy.ERROR)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
try {
|
||||||
|
query<RssData>("originPage == $0",rssData.originPage).find()?.first()?.let {
|
||||||
|
Blog.LOGE("SAVED CHECK ${Gson().toJson(this.copyFromRealm(it))}")
|
||||||
|
}
|
||||||
|
}catch (e: Exception) {e.printStackTrace()}
|
||||||
} catch (e : Exception) {
|
} catch (e : Exception) {
|
||||||
|
|
||||||
}
|
}
|
||||||
@ -212,6 +226,9 @@ object WorkersDb {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fun getPrivate() = getRealm().query<RssData>().query("category == $0 ",
|
||||||
|
RssDataType.PRIVATE.name).distinct("originPage", "title").sort("pubDate", Sort.DESCENDING)
|
||||||
|
|
||||||
fun getVotedRss() = getRealm().query<RssData>().query("vote == $0", true).distinct("originPage", "title")
|
fun getVotedRss() = getRealm().query<RssData>().query("vote == $0", true).distinct("originPage", "title")
|
||||||
|
|
||||||
fun getDeleteQuery( ) : RealmQuery<RssData>{
|
fun getDeleteQuery( ) : RealmQuery<RssData>{
|
||||||
|
|||||||
@ -1,8 +1,8 @@
|
|||||||
<vector xmlns:android="http://schemas.android.com/apk/res/android"
|
<vector xmlns:android="http://schemas.android.com/apk/res/android"
|
||||||
android:width="24dp" android:height="24dp"
|
android:width="24dp" android:height="24dp"
|
||||||
android:viewportWidth="24" android:viewportHeight="24"
|
android:viewportWidth="24" android:viewportHeight="24"
|
||||||
android:tint="?attr/colorControlNormal">
|
android:tint="@color/white">
|
||||||
<path
|
<path
|
||||||
android:fillColor="?android:attr/textColorPrimary"
|
android:fillColor="@color/white"
|
||||||
android:pathData="M7.7,20.5Q6.775,20.5 6.163,19.887Q5.55,19.275 5.55,18.35V5.9H4.55V4.55H8.95V3.65H15.1V4.55H19.5V5.9H18.5V18.35Q18.5,19.275 17.888,19.887Q17.275,20.5 16.35,20.5ZM17.15,5.9H6.9V18.35Q6.9,18.7 7.125,18.925Q7.35,19.15 7.7,19.15H16.35Q16.65,19.15 16.9,18.9Q17.15,18.65 17.15,18.35ZM9.525,17.125H10.875V7.925H9.525ZM13.175,17.125H14.525V7.925H13.175ZM6.9,5.9V18.35Q6.9,18.7 6.9,18.925Q6.9,19.15 6.9,19.15Q6.9,19.15 6.9,18.925Q6.9,18.7 6.9,18.35Z"/>
|
android:pathData="M7.7,20.5Q6.775,20.5 6.163,19.887Q5.55,19.275 5.55,18.35V5.9H4.55V4.55H8.95V3.65H15.1V4.55H19.5V5.9H18.5V18.35Q18.5,19.275 17.888,19.887Q17.275,20.5 16.35,20.5ZM17.15,5.9H6.9V18.35Q6.9,18.7 7.125,18.925Q7.35,19.15 7.7,19.15H16.35Q16.65,19.15 16.9,18.9Q17.15,18.65 17.15,18.35ZM9.525,17.125H10.875V7.925H9.525ZM13.175,17.125H14.525V7.925H13.175ZM6.9,5.9V18.35Q6.9,18.7 6.9,18.925Q6.9,19.15 6.9,19.15Q6.9,19.15 6.9,18.925Q6.9,18.7 6.9,18.35Z"/>
|
||||||
</vector>
|
</vector>
|
||||||
|
|||||||
@ -1,45 +1,146 @@
|
|||||||
<?xml version="1.0" encoding="utf-8"?>
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
<androidx.constraintlayout.widget.ConstraintLayout
|
<layout xmlns:tools="http://schemas.android.com/tools">
|
||||||
xmlns:android="http://schemas.android.com/apk/res/android"
|
<androidx.constraintlayout.widget.ConstraintLayout
|
||||||
xmlns:app="http://schemas.android.com/apk/res-auto"
|
xmlns:android="http://schemas.android.com/apk/res/android"
|
||||||
xmlns:tools="http://schemas.android.com/tools"
|
xmlns:app="http://schemas.android.com/apk/res-auto"
|
||||||
android:background="@android:color/transparent"
|
android:background="@android:color/transparent"
|
||||||
android:layout_width="match_parent"
|
|
||||||
android:layout_height="match_parent">
|
|
||||||
|
|
||||||
<androidx.recyclerview.widget.RecyclerView
|
|
||||||
app:layoutManager="androidx.recyclerview.widget.LinearLayoutManager"
|
|
||||||
android:layout_margin="@dimen/default_layout_margin"
|
|
||||||
android:id="@+id/infoList"
|
|
||||||
android:layout_width="match_parent"
|
android:layout_width="match_parent"
|
||||||
android:layout_height="match_parent"
|
android:layout_height="match_parent">
|
||||||
android:overScrollMode="never"
|
|
||||||
android:padding="@dimen/default_padding"
|
<ImageButton
|
||||||
android:scrollbars="none"
|
app:layout_constraintTop_toTopOf="parent"
|
||||||
android:visibility="visible"
|
app:layout_constraintRight_toRightOf="parent"
|
||||||
app:layout_constraintLeft_toLeftOf="parent"
|
app:layout_constraintLeft_toLeftOf="parent"
|
||||||
app:layout_constraintRight_toRightOf="parent"
|
android:id="@+id/test"
|
||||||
app:layout_constraintTop_toTopOf="parent"
|
android:scaleType="fitCenter"
|
||||||
app:layout_constraintBottom_toBottomOf="parent"
|
android:adjustViewBounds="true"
|
||||||
/>
|
android:visibility="visible"
|
||||||
|
android:background="@null"
|
||||||
|
android:src="@drawable/ic_search"
|
||||||
|
android:layout_width="40dp"
|
||||||
|
android:tint="@color/white"
|
||||||
|
android:foregroundTint="@color/white"
|
||||||
|
tools:ignore="ContentDescription,UseAppTint"
|
||||||
|
android:layout_height="40dp" />
|
||||||
|
|
||||||
|
<ImageButton
|
||||||
|
app:layout_constraintTop_toTopOf="parent"
|
||||||
|
app:layout_constraintRight_toRightOf="parent"
|
||||||
|
android:id="@+id/vote"
|
||||||
|
android:scaleType="fitCenter"
|
||||||
|
android:adjustViewBounds="true"
|
||||||
|
android:visibility="visible"
|
||||||
|
android:background="@null"
|
||||||
|
android:src="@drawable/saved"
|
||||||
|
android:layout_width="40dp"
|
||||||
|
tools:ignore="ContentDescription"
|
||||||
|
android:layout_height="40dp" />
|
||||||
|
|
||||||
|
<ImageButton
|
||||||
|
android:id="@+id/hide"
|
||||||
|
app:layout_constraintTop_toTopOf="parent"
|
||||||
|
app:layout_constraintRight_toLeftOf="@id/vote"
|
||||||
|
android:src="@drawable/ic_delete"
|
||||||
|
android:tintMode="multiply"
|
||||||
|
android:layout_marginLeft="12dp"
|
||||||
|
android:scaleType="fitCenter"
|
||||||
|
android:background="@null"
|
||||||
|
android:layout_width="40dp"
|
||||||
|
android:visibility="visible"
|
||||||
|
android:adjustViewBounds="true"
|
||||||
|
tools:ignore="ContentDescription"
|
||||||
|
android:layout_height="40dp"
|
||||||
|
/>
|
||||||
|
|
||||||
|
<ImageButton
|
||||||
|
android:id="@+id/home"
|
||||||
|
app:layout_constraintTop_toTopOf="parent"
|
||||||
|
app:layout_constraintLeft_toLeftOf="parent"
|
||||||
|
android:src="@drawable/home"
|
||||||
|
android:tintMode="multiply"
|
||||||
|
android:scaleType="fitCenter"
|
||||||
|
android:background="@null"
|
||||||
|
android:layout_width="40dp"
|
||||||
|
android:adjustViewBounds="true"
|
||||||
|
android:layout_height="40dp"
|
||||||
|
app:tint="@color/white"
|
||||||
|
tools:ignore="ContentDescription" />
|
||||||
|
|
||||||
|
<ImageButton
|
||||||
|
android:id="@+id/bookmark"
|
||||||
|
app:layout_constraintTop_toTopOf="parent"
|
||||||
|
app:layout_constraintLeft_toRightOf="@id/home"
|
||||||
|
android:src="@drawable/bookmark"
|
||||||
|
android:scaleType="fitCenter"
|
||||||
|
android:background="@null"
|
||||||
|
android:layout_width="40dp"
|
||||||
|
android:adjustViewBounds="true"
|
||||||
|
tools:ignore="ContentDescription"
|
||||||
|
android:layout_height="40dp"/>
|
||||||
|
<ImageButton
|
||||||
|
android:layout_marginLeft="10dp"
|
||||||
|
android:id="@+id/prv"
|
||||||
|
app:layout_constraintBottom_toBottomOf="@id/bookmark"
|
||||||
|
app:layout_constraintLeft_toRightOf="@id/bookmark"
|
||||||
|
android:src="@drawable/bookmark"
|
||||||
|
android:scaleType="fitCenter"
|
||||||
|
android:background="@null"
|
||||||
|
android:layout_width="10dp"
|
||||||
|
android:alpha="0.2"
|
||||||
|
android:tint="@color/finestSilver"
|
||||||
|
android:adjustViewBounds="true"
|
||||||
|
tools:ignore="ContentDescription"
|
||||||
|
android:layout_height="10dp"/>
|
||||||
|
|
||||||
|
<androidx.recyclerview.widget.RecyclerView
|
||||||
|
app:layoutManager="androidx.recyclerview.widget.LinearLayoutManager"
|
||||||
|
android:layout_margin="@dimen/default_layout_margin"
|
||||||
|
android:id="@+id/infoList"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:overScrollMode="never"
|
||||||
|
android:padding="@dimen/default_padding"
|
||||||
|
android:scrollbars="none"
|
||||||
|
android:visibility="visible"
|
||||||
|
app:layout_constraintLeft_toLeftOf="parent"
|
||||||
|
app:layout_constraintRight_toRightOf="parent"
|
||||||
|
app:layout_constraintTop_toBottomOf="@id/bookmark"
|
||||||
|
android:layout_height="0dp"
|
||||||
|
app:layout_constraintBottom_toBottomOf="parent"
|
||||||
|
/>
|
||||||
|
|
||||||
|
|
||||||
<bums.lunatic.launcher.home.GeckoWeb
|
<bums.lunatic.launcher.home.GeckoWeb
|
||||||
android:id="@+id/geckoWeb"
|
android:id="@+id/geckoWeb"
|
||||||
android:visibility="gone"
|
android:visibility="gone"
|
||||||
android:layout_width="match_parent"
|
android:layout_width="match_parent"
|
||||||
android:layout_height="match_parent"
|
app:layout_constraintBottom_toBottomOf="parent"
|
||||||
/>
|
app:layout_constraintLeft_toLeftOf="parent"
|
||||||
<ProgressBar
|
app:layout_constraintRight_toRightOf="parent"
|
||||||
app:layout_constraintTop_toTopOf="@id/geckoWeb"
|
app:layout_constraintTop_toBottomOf="@id/bookmark"
|
||||||
app:layout_constraintLeft_toLeftOf="@id/geckoWeb"
|
android:layout_height="0dp"
|
||||||
app:layout_constraintRight_toRightOf="@id/geckoWeb"
|
/>
|
||||||
android:id="@+id/progressBar"
|
|
||||||
style="?android:attr/progressBarStyleHorizontal"
|
<include layout="@layout/layout_rss_summary"
|
||||||
android:layout_width="0dp"
|
android:id="@+id/layout_rss_summary"
|
||||||
android:layout_height="4dp"
|
android:layout_width="match_parent"
|
||||||
android:max="100"
|
android:visibility="gone"
|
||||||
android:progress="0"
|
app:layout_constraintBottom_toBottomOf="parent"
|
||||||
android:visibility="visible"
|
app:layout_constraintLeft_toLeftOf="parent"
|
||||||
android:indeterminate="false"/>
|
app:layout_constraintRight_toRightOf="parent"
|
||||||
</androidx.constraintlayout.widget.ConstraintLayout>
|
app:layout_constraintTop_toBottomOf="@id/bookmark"
|
||||||
|
android:layout_height="0dp"/>
|
||||||
|
|
||||||
|
<ProgressBar
|
||||||
|
app:layout_constraintTop_toTopOf="@id/geckoWeb"
|
||||||
|
app:layout_constraintLeft_toLeftOf="@id/geckoWeb"
|
||||||
|
app:layout_constraintRight_toRightOf="@id/geckoWeb"
|
||||||
|
android:id="@+id/progressBar"
|
||||||
|
style="?android:attr/progressBarStyleHorizontal"
|
||||||
|
android:layout_width="0dp"
|
||||||
|
android:layout_height="4dp"
|
||||||
|
android:max="100"
|
||||||
|
android:progress="0"
|
||||||
|
android:visibility="visible"
|
||||||
|
android:indeterminate="false"/>
|
||||||
|
</androidx.constraintlayout.widget.ConstraintLayout>
|
||||||
|
</layout>
|
||||||
68
app/src/main/res/layout/layout_rss_summary.xml
Normal file
68
app/src/main/res/layout/layout_rss_summary.xml
Normal file
@ -0,0 +1,68 @@
|
|||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<layout xmlns:tools="http://schemas.android.com/tools"
|
||||||
|
xmlns:android="http://schemas.android.com/apk/res/android"
|
||||||
|
xmlns:app="http://schemas.android.com/apk/res-auto">
|
||||||
|
<data>
|
||||||
|
<import type="bums.lunatic.launcher.model.RssData"/>
|
||||||
|
<variable
|
||||||
|
name="rss"
|
||||||
|
type="bums.lunatic.launcher.model.RssData" />
|
||||||
|
</data>
|
||||||
|
<FrameLayout
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="match_parent">
|
||||||
|
<ScrollView
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="match_parent"
|
||||||
|
tools:ignore="UselessParent">
|
||||||
|
<LinearLayout
|
||||||
|
android:layout_gravity="center"
|
||||||
|
android:gravity="center"
|
||||||
|
android:orientation="vertical"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="wrap_content">
|
||||||
|
<TextView
|
||||||
|
android:id="@+id/title"
|
||||||
|
android:singleLine="false"
|
||||||
|
android:lines="0"
|
||||||
|
android:background="#000"
|
||||||
|
android:textSize="@dimen/_20sp"
|
||||||
|
android:textColor="@color/white"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="150dp"/>
|
||||||
|
<ImageView
|
||||||
|
android:alpha="0.05"
|
||||||
|
android:id="@+id/cover"
|
||||||
|
android:adjustViewBounds="true"
|
||||||
|
app:layout_constraintLeft_toLeftOf="parent"
|
||||||
|
app:layout_constraintTop_toTopOf="parent"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="wrap_content"/>
|
||||||
|
<TextView
|
||||||
|
android:id="@+id/desc"
|
||||||
|
android:singleLine="false"
|
||||||
|
android:lines="0"
|
||||||
|
android:background="#000"
|
||||||
|
android:textSize="@dimen/_20sp"
|
||||||
|
android:textColor="@color/white"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="150dp"/>
|
||||||
|
<ImageView
|
||||||
|
android:id="@+id/screen"
|
||||||
|
android:alpha="0.05"
|
||||||
|
android:adjustViewBounds="true"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="wrap_content"/>
|
||||||
|
<TextView
|
||||||
|
android:id="@+id/link"
|
||||||
|
android:singleLine="false"
|
||||||
|
android:lines="0"
|
||||||
|
android:background="#000"
|
||||||
|
android:textSize="@dimen/_20sp"
|
||||||
|
android:textColor="@color/white"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="150dp"/>
|
||||||
|
</LinearLayout>
|
||||||
|
</ScrollView>
|
||||||
|
</FrameLayout>
|
||||||
|
</layout>
|
||||||
Loading…
x
Reference in New Issue
Block a user