...
This commit is contained in:
parent
416279a11f
commit
57039939fd
@ -55,6 +55,13 @@ port.onMessage.addListener(response => {
|
|||||||
var type= response["type"];
|
var type= response["type"];
|
||||||
|
|
||||||
switch (type) {
|
switch (type) {
|
||||||
|
case "SCROLL_TOP": {
|
||||||
|
window.scrollTo({
|
||||||
|
top: 0,
|
||||||
|
behavior: 'smooth'
|
||||||
|
});
|
||||||
|
}
|
||||||
|
break;
|
||||||
case "SEEK_NEXT": // 5초 앞으로
|
case "SEEK_NEXT": // 5초 앞으로
|
||||||
{
|
{
|
||||||
let btn =
|
let btn =
|
||||||
|
|||||||
@ -129,6 +129,10 @@ open class GeckoWeb @JvmOverloads constructor(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fun scrollTop() {
|
||||||
|
sendJsonMsg("SCROLL_TOP")
|
||||||
|
}
|
||||||
|
|
||||||
// UI & State
|
// UI & State
|
||||||
var decoViews = arrayListOf<View>()
|
var decoViews = arrayListOf<View>()
|
||||||
var progress: ProgressBar? = null
|
var progress: ProgressBar? = null
|
||||||
@ -297,29 +301,6 @@ open class GeckoWeb @JvmOverloads constructor(
|
|||||||
}
|
}
|
||||||
} catch (e: Exception) {
|
} catch (e: Exception) {
|
||||||
Blog.LOGE("Download Check Error", e)
|
Blog.LOGE("Download Check Error", e)
|
||||||
|
|
||||||
// val msg = e.message ?: ""
|
|
||||||
|
|
||||||
// if (msg.contains("parse video information") && !lastCheckUrlS.contains(cleanUrl)) {
|
|
||||||
// CoroutineScope(Dispatchers.Main).launch {
|
|
||||||
// CoroutineScope(Dispatchers.Main).launch {
|
|
||||||
// decoViews.firstOrNull { it.id == R.id.btn_dl_video }?.let { view ->
|
|
||||||
// view.setOnClickListener {
|
|
||||||
// AlertDialog.Builder(context)
|
|
||||||
// .setTitle("음악 전용으로 재시도?")
|
|
||||||
// .setMessage("parse 에러 발생. forMusic=true로 재시도합니다.")
|
|
||||||
// .setPositiveButton("오키") { _, _ ->
|
|
||||||
// checkIfDownloadable(cleanUrl, true)
|
|
||||||
// }
|
|
||||||
// .setNegativeButton("취소", null)
|
|
||||||
// .show()
|
|
||||||
// lastCheckUrlS.add(cleanUrl)
|
|
||||||
// }
|
|
||||||
// }
|
|
||||||
// }
|
|
||||||
//
|
|
||||||
// }
|
|
||||||
// }
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -398,7 +379,6 @@ open class GeckoWeb @JvmOverloads constructor(
|
|||||||
url?.let {
|
url?.let {
|
||||||
if (it.contains(getFilterF()) && privateMode) this@GeckoWeb.visibility = View.INVISIBLE
|
if (it.contains(getFilterF()) && privateMode) this@GeckoWeb.visibility = View.INVISIBLE
|
||||||
lastedUrl = if (it.split("//").size > 1) it.replace("//", "/").replace("https:/", "https://") else it
|
lastedUrl = if (it.split("//").size > 1) it.replace("//", "/").replace("https:/", "https://") else it
|
||||||
checkIfDownloadable(it)
|
|
||||||
onLocationChangeCallback?.invoke(it) // 외부 콜백
|
onLocationChangeCallback?.invoke(it) // 외부 콜백
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -435,7 +415,7 @@ open class GeckoWeb @JvmOverloads constructor(
|
|||||||
|
|
||||||
}
|
}
|
||||||
override fun onCanGoBack(session: GeckoSession, canGoBack: Boolean) {
|
override fun onCanGoBack(session: GeckoSession, canGoBack: Boolean) {
|
||||||
Blog.LOGE("onCanGoBack $canGoBack ${session}")
|
// Blog.LOGE("onCanGoBack $canGoBack ${session}")
|
||||||
this@GeckoWeb.canGoBack = canGoBack
|
this@GeckoWeb.canGoBack = canGoBack
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -469,21 +449,19 @@ open class GeckoWeb @JvmOverloads constructor(
|
|||||||
saveCurrentSessionState()
|
saveCurrentSessionState()
|
||||||
}
|
}
|
||||||
onPageStartCallback?.invoke(url)
|
onPageStartCallback?.invoke(url)
|
||||||
// Blog.LOGE("onPageStart $url ${session}")
|
|
||||||
checkIfDownloadable(url)
|
|
||||||
}
|
}
|
||||||
override fun onPageStop(session: GeckoSession, success: Boolean) {
|
override fun onPageStop(session: GeckoSession, success: Boolean) {
|
||||||
onPageStopCallback?.invoke(success)
|
onPageStopCallback?.invoke(success)
|
||||||
if (success) {
|
if (success) {
|
||||||
saveCurrentSessionState()
|
saveCurrentSessionState()
|
||||||
}
|
}
|
||||||
Blog.LOGE("onPageStop $success ${session}")
|
// Blog.LOGE("onPageStop $success ${session}")
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun onSessionStateChange(session: GeckoSession, sessionState: GeckoSession.SessionState) {
|
override fun onSessionStateChange(session: GeckoSession, sessionState: GeckoSession.SessionState) {
|
||||||
lastSessionState = sessionState
|
lastSessionState = sessionState
|
||||||
onSessionStateChangeCallback?.invoke(sessionState)
|
onSessionStateChangeCallback?.invoke(sessionState)
|
||||||
Blog.LOGE("onSessionStateChange $sessionState ${session}")
|
// Blog.LOGE("onSessionStateChange $sessionState ${session}")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
private var lastSessionState: GeckoSession.SessionState? = null
|
private var lastSessionState: GeckoSession.SessionState? = null
|
||||||
@ -634,15 +612,16 @@ open class GeckoWeb @JvmOverloads constructor(
|
|||||||
private fun handlePortMessage(msg: PortMessage) {
|
private fun handlePortMessage(msg: PortMessage) {
|
||||||
when (msg.type) {
|
when (msg.type) {
|
||||||
"COOKIES_REPORT"-> {
|
"COOKIES_REPORT"-> {
|
||||||
Blog.LOGE("${msg.value} -> ${msg.url}")
|
// Blog.LOGE("${msg.value} -> ${msg.url}")
|
||||||
currentCookieString = msg.value ?: ""
|
currentCookieString = msg.value ?: ""
|
||||||
currentCookieUrlString = msg.url ?: ""
|
currentCookieUrlString = msg.url ?: ""
|
||||||
CoroutineScope(Dispatchers.IO).launch {
|
CoroutineScope(Dispatchers.IO).launch {
|
||||||
saveYoutubeCookiesToFile()
|
saveYoutubeCookiesToFile()
|
||||||
}
|
}
|
||||||
|
checkIfDownloadable(currentCookieUrlString)
|
||||||
}
|
}
|
||||||
"SCROLL_STATE" -> {
|
"SCROLL_STATE" -> {
|
||||||
Blog.LOGE("${msg.type} : ${msg.value}")
|
// Blog.LOGE("${msg.type} : ${msg.value}")
|
||||||
scrollState = msg.value?.toInt() ?: 0
|
scrollState = msg.value?.toInt() ?: 0
|
||||||
}
|
}
|
||||||
"allImagesFound" -> lastedUrl?.let { startBookmarkSaveProcessForMultipleImages(it, msg.urls) }
|
"allImagesFound" -> lastedUrl?.let { startBookmarkSaveProcessForMultipleImages(it, msg.urls) }
|
||||||
|
|||||||
@ -35,7 +35,9 @@ class LunaticBrowserLayout @JvmOverloads constructor(
|
|||||||
context.startActivity(Intent.createChooser(intent, "공유"))
|
context.startActivity(Intent.createChooser(intent, "공유"))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
binding.tvTitle.setOnClickListener {
|
||||||
|
geckoWeb.scrollTop()
|
||||||
|
}
|
||||||
// GeckoWeb 내부에서 주소 등 업데이트 시 연동되도록 등록
|
// GeckoWeb 내부에서 주소 등 업데이트 시 연동되도록 등록
|
||||||
geckoWeb.decoViews.addAll(listOf(
|
geckoWeb.decoViews.addAll(listOf(
|
||||||
binding.tvAddress, binding.btnDlVideo, binding.btnReload, binding.btnBack, binding.tvTitle
|
binding.tvAddress, binding.btnDlVideo, binding.btnReload, binding.btnBack, binding.tvTitle
|
||||||
|
|||||||
@ -17,6 +17,8 @@ import java.io.File
|
|||||||
|
|
||||||
class MyWallpaperService : WallpaperService() {
|
class MyWallpaperService : WallpaperService() {
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
private val TAG = "MyWallpaperService"
|
private val TAG = "MyWallpaperService"
|
||||||
|
|
||||||
override fun onCreateEngine(): Engine {
|
override fun onCreateEngine(): Engine {
|
||||||
@ -187,7 +189,7 @@ class MyWallpaperService : WallpaperService() {
|
|||||||
Log.d(TAG, "Initializing Renderer...")
|
Log.d(TAG, "Initializing Renderer...")
|
||||||
nativeRenderer = NativeRenderer()
|
nativeRenderer = NativeRenderer()
|
||||||
nativeRenderer?.initialize() // nativeInit() -> initialize()
|
nativeRenderer?.initialize() // nativeInit() -> initialize()
|
||||||
nativeRenderer?.setFadeDuration(1500)
|
nativeRenderer?.setFadeDuration(3000)
|
||||||
nativeRenderer?.setTurnPageDuration(8000)
|
nativeRenderer?.setTurnPageDuration(8000)
|
||||||
nativeRenderer?.setAnimationMode(NativeRenderer.ANIMATION_MODE_PAN)
|
nativeRenderer?.setAnimationMode(NativeRenderer.ANIMATION_MODE_PAN)
|
||||||
nativeRenderer?.setTransitionMode(NativeRenderer.TRANSITION_MODE_FADE)
|
nativeRenderer?.setTransitionMode(NativeRenderer.TRANSITION_MODE_FADE)
|
||||||
@ -199,23 +201,22 @@ class MyWallpaperService : WallpaperService() {
|
|||||||
handler.post { loadMediaFiles() }
|
handler.post { loadMediaFiles() }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
// ... loadMediaFiles, nextMediaCallback, getFdFromPath는 이전과 동일 ...
|
|
||||||
private fun loadMediaFiles() {
|
val requiredSizeRatio = 0.5
|
||||||
|
|
||||||
|
fun loadFiles() {
|
||||||
if (!mediaDir.exists()) mediaDir.mkdirs()
|
if (!mediaDir.exists()) mediaDir.mkdirs()
|
||||||
// mediaFiles = mediaDir.listFiles()
|
|
||||||
// ?.filter { supportedExtensions.contains(it.extension.lowercase()) }
|
|
||||||
// ?.toList() ?: emptyList()
|
|
||||||
|
|
||||||
Log.d(TAG, "Found ${mediaFiles.size} media files.")
|
Log.d(TAG, "Found ${mediaFiles.size} media files.")
|
||||||
|
|
||||||
val allFiles = mediaDir.listFiles()
|
val allFiles = mediaDir.listFiles().filter { supportedExtensions.contains(it.extension) }
|
||||||
val trashFolder = File(mediaDir, "low_res_backup")
|
val trashFolder = File(mediaDir, "low_res_backup")
|
||||||
if (!trashFolder.exists()) trashFolder.mkdirs()
|
if (!trashFolder.exists()) trashFolder.mkdirs()
|
||||||
val invalidImages = mutableListOf<File>()
|
val invalidImages = mutableListOf<File>()
|
||||||
val wm = WallpaperManager.getInstance(this@MyWallpaperService)
|
val wm = WallpaperManager.getInstance(this@MyWallpaperService)
|
||||||
val minWidth = wm.desiredMinimumWidth
|
val minWidth = wm.desiredMinimumWidth
|
||||||
val minHeight = wm.desiredMinimumHeight
|
val minHeight = wm.desiredMinimumHeight
|
||||||
val requiredSize = Math.max(minWidth, minHeight).times(0.6)
|
val requiredSize = Math.max(minWidth, minHeight).times(requiredSizeRatio)
|
||||||
for (file in allFiles) {
|
for (file in allFiles) {
|
||||||
|
|
||||||
if (file.isFile && (file.extension.equals("jpg", true) ||
|
if (file.isFile && (file.extension.equals("jpg", true) ||
|
||||||
@ -240,7 +241,10 @@ class MyWallpaperService : WallpaperService() {
|
|||||||
val targetFile = File(trashFolder, file.name)
|
val targetFile = File(trashFolder, file.name)
|
||||||
file.renameTo(targetFile) // 파일 이동
|
file.renameTo(targetFile) // 파일 이동
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun loadMediaFiles() {
|
||||||
|
loadFiles()
|
||||||
if (mediaFiles.isNotEmpty()) {
|
if (mediaFiles.isNotEmpty()) {
|
||||||
val initialFile = mediaFiles.random()
|
val initialFile = mediaFiles.random()
|
||||||
Log.d(TAG, "Attempting to load initial random media via preloader: ${initialFile.absolutePath}")
|
Log.d(TAG, "Attempting to load initial random media via preloader: ${initialFile.absolutePath}")
|
||||||
@ -256,48 +260,7 @@ class MyWallpaperService : WallpaperService() {
|
|||||||
|
|
||||||
private val nextMediaCallback = object : NativeRenderer.NextMediaCallback {
|
private val nextMediaCallback = object : NativeRenderer.NextMediaCallback {
|
||||||
override fun onNextMediaRequested() {
|
override fun onNextMediaRequested() {
|
||||||
|
loadFiles()
|
||||||
if (!mediaDir.exists()) mediaDir.mkdirs()
|
|
||||||
|
|
||||||
|
|
||||||
// mediaFiles = mediaDir.listFiles()
|
|
||||||
// ?.filter { supportedExtensions.contains(it.extension.lowercase()) }
|
|
||||||
// ?.toList() ?: emptyList()
|
|
||||||
|
|
||||||
val allFiles = mediaDir.listFiles()
|
|
||||||
val trashFolder = File(mediaDir, "low_res_backup")
|
|
||||||
if (!trashFolder.exists()) trashFolder.mkdirs()
|
|
||||||
// val validImages = mutableListOf<File>()
|
|
||||||
val invalidImages = mutableListOf<File>()
|
|
||||||
val wm = WallpaperManager.getInstance(this@MyWallpaperService)
|
|
||||||
val minWidth = wm.desiredMinimumWidth
|
|
||||||
val minHeight = wm.desiredMinimumHeight
|
|
||||||
val requiredSize = Math.max(minWidth, minHeight).times(0.6)
|
|
||||||
for (file in allFiles) {
|
|
||||||
|
|
||||||
if (file.isFile && (file.extension.equals("jpg", true) ||
|
|
||||||
file.extension.equals("png", true) ||
|
|
||||||
file.extension.equals("jpeg", true) ||
|
|
||||||
file.extension.equals("bmp", true) || // BMP 추가
|
|
||||||
file.extension.equals("webp", true))) {
|
|
||||||
|
|
||||||
val options = BitmapFactory.Options().apply { inJustDecodeBounds = true }
|
|
||||||
BitmapFactory.decodeFile(file.absolutePath, options)
|
|
||||||
Blog.LOGE("requiredSize ${requiredSize} w :${options.outWidth} , h : ${options.outHeight}")
|
|
||||||
if (options.outWidth >= requiredSize && options.outHeight >= requiredSize) {
|
|
||||||
mediaFiles.add(file)
|
|
||||||
} else {
|
|
||||||
invalidImages.add(file) // 조건 미달
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// 2. 부적합 이미지 이동 처리 (Job 밖에서 따로 돌려도 무방)
|
|
||||||
invalidImages.forEach { file ->
|
|
||||||
val targetFile = File(trashFolder, file.name)
|
|
||||||
file.renameTo(targetFile) // 파일 이동
|
|
||||||
}
|
|
||||||
|
|
||||||
val nextFile = mediaFiles.random()
|
val nextFile = mediaFiles.random()
|
||||||
Log.d(TAG, "Callback: Preloading next random media: ${nextFile.absolutePath}")
|
Log.d(TAG, "Callback: Preloading next random media: ${nextFile.absolutePath}")
|
||||||
|
|
||||||
|
|||||||
@ -96,6 +96,8 @@ open class NativeRenderer {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
// --- Private JNI declarations ---
|
// --- Private JNI declarations ---
|
||||||
private external fun nativeStartRenderLoop(nativeHandle: Long, surface: Surface)
|
private external fun nativeStartRenderLoop(nativeHandle: Long, surface: Surface)
|
||||||
private external fun nativeStopRenderLoop(nativeHandle: Long)
|
private external fun nativeStopRenderLoop(nativeHandle: Long)
|
||||||
|
|||||||
@ -11,7 +11,7 @@
|
|||||||
android:layout_height="40dp"
|
android:layout_height="40dp"
|
||||||
android:orientation="horizontal"
|
android:orientation="horizontal"
|
||||||
android:gravity="center_vertical"
|
android:gravity="center_vertical"
|
||||||
android:background="#CC000000"
|
android:background="#D000"
|
||||||
app:layout_constraintTop_toTopOf="parent">
|
app:layout_constraintTop_toTopOf="parent">
|
||||||
|
|
||||||
<TextView android:id="@+id/btn_home" android:text="home" style="@style/MaterialIconButtonStyle" />
|
<TextView android:id="@+id/btn_home" android:text="home" style="@style/MaterialIconButtonStyle" />
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user