This commit is contained in:
lunaticbum 2025-09-23 15:37:38 +09:00
parent f794e24f24
commit a4e21be0ec
47 changed files with 1734 additions and 2686 deletions

View File

@ -155,6 +155,7 @@ dependencies {
implementation("io.github.junkfood02.youtubedl-android:ffmpeg:0.17.4") implementation("io.github.junkfood02.youtubedl-android:ffmpeg:0.17.4")
implementation("io.github.junkfood02.youtubedl-android:aria2c:0.17.4") implementation("io.github.junkfood02.youtubedl-android:aria2c:0.17.4")
implementation("io.coil-kt:coil:2.5.0") implementation("io.coil-kt:coil:2.5.0")
implementation("io.coil-kt:coil-gif:2.5.0")
implementation ("com.squareup.okhttp3:logging-interceptor:4.11.0") implementation ("com.squareup.okhttp3:logging-interceptor:4.11.0")
implementation("androidx.lifecycle:lifecycle-viewmodel-ktx:2.8.3") implementation("androidx.lifecycle:lifecycle-viewmodel-ktx:2.8.3")

View File

@ -0,0 +1,186 @@
<!DOCTYPE html>
<html lang="ko">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Synology Photos Random Slideshow</title>
<style>
/* 기본 스타일링 */
body, html {
margin: 0;
padding: 0;
width: 100%;
height: 100%;
background-color: #000;
color: #fff;
font-family: sans-serif;
display: flex;
align-items: center;
justify-content: center;
overflow: hidden;
}
/* 로그인 화면 스타일 */
#login-form {
display: flex;
flex-direction: column;
gap: 15px;
padding: 30px;
background: #222;
border-radius: 8px;
}
#login-form input {
padding: 10px;
border: 1px solid #444;
background: #333;
color: #fff;
border-radius: 4px;
}
#login-form button {
padding: 10px;
background: #007bff;
border: none;
color: white;
cursor: pointer;
border-radius: 4px;
}
/* 사진이 표시될 컨테이너 */
#photo-container {
width: 100%;
height: 100%;
display: none; /* 처음에는 숨김 */
align-items: center;
justify-content: center;
}
/* 이미지 스타일 */
#slideshow-image {
max-width: 100%;
max-height: 100%;
object-fit: contain; /* 이미지 비율 유지 */
/* 부드러운 전환 효과 */
opacity: 0;
transition: opacity 1.5s ease-in-out;
}
</style>
</head>
<body>
<div id="login-form">
<h2>시놀로지 포토 로그인</h2>
<input type="text" id="nas-address" placeholder="NAS 주소 (예: 192.168.0.100)">
<input type="text" id="username" placeholder="사용자 ID">
<input type="password" id="password" placeholder="비밀번호">
<button onclick="startSlideshow()">슬라이드쇼 시작</button>
<p id="message" style="color: #ffdddd; text-align: center;"></p>
</div>
<div id="photo-container">
<img id="slideshow-image" alt="Loading photo...">
</div>
<script>
// 전역 변수 설정
let sid = '';
let nasAddress = '';
const allPhotoIds = [];
let slideshowInterval;
// 메시지 표시 함수
function showMessage(msg) {
document.getElementById('message').innerText = msg;
}
// 슬라이드쇼 시작 함수
async function startSlideshow() {
nasAddress = document.getElementById('nas-address').value.trim();
const username = document.getElementById('username').value.trim();
const password = document.getElementById('password').value;
if (!nasAddress || !username || !password) {
showMessage('모든 정보를 입력해주세요.');
return;
}
showMessage('로그인 중...');
try {
// 1. 로그인하여 세션 ID (sid) 얻기
const loginUrl = `https://${nasAddress}/webapi/auth.cgi?api=SYNO.API.Auth&version=7&method=login&account=${username}&passwd=${password}&session=SynologyPhotos&format=sid`;
const loginResponse = await fetch(loginUrl,{
mode: 'no-cors'
});
const loginData = await loginResponse.json();
if (loginData.success && loginData.data.sid) {
sid = loginData.data.sid;
showMessage('로그인 성공! 사진 목록을 가져옵니다...');
// 2. 전체 사진 목록 가져오기
await fetchAllPhotos(0);
} else {
showMessage('로그인 실패. 정보를 확인하세요.');
}
} catch (error) {
console.error('Error:', error);
showMessage('오류 발생. NAS 주소를 확인하세요.');
}
}
// 재귀적으로 모든 사진 ID를 가져오는 함수
async function fetchAllPhotos(offset) {
const limit = 5000; // 한 번에 5000개씩 요청
const listUrl = `https://${nasAddress}/webapi/entry.cgi?api=SYNO.Foto.Browse.Item&version=1&method=list&limit=${limit}&offset=${offset}&_sid=${sid}`;
const response = await fetch(listUrl);
const data = await response.json();
if (data.success) {
data.data.list.forEach(item => allPhotoIds.push(item.id));
const total = data.data.total;
if (offset + limit < total) {
// 받아올 사진이 더 있다면 다음 페이지 요청
showMessage(`${allPhotoIds.length} / ${total} 장 로딩...`);
await fetchAllPhotos(offset + limit);
} else {
// 모든 사진을 다 받아왔다면 슬라이드쇼 시작
showMessage('사진 로딩 완료! 슬라이드쇼를 시작합니다.');
document.getElementById('login-form').style.display = 'none';
document.getElementById('photo-container').style.display = 'flex';
displayRandomPhoto(); // 첫 사진 표시
// 10초마다 사진 변경
slideshowInterval = setInterval(displayRandomPhoto, 10000);
}
} else {
showMessage('사진 목록 가져오기 실패.');
}
}
// 랜덤 사진을 화면에 표시하는 함수
function displayRandomPhoto() {
if (allPhotoIds.length === 0) return;
// 랜덤하게 사진 ID 하나 선택
const randomIndex = Math.floor(Math.random() * allPhotoIds.length);
const photoId = allPhotoIds[randomIndex];
// 이미지 다운로드 URL 생성
const imageUrl = `https://${nasAddress}/webapi/entry.cgi?api=SYNO.Foto.Download&version=1&method=download&force_download=true&item_id=%5B${photoId}%5D&_sid=${sid}`;
const imageElement = document.getElementById('slideshow-image');
// 이미지 Fade out
imageElement.style.opacity = 0;
// 이미지가 완전히 사라진 후 새 이미지 로딩
setTimeout(() => {
imageElement.src = imageUrl;
// 새 이미지 로딩이 완료되면 Fade in
imageElement.onload = () => {
imageElement.style.opacity = 1;
};
}, 1500); // transition 시간과 동일하게 설정
}
</script>
</body>
</html>

View File

@ -405,6 +405,9 @@ class BookmarkApiService {
val pageType = object : TypeToken<Page<WebBookmark>>() {}.type val pageType = object : TypeToken<Page<WebBookmark>>() {}.type
val page: Page<WebBookmark> = Gson().fromJson(responseJson, pageType) val page: Page<WebBookmark> = Gson().fromJson(responseJson, pageType)
println("✅ 북마크 ${page.content.size}개 로딩 성공!") println("✅ 북마크 ${page.content.size}개 로딩 성공!")
page.content.forEach {
println("it.images >>> ${it.images}")
}
return@withContext page.content // Page 객체에서 실제 북마크 목록만 반환 return@withContext page.content // Page 객체에서 실제 북마크 목록만 반환
} }
return@withContext null return@withContext null

View File

@ -67,10 +67,8 @@ import bums.lunatic.launcher.tokiz.Comics
import bums.lunatic.launcher.tokiz.Magnet import bums.lunatic.launcher.tokiz.Magnet
import bums.lunatic.launcher.tokiz.Novels import bums.lunatic.launcher.tokiz.Novels
import bums.lunatic.launcher.tokiz.Perplexity import bums.lunatic.launcher.tokiz.Perplexity
import bums.lunatic.launcher.tokiz.Twitter
import bums.lunatic.launcher.tokiz.Webtoons import bums.lunatic.launcher.tokiz.Webtoons
import bums.lunatic.launcher.tokiz.YouTube import bums.lunatic.launcher.tokiz.YouTube
import bums.lunatic.launcher.tokiz.Zota
import bums.lunatic.launcher.utils.Blog import bums.lunatic.launcher.utils.Blog
import bums.lunatic.launcher.workers.WorkersDb import bums.lunatic.launcher.workers.WorkersDb
import com.google.android.material.color.DynamicColors import com.google.android.material.color.DynamicColors
@ -511,7 +509,7 @@ open class LauncherActivity : CommonActivity() {
R.id.webtoons ->{ R.id.webtoons ->{
supportFragmentManager.beginTransaction() supportFragmentManager.beginTransaction()
.replace(R.id.fragment_container, BookmarkPagerFragment()) .replace(R.id.fragment_container, Webtoons())
.commit() .commit()
} }
R.id.comics ->{ R.id.comics ->{
@ -531,14 +529,10 @@ open class LauncherActivity : CommonActivity() {
} }
R.id.zota ->{ R.id.zota ->{
supportFragmentManager.beginTransaction() supportFragmentManager.beginTransaction()
.replace(R.id.fragment_container, Zota()) .replace(R.id.fragment_container, BookmarkPagerFragment())
.commit()
}
R.id.twitter ->{
supportFragmentManager.beginTransaction()
.replace(R.id.fragment_container, Twitter())
.commit() .commit()
} }
R.id.magnet ->{ R.id.magnet ->{
supportFragmentManager.beginTransaction() supportFragmentManager.beginTransaction()
.replace(R.id.fragment_container, Magnet()) .replace(R.id.fragment_container, Magnet())

View File

@ -46,7 +46,7 @@ import bums.lunatic.launcher.R
import bums.lunatic.launcher.model.Dotax import bums.lunatic.launcher.model.Dotax
import bums.lunatic.launcher.model.DotaxArticles import bums.lunatic.launcher.model.DotaxArticles
import bums.lunatic.launcher.model.getRssData import bums.lunatic.launcher.model.getRssData
import bums.lunatic.launcher.tokiz.data.model.PortMessage import bums.lunatic.launcher.tokiz.PortMessage
import bums.lunatic.launcher.tokiz.view.BWebview import bums.lunatic.launcher.tokiz.view.BWebview
import bums.lunatic.launcher.utils.Blog import bums.lunatic.launcher.utils.Blog
import bums.lunatic.launcher.utils.CommonUtils import bums.lunatic.launcher.utils.CommonUtils

View File

@ -1,9 +1,12 @@
package bums.lunatic.launcher.home.adapters package bums.lunatic.launcher.home.adapters
import android.app.Application
import android.content.Context
import android.os.Bundle import android.os.Bundle
import android.view.LayoutInflater import android.view.LayoutInflater
import android.view.View import android.view.View
import android.view.ViewGroup import android.view.ViewGroup
import android.view.animation.AnimationUtils
import android.widget.ImageView import android.widget.ImageView
import android.widget.TextView import android.widget.TextView
import androidx.fragment.app.Fragment import androidx.fragment.app.Fragment
@ -30,12 +33,54 @@ import android.widget.Toast
import androidx.core.view.isVisible import androidx.core.view.isVisible
import androidx.fragment.app.activityViewModels import androidx.fragment.app.activityViewModels
import androidx.fragment.app.viewModels import androidx.fragment.app.viewModels
import androidx.lifecycle.AndroidViewModel
import androidx.lifecycle.lifecycleScope import androidx.lifecycle.lifecycleScope
import androidx.viewpager2.widget.ViewPager2 import androidx.viewpager2.widget.ViewPager2
import bums.lunatic.launcher.utils.Blog import bums.lunatic.launcher.utils.Blog
import coil.ImageLoader
import coil.decode.GifDecoder
import coil.decode.ImageDecoderDecoder
import coil.disk.DiskCache
import coil.memory.MemoryCache
import coil.request.ImageRequest
import kotlinx.coroutines.flow.collect import kotlinx.coroutines.flow.collect
import kotlinx.coroutines.launch import kotlinx.coroutines.launch
object CoilInstance {
private var imageLoader: ImageLoader? = null
fun getImageLoader(context: Context): ImageLoader {
// 이미 인스턴스가 있으면 그것을 반환 (싱글턴)
if (imageLoader == null) {
imageLoader = ImageLoader.Builder(context)
.components {
// GIF 지원
if (android.os.Build.VERSION.SDK_INT >= 28) {
add(ImageDecoderDecoder.Factory())
} else {
add(GifDecoder.Factory())
}
}
// --- 캐시 설정 추가 ---
.memoryCache {
MemoryCache.Builder(context)
.maxSizePercent(0.05) // 앱 메모리의 25%를 메모리 캐시로 사용
.build()
}
.diskCache {
DiskCache.Builder()
.directory(context.cacheDir.resolve("image_cache")) // 캐시 파일 저장 위치
.maxSizePercent(0.05) // 디스크 공간의 2%를 디스크 캐시로 사용
.build()
}
// --- 캐시 설정 끝 ---
.build()
}
return imageLoader!!
}
}
class BookmarkPagerFragment : Fragment() { class BookmarkPagerFragment : Fragment() {
// by viewModels() 델리게이트를 사용해 ViewModel 인스턴스 생성 // by viewModels() 델리게이트를 사용해 ViewModel 인스턴스 생성
@ -139,6 +184,12 @@ enum class BookmarkType {
IMAGE, // 하나 이상의 이미지 IMAGE, // 하나 이상의 이미지
VIDEO // 하나 이상의 비디오 VIDEO // 하나 이상의 비디오
} }
data class BookmarkImage(
val url: String = "",
var isVisible: Boolean = true
)
data class WebBookmark( data class WebBookmark(
var id: String? = null, var id: String? = null,
var userId: String, // 누가 저장했는지 var userId: String, // 누가 저장했는지
@ -147,6 +198,7 @@ data class WebBookmark(
var bookmarkType: String = BookmarkType.URL.name, var bookmarkType: String = BookmarkType.URL.name,
// [신규] 콘텐츠 URL 목록 (웹페이지는 1개, 이미지는 여러 개 가능) // [신규] 콘텐츠 URL 목록 (웹페이지는 1개, 이미지는 여러 개 가능)
var contentUrls: List<String> = emptyList(), var contentUrls: List<String> = emptyList(),
var images: List<BookmarkImage> = emptyList(),
var title: String? = null, // 페이지 제목 var title: String? = null, // 페이지 제목
var description: String? = null, // 페이지 요약 (메타 태그) var description: String? = null, // 페이지 요약 (메타 태그)
var thumbnailUrl: String? = null, // 페이지 썸네일 (메타 태그) var thumbnailUrl: String? = null, // 페이지 썸네일 (메타 태그)
@ -182,6 +234,7 @@ init {
} }
class ImageViewHolder(view: View) : RecyclerView.ViewHolder(view) { class ImageViewHolder(view: View) : RecyclerView.ViewHolder(view) {
val imageView: ImageView = view.findViewById(R.id.bookmarkImageView) val imageView: ImageView = view.findViewById(R.id.bookmarkImageView)
val progressBar: ProgressBar = view.findViewById(R.id.imageProgressBar)
} }
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): ImageViewHolder { override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): ImageViewHolder {
@ -193,11 +246,29 @@ init {
override fun onBindViewHolder(holder: ImageViewHolder, position: Int) { override fun onBindViewHolder(holder: ImageViewHolder, position: Int) {
val imageUrl = imageUrls[position] val imageUrl = imageUrls[position]
// Coil을 사용해 URL로부터 이미지를 로드하고 ImageView에 표시합니다. // Coil을 사용해 URL로부터 이미지를 로드하고 ImageView에 표시합니다.
val imageLoader = CoilInstance.getImageLoader(holder.itemView.context)
Blog.LOGE("imageUrl >>> ${imageUrl}") Blog.LOGE("imageUrl >>> ${imageUrl}")
holder.imageView.load("https://lunaticbum.kr$imageUrl") { holder.imageView.load("https://lunaticbum.kr$imageUrl",imageLoader) {
crossfade(true) crossfade(true)
placeholder(R.drawable.ic_launcher) // 로딩 중 보여줄 이미지 (ic_placeholder.xml 같은 drawable 필요)
error(R.drawable.ic_news) // 에러 시 보여줄 이미지 (ic_error.xml 같은 drawable 필요) error(R.drawable.ic_news) // 에러 시 보여줄 이미지 (ic_error.xml 같은 drawable 필요)
listener(
onStart = {
// 로딩 시작: 프로그레스 바를 보여줌
holder.progressBar.visibility = View.VISIBLE
},
onSuccess = { _, _ ->
// 로딩 성공: 프로그레스 바를 숨김
holder.progressBar.visibility = View.GONE
val fadeInAnimation = AnimationUtils.loadAnimation(holder.itemView.context, R.anim.fade_in)
holder.imageView.startAnimation(fadeInAnimation)
},
onError = { _, _ ->
// 로딩 실패: 프로그레스 바를 숨김
holder.progressBar.visibility = View.GONE
}
)
} }
} }
@ -279,7 +350,7 @@ class BookmarkDetailFragment : Fragment() {
// RecyclerView 설정 // RecyclerView 설정
recyclerView.layoutManager = LinearLayoutManager(context) recyclerView.layoutManager = LinearLayoutManager(context)
// contentUrls에 있는 이미지 목록으로 어댑터를 생성하고 RecyclerView에 연결합니다. // contentUrls에 있는 이미지 목록으로 어댑터를 생성하고 RecyclerView에 연결합니다.
recyclerView.adapter = BookmarkImageAdapter(bookmark.contentUrls) recyclerView.adapter = BookmarkImageAdapter(bookmark.images.filter { it.isVisible }.map { it.url })
} }
companion object { companion object {
@ -305,7 +376,7 @@ sealed class UiState {
data class Error(val message: String) : UiState() // 에러 (에러 메시지 보여줌) data class Error(val message: String) : UiState() // 에러 (에러 메시지 보여줌)
} }
class BookmarkViewModel : ViewModel() { class BookmarkViewModel(application: Application) : AndroidViewModel(application) {
private val apiService = BookmarkApiService() private val apiService = BookmarkApiService()
@ -338,6 +409,27 @@ class BookmarkViewModel : ViewModel() {
} }
} }
private fun preloadImages(bookmarks: List<WebBookmark>) {
// 싱글턴 ImageLoader 가져오기
val imageLoader = CoilInstance.getImageLoader(getApplication())
// 모든 북마크의 모든 이미지 URL을 하나의 리스트로 만듦
val allImageUrls = bookmarks.flatMap { bookmark ->
bookmark.images.filter { it.isVisible }.map { it.url }
}
// 각 이미지 URL에 대해 캐시 저장 요청을 보냄
allImageUrls.forEach { imageUrl ->
val fullUrl = "https://lunaticbum.kr$imageUrl"
val request = ImageRequest.Builder(getApplication())
.data(fullUrl)
// 중요: .target()을 설정하지 않으면 이미지를 뷰에 표시하지 않고
// 캐시에만 저장합니다.
.build()
imageLoader.enqueue(request) // 요청을 대기열에 추가
}
}
private fun fetchBookmarks() { private fun fetchBookmarks() {
viewModelScope.launch { viewModelScope.launch {
_uiState.value = UiState.Loading // 로딩 상태로 변경 _uiState.value = UiState.Loading // 로딩 상태로 변경
@ -346,6 +438,7 @@ class BookmarkViewModel : ViewModel() {
if (bookmarks.isEmpty()){ if (bookmarks.isEmpty()){
_uiState.value = UiState.Error("저장된 북마크가 없습니다.") _uiState.value = UiState.Error("저장된 북마크가 없습니다.")
} else { } else {
preloadImages(bookmarks)
_uiState.value = UiState.Success(bookmarks) // 성공 상태와 데이터 전달 _uiState.value = UiState.Success(bookmarks) // 성공 상태와 데이터 전달
} }
} else { } else {

View File

@ -181,7 +181,7 @@ internal class RssItemAdapter (
} else { } else {
holder.view.date.text = emptyDate holder.view.date.text = emptyDate
} }
Picasso.get().cancelRequest(holder.view.circlePreview)
holder.view.title.text = "".plus(if (rssData.vote) " * " else "") holder.view.title.text = "".plus(if (rssData.vote) " * " else "")
.plus(rssData.title().plus("[R:${rssData.read}]")) .plus(rssData.title().plus("[R:${rssData.read}]"))
@ -191,7 +191,7 @@ internal class RssItemAdapter (
holder.view.circlePreview.layoutParams = holder.view.circlePreview.layoutParams =
ConstraintLayout.LayoutParams(rssData.category().defaultImgSize(), param.height) ConstraintLayout.LayoutParams(rssData.category().defaultImgSize(), param.height)
holder.view.circlePreview.visibility = rssData.category().getDefaultVisibiliy() holder.view.circlePreview.visibility = rssData.category().getDefaultVisibiliy()
Picasso.get().cancelRequest(holder.view.circlePreview)
if (rssData.category().getResId() > 0) { if (rssData.category().getResId() > 0) {
holder.view.circlePreview.setImageResource(rssData.category().getResId()) holder.view.circlePreview.setImageResource(rssData.category().getResId())
@ -199,9 +199,9 @@ internal class RssItemAdapter (
if (rssData.thumbnailUrl()?.length ?: 0 > 6) { if (rssData.thumbnailUrl()?.length ?: 0 > 6) {
Blog.LOGE("rssData.thumbnailUrl() >>> ${rssData.thumbnailUrl()}") Blog.LOGE("rssData.thumbnailUrl() >>> ${rssData.thumbnailUrl()}")
val requestOptions = RequestOptions() // val requestOptions = RequestOptions()
.diskCacheStrategy(DiskCacheStrategy.ALL) // .diskCacheStrategy(DiskCacheStrategy.ALL)
.timeout(3000) // 3초 // .timeout(3000) // 3초
Picasso.get().load(rssData.thumbnailUrl().replace("&amp;", "&").toUri()) Picasso.get().load(rssData.thumbnailUrl().replace("&amp;", "&").toUri())
.error(rssData.category().getResId()) .error(rssData.category().getResId())
@ -210,7 +210,7 @@ internal class RssItemAdapter (
// 캐시에서 이미지 성공적으로 로드됨 // 캐시에서 이미지 성공적으로 로드됨
} }
override fun onError(e: Exception?) { override fun onError(e: Exception?) {
Glide.with(holder.view.circlePreview).load(rssData.thumbnailUrl().replace("&amp;", "&")).apply(requestOptions).error(rssData.category().getResId()).into(holder.view.circlePreview) // Glide.with(holder.view.circlePreview).load(rssData.thumbnailUrl().replace("&amp;", "&")).apply(requestOptions).error(rssData.category().getResId()).into(holder.view.circlePreview)
} }
}) })
} }

View File

@ -38,21 +38,6 @@ import bums.lunatic.launcher.LauncherActivity.Companion.getRuntime
import bums.lunatic.launcher.R import bums.lunatic.launcher.R
import bums.lunatic.launcher.databinding.BooktokiBinding import bums.lunatic.launcher.databinding.BooktokiBinding
import bums.lunatic.launcher.home.toast import bums.lunatic.launcher.home.toast
import bums.lunatic.launcher.tokiz.common.PairArray
import bums.lunatic.launcher.tokiz.common.TouchArea
import bums.lunatic.launcher.tokiz.common.colorz
import bums.lunatic.launcher.tokiz.common.getIndex
import bums.lunatic.launcher.tokiz.common.typesfacez
import bums.lunatic.launcher.tokiz.data.HistoryManager
import bums.lunatic.launcher.tokiz.data.model.ContentsCollection
import bums.lunatic.launcher.tokiz.data.model.ContentsPageInfo
import bums.lunatic.launcher.tokiz.data.model.FakeSessions
import bums.lunatic.launcher.tokiz.data.model.HistoryItem
import bums.lunatic.launcher.tokiz.data.model.LastInfo
import bums.lunatic.launcher.tokiz.data.model.PageInfosJ
import bums.lunatic.launcher.tokiz.data.model.PortMessage
import bums.lunatic.launcher.tokiz.data.model.ReaderConfig
import bums.lunatic.launcher.tokiz.dialog.DefaultList
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.tokiz.view.PagedTextLayout import bums.lunatic.launcher.tokiz.view.PagedTextLayout
@ -684,7 +669,7 @@ abstract class BaseToki : Fragment(), PagedTextViewInterface {
private fun getHistory() : List<HistoryItem>? { private fun getHistory() : List<HistoryItem>? {
try { try {
var realm = openRealm() var realm = openRealm()
return realm.query<HistoryItem>().query("contentsType == $0", contentsType).find()?.copyFromRealm() return realm.query<HistoryItem>().query("contentsType == $0", contentsType).find()?.copyFromRealm()?.reversed()
}catch (e: Exception){ }catch (e: Exception){
e.printStackTrace() e.printStackTrace()
} }
@ -1163,13 +1148,6 @@ abstract class BaseToki : Fragment(), PagedTextViewInterface {
fun onStateChange(sessionState: GeckoSession.SessionState) { fun onStateChange(sessionState: GeckoSession.SessionState) {
var fakeSession : FakeSessions? = null
try {
fakeSession = Gson().fromJson(Gson().toJson(sessionState), FakeSessions::class.java)
Blog.LOGE("fakeSession >>> $fakeSession")
}catch (e: Exception){
e.printStackTrace()
}
if (sessionState.last().uri.length > 10) { if (sessionState.last().uri.length > 10) {
lastedUrl?.let { lastedUrl?.let {
@ -1546,4 +1524,497 @@ abstract class BaseToki : Fragment(), PagedTextViewInterface {
// binding.menuWeb.session?.goBack() // binding.menuWeb.session?.goBack()
} }
}
class YouTube : BaseToki(){
override val contentsType = "youtube"
override var lastNumber : Int = 143
override val webcontentsName : String = "youtube"
override val afterDot = "com"
override var isPrivateMode: Boolean = true
override fun getLastedDoamin(): String {
return String.format("https://%s.%s", webcontentsName, afterDot)
}
override fun onCreateView(
inflater: LayoutInflater,
container: ViewGroup?,
savedInstanceState: Bundle?
): View {
super.onCreateView(inflater, container, savedInstanceState)
return binding.root
}
override fun onStart() {
super.onStart()
}
override fun onResume() {
super.onResume()
loadLastInfo()
}
override fun back() {
binding.menuWeb.session?.goBack()
}
override fun onTouch(touchArea: TouchArea) {
}
override fun onTimeoverTouch() {
}
override fun onSwipeLeft(touchCount: Int) {
}
override fun onSwipeRight(touchCount: Int) {
}
override fun onSwipeDown(touchCount: Int) {
}
override fun onSwipeUp(touchCount: Int) {
}
override fun onLongClick() {
}
}
class Comics : BaseToki(), PagedTextViewInterface {
override val contentsType = "comics"
override var lastNumber : Int = 468
override val webcontentsName : String = "manatoki"
override val afterDot = "net"
override fun onCreateView(
inflater: LayoutInflater,
container: ViewGroup?,
savedInstanceState: Bundle?
): View {
super.onCreateView(inflater, container, savedInstanceState)
return binding.root
}
override fun onStart() {
super.onStart()
}
override fun onResume() {
super.onResume()
loadLastInfo()
}
override fun onTouch(touchArea: TouchArea) {
Blog.LOGD(log = "onTouch ${touchArea}")
when (touchArea) {
TouchArea.Center -> {
}
TouchArea.Right -> {
actionNextEvent()
}
TouchArea.Left -> {
actionPrevEvent()
}
TouchArea.DoubleRight -> {
actionNextEvent(true)
}
TouchArea.DoubleLeft -> {
actionPrevEvent(true)
}
else -> {
}
}
}
override fun onLongClick() {
Blog.LOGD(log = "onLongClick")
}
override fun onSwipeLeft(count: Int) {
Blog.LOGD(log = "onSwipeLeft ${count}")
actionNextEvent(count > 1)
}
override fun onSwipeRight(count: Int) {
Blog.LOGD(log = "onSwipeRight ${count}")
actionPrevEvent(count > 1)
}
override fun onSwipeUp(touchCount: Int) {
}
override fun onSwipeDown(touchCount: Int) {
if (touchCount == 2) {
if (binding.pagedLayer.isVisible) {
binding.pagedLayer.visibility = GONE
}
}
}
override fun onTimeoverTouch() {
}
}
class Magnet : BaseToki(), PagedTextViewInterface {
// "https://btsearch.love/
override val contentsType = "btsearch"
override var lastNumber : Int = 143
override val webcontentsName : String = "btsearch"
override val afterDot = "love"
override fun getLastedDoamin(): String {
return String.format("https://%s.%s", webcontentsName, afterDot)
}
override fun onCreateView(
inflater: LayoutInflater,
container: ViewGroup?,
savedInstanceState: Bundle?
): View {
super.onCreateView(inflater, container, savedInstanceState)
return binding.root
}
override fun onStart() {
super.onStart()
}
override fun onResume() {
super.onResume()
loadLastInfo()
}
override fun onTouch(touchArea: TouchArea) {
Blog.LOGD(log = "onTouch ${touchArea}")
when (touchArea) {
TouchArea.Center -> {
}
TouchArea.Right -> {
actionNextEvent()
}
TouchArea.Left -> {
actionPrevEvent()
}
TouchArea.DoubleRight -> {
actionNextEvent(true)
}
TouchArea.DoubleLeft -> {
actionPrevEvent(true)
}
else -> {
}
}
}
override fun onLongClick() {
Blog.LOGD(log = "onLongClick")
}
override fun onSwipeLeft(count: Int) {
Blog.LOGD(log = "onSwipeLeft ${count}")
actionNextEvent(count > 1)
}
override fun onSwipeRight(count: Int) {
Blog.LOGD(log = "onSwipeRight ${count}")
actionPrevEvent(count > 1)
}
override fun onSwipeUp(touchCount: Int) {
}
override fun onSwipeDown(touchCount: Int) {
if (touchCount == 2) {
if (binding.pagedLayer.isVisible) {
binding.pagedLayer.visibility = GONE
}
}
}
override fun onTimeoverTouch() {
}
}
class Novels : BaseToki(), PagedTextViewInterface {
override val contentsType = "book"
override var lastNumber : Int = 468
override val webcontentsName : String = "booktoki"
override val afterDot = "com"
override fun onCreateView(
inflater: LayoutInflater,
container: ViewGroup?,
savedInstanceState: Bundle?
): View {
super.onCreateView(inflater, container, savedInstanceState)
return binding.root
}
override fun onStart() {
super.onStart()
}
override fun onResume() {
super.onResume()
loadLastInfo()
}
override fun onTouch(touchArea: TouchArea) {
Blog.LOGD(log = "onTouch ${touchArea}")
when (touchArea) {
TouchArea.Center -> {
}
TouchArea.Right -> {
actionNextEvent()
}
TouchArea.Left -> {
actionPrevEvent()
}
TouchArea.DoubleRight -> {
actionNextEvent(true)
}
TouchArea.DoubleLeft -> {
actionPrevEvent(true)
}
else -> {
}
}
}
override fun onLongClick() {
Blog.LOGD(log = "onLongClick")
}
override fun onSwipeLeft(count: Int) {
Blog.LOGD(log = "onSwipeLeft ${count}")
actionNextEvent(count > 1)
}
override fun onSwipeRight(count: Int) {
Blog.LOGD(log = "onSwipeRight ${count}")
actionPrevEvent(count > 1)
}
override fun onSwipeUp(touchCount: Int) {
}
override fun onSwipeDown(touchCount: Int) {
if (touchCount == 2) {
if (binding.pagedLayer.isVisible) {
binding.pagedLayer.visibility = GONE
}
binding.menuWeb.visibility = View.VISIBLE
}
}
override fun onTimeoverTouch() {
}
}
class Perplexity : BaseToki(), PagedTextViewInterface {
// "https://btsearch.love/
override val contentsType = "perplexity"
override var lastNumber : Int = 143
override val webcontentsName : String = "www.perplexity"
override val afterDot = "ai"
override fun getLastedDoamin(): String {
return String.format("https://%s.%s", webcontentsName, afterDot)
}
override fun onCreateView(
inflater: LayoutInflater,
container: ViewGroup?,
savedInstanceState: Bundle?
): View {
super.onCreateView(inflater, container, savedInstanceState)
return binding.root
}
override fun onStart() {
super.onStart()
}
override fun onResume() {
super.onResume()
loadLastInfo()
}
override fun onTouch(touchArea: TouchArea) {
Blog.LOGD(log = "onTouch ${touchArea}")
when (touchArea) {
TouchArea.Center -> {
}
TouchArea.Right -> {
actionNextEvent()
}
TouchArea.Left -> {
actionPrevEvent()
}
TouchArea.DoubleRight -> {
actionNextEvent(true)
}
TouchArea.DoubleLeft -> {
actionPrevEvent(true)
}
else -> {
}
}
}
override fun onLongClick() {
Blog.LOGD(log = "onLongClick")
}
override fun onSwipeLeft(count: Int) {
Blog.LOGD(log = "onSwipeLeft ${count}")
actionNextEvent(count > 1)
}
override fun onSwipeRight(count: Int) {
Blog.LOGD(log = "onSwipeRight ${count}")
actionPrevEvent(count > 1)
}
override fun onSwipeUp(touchCount: Int) {
}
override fun onSwipeDown(touchCount: Int) {
if (touchCount == 2) {
if (binding.pagedLayer.isVisible) {
binding.pagedLayer.visibility = GONE
}
}
}
override fun onTimeoverTouch() {
}
}
class Webtoons : BaseToki(), PagedTextViewInterface {
override val contentsType = "webtoon"
override var lastNumber : Int = 468
override val webcontentsName : String = "newtoki"
override val afterDot = "com"
override fun onCreateView(
inflater: LayoutInflater,
container: ViewGroup?,
savedInstanceState: Bundle?
): View {
super.onCreateView(inflater, container, savedInstanceState)
return binding.root
}
override fun onStart() {
super.onStart()
}
override fun onResume() {
super.onResume()
loadLastInfo()
Blog.LOGE("binding.root >>> ${binding.root}")
}
override fun onTouch(touchArea: TouchArea) {
Blog.LOGD(log = "onTouch ${touchArea}")
when (touchArea) {
TouchArea.Center -> {
}
TouchArea.Right -> {
actionNextEvent()
}
TouchArea.Left -> {
actionPrevEvent()
}
TouchArea.DoubleRight -> {
actionNextEvent(true)
}
TouchArea.DoubleLeft -> {
actionPrevEvent(true)
}
else -> {
}
}
}
override fun onLongClick() {
Blog.LOGD(log = "onLongClick")
}
override fun onSwipeLeft(count: Int) {
Blog.LOGD(log = "onSwipeLeft ${count}")
actionNextEvent(count > 1)
}
override fun onSwipeRight(count: Int) {
Blog.LOGD(log = "onSwipeRight ${count}")
actionPrevEvent(count > 1)
}
override fun onSwipeUp(touchCount: Int) {
}
override fun onSwipeDown(touchCount: Int) {
if (touchCount == 2) {
if (binding.pagedLayer.isVisible) {
binding.pagedLayer.visibility = GONE
}
}
}
override fun onTimeoverTouch() {
}
} }

View File

@ -1,99 +0,0 @@
package bums.lunatic.launcher.tokiz
import android.os.Bundle
import android.view.LayoutInflater
import android.view.View
import android.view.View.GONE
import android.view.ViewGroup
import androidx.core.view.isVisible
import bums.lunatic.launcher.tokiz.common.TouchArea
import bums.lunatic.launcher.tokiz.view.PagedTextViewInterface
import bums.lunatic.launcher.utils.Blog
class Comics : BaseToki(), PagedTextViewInterface {
override val contentsType = "comics"
override var lastNumber : Int = 468
override val webcontentsName : String = "manatoki"
override val afterDot = "net"
override fun onCreateView(
inflater: LayoutInflater,
container: ViewGroup?,
savedInstanceState: Bundle?
): View {
super.onCreateView(inflater, container, savedInstanceState)
return binding.root
}
override fun onStart() {
super.onStart()
}
override fun onResume() {
super.onResume()
loadLastInfo()
}
override fun onTouch(touchArea: TouchArea) {
Blog.LOGD(log = "onTouch ${touchArea}")
when (touchArea) {
TouchArea.Center -> {
}
TouchArea.Right -> {
actionNextEvent()
}
TouchArea.Left -> {
actionPrevEvent()
}
TouchArea.DoubleRight -> {
actionNextEvent(true)
}
TouchArea.DoubleLeft -> {
actionPrevEvent(true)
}
else -> {
}
}
}
override fun onLongClick() {
Blog.LOGD(log = "onLongClick")
}
override fun onSwipeLeft(count: Int) {
Blog.LOGD(log = "onSwipeLeft ${count}")
actionNextEvent(count > 1)
}
override fun onSwipeRight(count: Int) {
Blog.LOGD(log = "onSwipeRight ${count}")
actionPrevEvent(count > 1)
}
override fun onSwipeUp(touchCount: Int) {
}
override fun onSwipeDown(touchCount: Int) {
if (touchCount == 2) {
if (binding.pagedLayer.isVisible) {
binding.pagedLayer.visibility = GONE
}
}
}
override fun onTimeoverTouch() {
}
}

View File

@ -0,0 +1,459 @@
package bums.lunatic.launcher.tokiz
import android.R
import android.content.Context
import android.content.DialogInterface
import android.content.pm.ActivityInfo
import android.widget.ArrayAdapter
import androidx.activity.ComponentDialog
import androidx.appcompat.app.AlertDialog
import bums.lunatic.launcher.model.RssData
import bums.lunatic.launcher.utils.Blog
import bums.lunatic.launcher.workers.WorkersDb
import io.realm.kotlin.Realm
import io.realm.kotlin.UpdatePolicy
import io.realm.kotlin.ext.realmListOf
import io.realm.kotlin.types.RealmList
import io.realm.kotlin.types.RealmObject
import io.realm.kotlin.types.annotations.PrimaryKey
import java.text.SimpleDateFormat
import java.util.Date
class LastInfo : RealmObject {
@PrimaryKey
var _id : String = ""
var pageUrl : String = ""
var title : String = ""
var chapter : Int = 0
var pageIndex : Int = 0
var contentsName : String = ""
var contentsType : String? = ""
set(value) {
_id = value ?: ""
field = value
}
var displayOrientation : Int = ActivityInfo.SCREEN_ORIENTATION_PORTRAIT
fun makeHistoryItem() : HistoryItem = HistoryItem().apply {
title = this@LastInfo.title
pageUrl = this@LastInfo.pageUrl
chapter = this@LastInfo.chapter
pageIndex = this@LastInfo.pageIndex
contentsName = this@LastInfo.contentsName
displayOrientation = this@LastInfo.displayOrientation
contentsType = this@LastInfo.contentsType
}
}
class HistoryItem : RealmObject {
@PrimaryKey
var title : String = ""
var pageUrl : String = ""
var chapter : Int = 0
var pageIndex : Int = 0
var contentsName : String = ""
var displayOrientation : Int = ActivityInfo.SCREEN_ORIENTATION_PORTRAIT
var contentsType : String? = ""
fun makeLastInfo() = LastInfo().apply{
_id = "UniqLastId"
title = this@HistoryItem.title
pageUrl = this@HistoryItem.pageUrl
chapter = this@HistoryItem.chapter
pageIndex = this@HistoryItem.pageIndex
contentsName = this@HistoryItem.contentsName
displayOrientation = this@HistoryItem.displayOrientation
contentsType = this@HistoryItem.contentsType
}
fun putHistory(contentsPageInfo: ContentsPageInfo?, currentPath : String) : HistoryItem {
title = contentsPageInfo?.bookTitle ?: SimpleDateFormat("YY-mm-DD-HH:mm").format(Date())
pageUrl = contentsPageInfo?.pathUrl ?: currentPath
chapter = contentsPageInfo?.chapterNum ?: 0
pageIndex = contentsPageInfo?.lastPage ?: 0
contentsName = contentsPageInfo?.chapterTitle ?: ""
contentsType = contentsPageInfo?.contentsType ?: ""
return this
}
}
class Bookmark() : RealmObject {
@PrimaryKey
var pageUrl : String = ""
}
class ReaderConfig : RealmObject {
@PrimaryKey
var id : String? = "ReaderConfig"
var textSize : Int? = 14
var textColor : String? = "#FFFFFF"
var bgColor : String? = "#000000"
var style : Int? = 0
var lineSpace : Int? = 1
var letterSpace : Int? = 1
var font : String? = ""
var padding : Int? = 5
}
class PortMessage {
var type : String? = ""
var bookInfos : PageInfosJ? = null
var book : BookContents? = null
var msg : String? = null
var contents : String? = null
var privates : ArrayList<RssData>? = null
var currentPage : String? = null
var cookies : String? = null
var urls : List<String> = emptyList()
var imgSrc: String? = null
var base64Data: String? = null
}
class BookContents {
var chapterTitle : String? = null
var bookContents : String? = null
}
class PageInfosJ {
var bookTitle : String = ""
var bookPageUrl : String = ""
var contentsType : String? = ""
var pages : ArrayList<PageInfoJ> = arrayListOf<PageInfoJ>()
fun getTitleArray() : ArrayList<String> {
var arrayList = ArrayList<String>()
pages.forEach { arrayList.add(it.bookTitle ?: "") }
return arrayList
}
fun getR() : ContentsCollection{
var r = ContentsCollection()
r.bookTitle = this.bookTitle
r.bookPageUrl = this.bookPageUrl
r.contentsType = this.contentsType
return r
}
}
class PageInfoJ {
var chapterID : Int = 0
var contents : String? = ""
var bookPageUrl : String? = ""
var chapterTitle : String? = ""
var bookTitle : String? = ""
var chapterNum : Int = 0
var lastPage : Int? = 0
var pathUrl : String? = ""
var contentsType : String? = ""
fun getRealm() : ContentsPageInfo {
var r = ContentsPageInfo()
r.chapterID = this.chapterID
r.contents = this.contents
r.bookPageUrl = this.bookPageUrl ?: ""
r.chapterTitle = this.chapterTitle
r.bookTitle = this.bookTitle ?: ""
r.chapterNum = this.chapterNum
r.lastPage = this.lastPage
r.pathUrl = this.pathUrl?.replace("'","")
r.contentsType = this.contentsType
return r
}
}
class ContentsCollection : RealmObject {
var bookTitle : String = ""
@PrimaryKey
var bookPageUrl : String? = ""
var pages : RealmList<ContentsPageInfo> = realmListOf()
var contentsType : String? = ""
fun getTitleArray() : ArrayList<String> {
var arrayList = ArrayList<String>()
pages.forEach {
arrayList.add(it.getTitleItem())}
return arrayList
}
fun sort() {
val comparator : Comparator<ContentsPageInfo> = compareBy { it.chapterID }
pages.sortWith(comparator)
}
fun hasItem(item: ContentsPageInfo) : Boolean {
var hasItem = false
for (c in pages) {
if (!hasItem) {
hasItem = c.pathUrl.equals(item.pathUrl)
}
}
return hasItem
}
}
class ContentsPageInfo : RealmObject {
var chapterID : Int = 0
var contents : String? = ""
var bookPageUrl : String? = ""
var chapterTitle : String? = ""
var bookTitle : String? = ""
var chapterNum : Int = 0
var lastPage : Int? = 0
var contentsType : String? = ""
fun isValidBook() = (pathUrl?.length ?: 0) > 1
@PrimaryKey
var pathUrl : String? = ""
fun getTitleItem() : String {
var result = StringBuilder()
result.append(if ((contents?.length ?: 0) > 10) {
"S:[0] "
} else {
"[X] "
})
result.append(chapterTitle?: "")
result.append(if ((lastPage ?: 0) > 0) {
" [0] "
} else {
" [X] "
})
return result.toString()
}
}
object HistoryManager {
val openRealm : Realm = WorkersDb.getRealm()
fun save(lastInfo: LastInfo) {
openRealm.apply{
this.writeBlocking {
copyToRealm(lastInfo, UpdatePolicy.ALL)
}
}
}
fun save(historyItem: HistoryItem) {
openRealm.apply{
this.writeBlocking {
copyToRealm(historyItem, UpdatePolicy.ALL)
}
}
}
fun requestLastInfo(callback : (LastInfo)->Unit) {
openRealm.apply{
}
}
fun save(config : ReaderConfig) {
openRealm.apply{
this.writeBlocking {
copyToRealm(config,UpdatePolicy.ALL)
}
}
}
fun getBookInfos(contentsType : String,aUrl : String, callback : (ContentsCollection?)->Unit) {
var url : String = aUrl
Blog.LOGE("aUrl >>> ${aUrl} , contentsType ${contentsType}")
openRealm.apply{
if (url.startsWith("//")) {
while (url.startsWith("//")) {
url = url.replace("//","/").trim()
}
}
Blog.LOGE("aUrl >>> ${url}")
var contentsPageInfo = this.query(ContentsPageInfo::class).query("contentsType == $0", contentsType).query("pathUrl == $0 || bookPageUrl == $0","${url}").find()
if (contentsPageInfo != null && contentsPageInfo.count() > 0) {
Blog.LOGE("get ${contentsPageInfo}" )
var pgs = this.query(ContentsCollection::class,"bookPageUrl == $0", contentsPageInfo.first().bookPageUrl).find()
if (pgs.size > 0) {
pgs.first().let {
Blog.LOGE("get ${it} , ${it?.pages}")
callback.invoke(this.copyFromRealm(it))
}
} else {
callback.invoke(null)
}
} else {
callback.invoke(null)
}
}
}
fun getBookPageInfo(contentsType : String, aUrl : String, callback : (ContentsPageInfo?)->Unit) {
var url : String = aUrl
openRealm.apply{
if (url.startsWith("//")) {
while (url.startsWith("//")) {
url = url.replace("//","/").trim()
}
}
var result = this.query(ContentsPageInfo::class).query("contentsType == $0", contentsType).query("pathUrl == $0","${url}").find()
if (result.size > 0) {
var bookPageInfo = result?.first()
if (bookPageInfo != null) {
callback.invoke(bookPageInfo)
} else {
callback.invoke(null)
}
} else {
callback.invoke(null)
}
}
}
fun setBookPageInfo(contentsType : String,aUrl : String, page :Int) {
var url : String = aUrl
openRealm.writeBlocking {
if (url.startsWith("//")) {
while (url.startsWith("//")) {
url = url.replace("//","/").trim()
}
}
var result = this.query(ContentsPageInfo::class).query("contentsType == $0", contentsType).query("pathUrl == $0","${url}").find()
if (result.size > 0) {
var bookPageInfo = result?.first()
if (bookPageInfo != null) {
bookPageInfo.lastPage = page
}
}
}
}
fun getBooPageInfoContentsSave(contentsType : String,aUrl : String, contents : String) {
var url : String = if (aUrl.startsWith("//") || aUrl.startsWith("///") || aUrl.startsWith("////")) {
aUrl.replace("////","/").replace("///","/").replace("//","/")
} else aUrl
openRealm.writeBlocking {
Blog.LOGE("getBooPageInfoContentsSave ${url}")
val result = query(ContentsPageInfo::class).query("contentsType == $0", contentsType).query("pathUrl == $0", "${url}").find()
if (result.size > 0) {
result.first().contents = contents
copyToRealm(result.first(), UpdatePolicy.ALL)
}
}
}
fun getNextPage(contentsType : String,aUrl : String ,callback : (ContentsPageInfo?)->Unit) {
var url : String = aUrl
openRealm.apply{
if (url.startsWith("//")) {
while (url.startsWith("//")) {
url = url.replace("//","/").trim()
}
}
var contentsPageInfo =
this.query(ContentsPageInfo::class).query("contentsType == $0", contentsType).query("pathUrl == $0", url).find()
if (contentsPageInfo.size > 0) {
Blog.LOGE("getNextPage 2 => chapterNum : ${contentsPageInfo.first().chapterNum} , bookPageInfo.bookPageUrl : ${contentsPageInfo.first().bookPageUrl}" )
var results = this.query(ContentsPageInfo::class).query("chapterNum == $0",contentsPageInfo.first().chapterNum + 1).query("bookPageUrl == $0","${contentsPageInfo.first().bookPageUrl}").find()
if(results.size > 0) {
results.first().let {
Blog.LOGE("getNextPage 2 nextBook pathUrl : ${it.pathUrl}" )
callback.invoke(it)
}
} else {callback.invoke(null)}
} else {callback.invoke(null)}
}
}
fun getPrevPage(contentsType : String,aUrl : String ,callback : (ContentsPageInfo?)->Unit) {
var url : String = aUrl
openRealm.apply{
Blog.LOGE("getPrevPage ${url}" )
if (url.startsWith("//")) {
while (url.startsWith("//")) {
url = url.replace("//","/").trim()
}
}
Blog.LOGE("getPrevPage ${url}" )
var contentsPageInfo =
this.query(ContentsPageInfo::class).query("contentsType == $0", contentsType).query("pathUrl == $0", url).find()
Blog.LOGE("getPrevPage ${contentsPageInfo}" )
if (contentsPageInfo.size > 0) {
Blog.LOGE("getPrevPage 2 ${contentsPageInfo?.first()?.chapterNum}" )
Blog.LOGE("getPrevPage 2 ${contentsPageInfo?.first()?.bookPageUrl}" )
var results = this.query(ContentsPageInfo::class).query("chapterNum == $0",contentsPageInfo.first().chapterNum - 1).query("bookPageUrl == $0","${contentsPageInfo.first().bookPageUrl}").find()
if(results.size > 0) {
results.first()?.let {
Blog.LOGE("getPrevPage 2 ${it.bookPageUrl}" )
Blog.LOGE("getPrevPage 2 ${it.pathUrl}" )
callback.invoke(it)
}
} else {
callback.invoke(null)
}
} else {
callback.invoke(null)
}
}
}
}
object DefaultList {
fun showDefaultList(context: Context, title : String, items : Collection<ContentsPageInfo>, firstPosition : Int, choosedTitle : (Int)->String, chooedPositive : (Int)->Unit, saveCalback : (Int)->Unit ) {
val builderSingle: AlertDialog.Builder = AlertDialog.Builder(context)
builderSingle.setTitle(title)
val arrayAdapter =
ArrayAdapter<String>(context, R.layout.select_dialog_singlechoice)
for (item in items) {
arrayAdapter.add(item.getTitleItem())
}
builderSingle.setNeutralButton("전체 저장") { dialog, which ->
saveCalback.invoke(-1)
dialog.dismiss()
}
builderSingle.setNegativeButton("닫기",
DialogInterface.OnClickListener { dialog, which ->
dialog.dismiss() })
builderSingle.setAdapter(arrayAdapter,
DialogInterface.OnClickListener { dialog, position ->
val strName = arrayAdapter.getItem(position)
val builderInner: AlertDialog.Builder = AlertDialog.Builder(context)
builderInner.setMessage(strName)
builderInner.setTitle(choosedTitle.invoke(position))
builderInner.setNegativeButton("닫기") { dialog, which ->
}
// builderInner.setNeutralButton("자동 저장") { dialog, which ->
// saveCalback.invoke(position)
// }
builderInner.setPositiveButton("이동"){ dialog, which ->
chooedPositive.invoke(position)
dialog.dismiss()
}
builderInner.show().apply {
DialogManager.add(this)
}
})
builderSingle.create()?.apply{
setOnShowListener { d->
(d as? AlertDialog)?.let{
it.listView?.setSelection(firstPosition)
}
}
DialogManager.add(this)
}?.show()
}
}
object DialogManager {
val dialogs = arrayListOf<ComponentDialog>()
fun add(item : ComponentDialog) = dialogs.add(item)
fun closeAll() {
for (dialog in dialogs) {
try {
dialog?.dismiss()
} catch(e : Exception) {
}
}
}
}

View File

@ -1,102 +0,0 @@
package bums.lunatic.launcher.tokiz
import android.os.Bundle
import android.view.LayoutInflater
import android.view.View
import android.view.View.GONE
import android.view.ViewGroup
import androidx.core.view.isVisible
import bums.lunatic.launcher.tokiz.common.TouchArea
import bums.lunatic.launcher.tokiz.view.PagedTextViewInterface
import bums.lunatic.launcher.utils.Blog
class Magnet : BaseToki(), PagedTextViewInterface {
// "https://btsearch.love/
override val contentsType = "btsearch"
override var lastNumber : Int = 143
override val webcontentsName : String = "btsearch"
override val afterDot = "love"
override fun getLastedDoamin(): String {
return String.format("https://%s.%s", webcontentsName, afterDot)
}
override fun onCreateView(
inflater: LayoutInflater,
container: ViewGroup?,
savedInstanceState: Bundle?
): View {
super.onCreateView(inflater, container, savedInstanceState)
return binding.root
}
override fun onStart() {
super.onStart()
}
override fun onResume() {
super.onResume()
loadLastInfo()
}
override fun onTouch(touchArea: TouchArea) {
Blog.LOGD(log = "onTouch ${touchArea}")
when (touchArea) {
TouchArea.Center -> {
}
TouchArea.Right -> {
actionNextEvent()
}
TouchArea.Left -> {
actionPrevEvent()
}
TouchArea.DoubleRight -> {
actionNextEvent(true)
}
TouchArea.DoubleLeft -> {
actionPrevEvent(true)
}
else -> {
}
}
}
override fun onLongClick() {
Blog.LOGD(log = "onLongClick")
}
override fun onSwipeLeft(count: Int) {
Blog.LOGD(log = "onSwipeLeft ${count}")
actionNextEvent(count > 1)
}
override fun onSwipeRight(count: Int) {
Blog.LOGD(log = "onSwipeRight ${count}")
actionPrevEvent(count > 1)
}
override fun onSwipeUp(touchCount: Int) {
}
override fun onSwipeDown(touchCount: Int) {
if (touchCount == 2) {
if (binding.pagedLayer.isVisible) {
binding.pagedLayer.visibility = GONE
}
}
}
override fun onTimeoverTouch() {
}
}

View File

@ -1,100 +0,0 @@
package bums.lunatic.launcher.tokiz
import android.os.Bundle
import android.view.LayoutInflater
import android.view.View
import android.view.View.GONE
import android.view.ViewGroup
import androidx.core.view.isVisible
import bums.lunatic.launcher.tokiz.common.TouchArea
import bums.lunatic.launcher.tokiz.view.PagedTextViewInterface
import bums.lunatic.launcher.utils.Blog
class Novels : BaseToki(), PagedTextViewInterface {
override val contentsType = "book"
override var lastNumber : Int = 468
override val webcontentsName : String = "booktoki"
override val afterDot = "com"
override fun onCreateView(
inflater: LayoutInflater,
container: ViewGroup?,
savedInstanceState: Bundle?
): View {
super.onCreateView(inflater, container, savedInstanceState)
return binding.root
}
override fun onStart() {
super.onStart()
}
override fun onResume() {
super.onResume()
loadLastInfo()
}
override fun onTouch(touchArea: TouchArea) {
Blog.LOGD(log = "onTouch ${touchArea}")
when (touchArea) {
TouchArea.Center -> {
}
TouchArea.Right -> {
actionNextEvent()
}
TouchArea.Left -> {
actionPrevEvent()
}
TouchArea.DoubleRight -> {
actionNextEvent(true)
}
TouchArea.DoubleLeft -> {
actionPrevEvent(true)
}
else -> {
}
}
}
override fun onLongClick() {
Blog.LOGD(log = "onLongClick")
}
override fun onSwipeLeft(count: Int) {
Blog.LOGD(log = "onSwipeLeft ${count}")
actionNextEvent(count > 1)
}
override fun onSwipeRight(count: Int) {
Blog.LOGD(log = "onSwipeRight ${count}")
actionPrevEvent(count > 1)
}
override fun onSwipeUp(touchCount: Int) {
}
override fun onSwipeDown(touchCount: Int) {
if (touchCount == 2) {
if (binding.pagedLayer.isVisible) {
binding.pagedLayer.visibility = GONE
}
binding.menuWeb.visibility = View.VISIBLE
}
}
override fun onTimeoverTouch() {
}
}

View File

@ -1,102 +0,0 @@
package bums.lunatic.launcher.tokiz
import android.os.Bundle
import android.view.LayoutInflater
import android.view.View
import android.view.View.GONE
import android.view.ViewGroup
import androidx.core.view.isVisible
import bums.lunatic.launcher.tokiz.common.TouchArea
import bums.lunatic.launcher.tokiz.view.PagedTextViewInterface
import bums.lunatic.launcher.utils.Blog
class Perplexity : BaseToki(), PagedTextViewInterface {
// "https://btsearch.love/
override val contentsType = "perplexity"
override var lastNumber : Int = 143
override val webcontentsName : String = "www.perplexity"
override val afterDot = "ai"
override fun getLastedDoamin(): String {
return String.format("https://%s.%s", webcontentsName, afterDot)
}
override fun onCreateView(
inflater: LayoutInflater,
container: ViewGroup?,
savedInstanceState: Bundle?
): View {
super.onCreateView(inflater, container, savedInstanceState)
return binding.root
}
override fun onStart() {
super.onStart()
}
override fun onResume() {
super.onResume()
loadLastInfo()
}
override fun onTouch(touchArea: TouchArea) {
Blog.LOGD(log = "onTouch ${touchArea}")
when (touchArea) {
TouchArea.Center -> {
}
TouchArea.Right -> {
actionNextEvent()
}
TouchArea.Left -> {
actionPrevEvent()
}
TouchArea.DoubleRight -> {
actionNextEvent(true)
}
TouchArea.DoubleLeft -> {
actionPrevEvent(true)
}
else -> {
}
}
}
override fun onLongClick() {
Blog.LOGD(log = "onLongClick")
}
override fun onSwipeLeft(count: Int) {
Blog.LOGD(log = "onSwipeLeft ${count}")
actionNextEvent(count > 1)
}
override fun onSwipeRight(count: Int) {
Blog.LOGD(log = "onSwipeRight ${count}")
actionPrevEvent(count > 1)
}
override fun onSwipeUp(touchCount: Int) {
}
override fun onSwipeDown(touchCount: Int) {
if (touchCount == 2) {
if (binding.pagedLayer.isVisible) {
binding.pagedLayer.visibility = GONE
}
}
}
override fun onTimeoverTouch() {
}
}

View File

@ -8,15 +8,93 @@ import androidx.databinding.DataBindingUtil
import bums.lunatic.launcher.R import bums.lunatic.launcher.R
import bums.lunatic.launcher.common.CommonActivity import bums.lunatic.launcher.common.CommonActivity
import bums.lunatic.launcher.databinding.SettingsBinding import bums.lunatic.launcher.databinding.SettingsBinding
import bums.lunatic.launcher.tokiz.common.PairArray
import bums.lunatic.launcher.tokiz.common.colorz
import bums.lunatic.launcher.tokiz.common.getIndex
import bums.lunatic.launcher.tokiz.common.typesfacez
import bums.lunatic.launcher.tokiz.data.HistoryManager
import bums.lunatic.launcher.tokiz.data.model.ReaderConfig
import io.realm.kotlin.UpdatePolicy import io.realm.kotlin.UpdatePolicy
import io.realm.kotlin.ext.query import io.realm.kotlin.ext.query
typealias PairArray<T> = Array<Pair<String,T>>
val colorz : PairArray<Array<String>> = arrayOf<Pair<String,Array<String>>>(
Pair("color set 01",arrayOf<String>("#E1F5FE", "#263238")),
Pair("color set 02",arrayOf<String>("#F0F4C3", "#37474F")),
Pair("color set 03",arrayOf<String>("#ECEFF1", "#455A64")),
Pair("color set 04",arrayOf<String>("#E0F7FA", "#263238")),
Pair("color set 05",arrayOf<String>("#F5F5F5", "#263238")),
Pair("color set 06",arrayOf<String>("#ECEFF1", "#263238")),
Pair("color set 07",arrayOf<String>("#F8BBD0", "#263238")),
Pair("color set 08",arrayOf<String>("#E6EE9C", "#455A64")),
Pair("color set 09",arrayOf<String>("#CFD8DC", "#455A64")),
Pair("color set 10",arrayOf<String>("#FFF59D", "#37474F")),
Pair("color set 21",arrayOf<String>("#263238","#E1F5FE")),
Pair("color set 22",arrayOf<String>("#37474F","#F0F4C3")),
Pair("color set 23",arrayOf<String>("#455A64","#ECEFF1")),
Pair("color set 24",arrayOf<String>("#263238","#E0F7FA")),
Pair("color set 25",arrayOf<String>("#263238","#F5F5F5")),
Pair("color set 26",arrayOf<String>("#263238","#ECEFF1")),
Pair("color set 27",arrayOf<String>("#263238","#F8BBD0")),
Pair("color set 28",arrayOf<String>("#455A64","#E6EE9C")),
Pair("color set 29",arrayOf<String>("#455A64","#CFD8DC")),
Pair("color set 30",arrayOf<String>("#37474F","#FFF59D")),
Pair("color set 31",arrayOf<String>("#FFFFFF","#1C1B1B")),
Pair("color set 32",arrayOf<String>("#272727","#FFFFFF")),
Pair("color set 33",arrayOf<String>("#1C1B1B","#FFFFFF")),
Pair("color set 34",arrayOf<String>("#FFFFFF","#272727"))
)
val typesfacez : PairArray<Int> = arrayOf<Pair<String,Int>>(
Pair("정선 아리랑 혼", R.font.jsarirang_hon),
Pair("정선 아리랑 뿌리", R.font.jsarirang_ppuri),
Pair("정선 동강 레귤러", R.font.jsdongkang_regular),
Pair("손기정체", R.font.kcc_sonkeechung),
Pair("교보 손글씨", R.font.kyobo_handwriting_2021sjy),
Pair("태백 은하수", R.font.taebaek_milkyway),
Pair("taebaek_milkyway",R.font.taebaek_milkyway),
Pair("kccahnjunggeun",R.font.kccahnjunggeun),
Pair("kotra_songeulssi",R.font.kotra_songeulssi),
Pair("kotra_bold",R.font.kotra_bold),
Pair("cafe24oneprettynight",R.font.cafe24oneprettynight),
Pair("nnsgc_wsjidyp",R.font.nnsgc_wsjidyp),
Pair("nnsgc_yjc",R.font.nnsgc_yjc),
Pair("nnsgc_brhp",R.font.nnsgc_brhp),
Pair("nnsgc_md",R.font.nnsgc_md),
Pair("nnsgc_gd_an_gd",R.font.nnsgc_gd_an_gd),
Pair("dovemayo",R.font.dovemayo),
Pair("gabia_solmee",R.font.gabia_solmee),
Pair("ylee_mortal_heart_immortal_memory",R.font.ylee_mortal_heart_immortal_memory),
Pair("kcc_kimhoon",R.font.kcc_kimhoon),
Pair("taefont_tsthlml",R.font.taefont_tsthlml),
Pair("ssshinb7",R.font.ssshinb7),
Pair("godomaum",R.font.godomaum),
Pair("tvn_jguiyg_medium",R.font.tvn_jguiyg_medium),
Pair("tvn_jguiyg_light",R.font.tvn_jguiyg_light),
Pair("on_jsuhr",R.font.on_jsuhr),
Pair("on_jsuhl",R.font.on_jsuhl),
Pair("on_ychyuhr",R.font.on_ychyuhr),
Pair("on_ychyuhl",R.font.on_ychyuhl),
Pair("on_treeususimgul_r",R.font.on_treeususimgul_r),
Pair("on_treeususimgul",R.font.on_treeususimgul),
Pair("on_wibsr",R.font.on_wibsr),
Pair("on_wisbl",R.font.on_wisbl),
Pair("on_sbsjl",R.font.on_sbsjl),
Pair("on_sbsjr",R.font.on_sbsjr),
Pair("wandohoper",R.font.wandohoper),
Pair("ebs_r",R.font.ebs_r),
)
@JvmName("getIndexAny")
fun PairArray<Any>.getIndex(key : String) = getIndex(this, key)
fun getIndex(collection : PairArray<Any>, key : String) : Int {
var index = 0
var returns = 0
for (item in collection) {
if(item.first.equals(key)) {
returns = index
}
index = index.inc()
}
return returns
}
enum class TouchArea {
Left,Center,Right, DoubleLeft, DoubleRight
}
class Settings : CommonActivity() { class Settings : CommonActivity() {
lateinit var binding : SettingsBinding lateinit var binding : SettingsBinding

View File

@ -1,102 +0,0 @@
package bums.lunatic.launcher.tokiz
import android.os.Bundle
import android.view.LayoutInflater
import android.view.View
import android.view.View.GONE
import android.view.ViewGroup
import androidx.core.view.isVisible
import bums.lunatic.launcher.tokiz.common.TouchArea
import bums.lunatic.launcher.tokiz.view.PagedTextViewInterface
import bums.lunatic.launcher.utils.Blog
class Twitter : BaseToki(), PagedTextViewInterface {
override val contentsType = "twitter"
override var lastNumber : Int = 143
override val webcontentsName : String = "twitter"
override val afterDot = "com"
override fun getLastedDoamin(): String {
return String.format("https://%s.%s", webcontentsName, afterDot)
}
override fun onCreateView(
inflater: LayoutInflater,
container: ViewGroup?,
savedInstanceState: Bundle?
): View {
super.onCreateView(inflater, container, savedInstanceState)
return binding.root
}
override fun onStart() {
super.onStart()
}
override fun onResume() {
super.onResume()
loadLastInfo()
}
override fun onTouch(touchArea: TouchArea) {
Blog.LOGD(log = "onTouch ${touchArea}")
when (touchArea) {
TouchArea.Center -> {
}
TouchArea.Right -> {
actionNextEvent()
}
TouchArea.Left -> {
actionPrevEvent()
}
TouchArea.DoubleRight -> {
actionNextEvent(true)
}
TouchArea.DoubleLeft -> {
actionPrevEvent(true)
}
else -> {
}
}
}
override fun onLongClick() {
Blog.LOGD(log = "onLongClick")
}
override fun onSwipeLeft(count: Int) {
Blog.LOGD(log = "onSwipeLeft ${count}")
actionNextEvent(count > 1)
}
override fun onSwipeRight(count: Int) {
Blog.LOGD(log = "onSwipeRight ${count}")
actionPrevEvent(count > 1)
}
override fun onSwipeUp(touchCount: Int) {
}
override fun onSwipeDown(touchCount: Int) {
if (touchCount == 2) {
if (binding.pagedLayer.isVisible) {
binding.pagedLayer.visibility = GONE
}
}
}
override fun onTimeoverTouch() {
}
}

View File

@ -1,101 +0,0 @@
package bums.lunatic.launcher.tokiz
import android.os.Bundle
import android.view.LayoutInflater
import android.view.View
import android.view.View.GONE
import android.view.ViewGroup
import androidx.core.view.isVisible
import bums.lunatic.launcher.tokiz.common.TouchArea
import bums.lunatic.launcher.tokiz.view.PagedTextViewInterface
import bums.lunatic.launcher.utils.Blog
class Webtoons : BaseToki(), PagedTextViewInterface {
override val contentsType = "webtoon"
override var lastNumber : Int = 468
override val webcontentsName : String = "newtoki"
override val afterDot = "com"
override fun onCreateView(
inflater: LayoutInflater,
container: ViewGroup?,
savedInstanceState: Bundle?
): View {
super.onCreateView(inflater, container, savedInstanceState)
return binding.root
}
override fun onStart() {
super.onStart()
}
override fun onResume() {
super.onResume()
loadLastInfo()
Blog.LOGE("binding.root >>> ${binding.root}")
}
override fun onTouch(touchArea: TouchArea) {
Blog.LOGD(log = "onTouch ${touchArea}")
when (touchArea) {
TouchArea.Center -> {
}
TouchArea.Right -> {
actionNextEvent()
}
TouchArea.Left -> {
actionPrevEvent()
}
TouchArea.DoubleRight -> {
actionNextEvent(true)
}
TouchArea.DoubleLeft -> {
actionPrevEvent(true)
}
else -> {
}
}
}
override fun onLongClick() {
Blog.LOGD(log = "onLongClick")
}
override fun onSwipeLeft(count: Int) {
Blog.LOGD(log = "onSwipeLeft ${count}")
actionNextEvent(count > 1)
}
override fun onSwipeRight(count: Int) {
Blog.LOGD(log = "onSwipeRight ${count}")
actionPrevEvent(count > 1)
}
override fun onSwipeUp(touchCount: Int) {
}
override fun onSwipeDown(touchCount: Int) {
if (touchCount == 2) {
if (binding.pagedLayer.isVisible) {
binding.pagedLayer.visibility = GONE
}
}
}
override fun onTimeoverTouch() {
}
}

View File

@ -1,61 +0,0 @@
package bums.lunatic.launcher.tokiz
import android.os.Bundle
import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
import bums.lunatic.launcher.tokiz.common.TouchArea
class YouTube : BaseToki(){
override val contentsType = "youtube"
override var lastNumber : Int = 143
override val webcontentsName : String = "youtube"
override val afterDot = "com"
override var isPrivateMode: Boolean = true
override fun getLastedDoamin(): String {
return String.format("https://%s.%s", webcontentsName, afterDot)
}
override fun onCreateView(
inflater: LayoutInflater,
container: ViewGroup?,
savedInstanceState: Bundle?
): View {
super.onCreateView(inflater, container, savedInstanceState)
return binding.root
}
override fun onStart() {
super.onStart()
}
override fun onResume() {
super.onResume()
loadLastInfo()
}
override fun back() {
binding.menuWeb.session?.goBack()
}
override fun onTouch(touchArea: TouchArea) {
}
override fun onTimeoverTouch() {
}
override fun onSwipeLeft(touchCount: Int) {
}
override fun onSwipeRight(touchCount: Int) {
}
override fun onSwipeDown(touchCount: Int) {
}
override fun onSwipeUp(touchCount: Int) {
}
override fun onLongClick() {
}
}

View File

@ -1,99 +0,0 @@
package bums.lunatic.launcher.tokiz
import android.os.Bundle
import android.view.LayoutInflater
import android.view.View
import android.view.View.GONE
import android.view.ViewGroup
import androidx.core.view.isVisible
import bums.lunatic.launcher.tokiz.common.TouchArea
import bums.lunatic.launcher.tokiz.view.PagedTextViewInterface
import bums.lunatic.launcher.utils.Blog
class Zota : BaseToki(), PagedTextViewInterface {
override val contentsType = "Torrent"
override var lastNumber : Int = 143
override val webcontentsName : String = "torrentzota"
override val afterDot = "com"
override fun onCreateView(
inflater: LayoutInflater,
container: ViewGroup?,
savedInstanceState: Bundle?
): View {
super.onCreateView(inflater, container, savedInstanceState)
return binding.root
}
override fun onStart() {
super.onStart()
}
override fun onResume() {
super.onResume()
loadLastInfo()
}
override fun onTouch(touchArea: TouchArea) {
Blog.LOGD(log = "onTouch ${touchArea}")
when (touchArea) {
TouchArea.Center -> {
}
TouchArea.Right -> {
actionNextEvent()
}
TouchArea.Left -> {
actionPrevEvent()
}
TouchArea.DoubleRight -> {
actionNextEvent(true)
}
TouchArea.DoubleLeft -> {
actionPrevEvent(true)
}
else -> {
}
}
}
override fun onLongClick() {
Blog.LOGD(log = "onLongClick")
}
override fun onSwipeLeft(count: Int) {
Blog.LOGD(log = "onSwipeLeft ${count}")
actionNextEvent(count > 1)
}
override fun onSwipeRight(count: Int) {
Blog.LOGD(log = "onSwipeRight ${count}")
actionPrevEvent(count > 1)
}
override fun onSwipeUp(touchCount: Int) {
}
override fun onSwipeDown(touchCount: Int) {
if (touchCount == 2) {
if (binding.pagedLayer.isVisible) {
binding.pagedLayer.visibility = GONE
}
}
}
override fun onTimeoverTouch() {
}
}

View File

@ -1,88 +0,0 @@
package bums.lunatic.launcher.tokiz.common
import bums.lunatic.launcher.R
typealias PairArray<T> = Array<Pair<String,T>>
val colorz : PairArray<Array<String>> = arrayOf<Pair<String,Array<String>>>(
Pair("color set 01",arrayOf<String>("#E1F5FE", "#263238")),
Pair("color set 02",arrayOf<String>("#F0F4C3", "#37474F")),
Pair("color set 03",arrayOf<String>("#ECEFF1", "#455A64")),
Pair("color set 04",arrayOf<String>("#E0F7FA", "#263238")),
Pair("color set 05",arrayOf<String>("#F5F5F5", "#263238")),
Pair("color set 06",arrayOf<String>("#ECEFF1", "#263238")),
Pair("color set 07",arrayOf<String>("#F8BBD0", "#263238")),
Pair("color set 08",arrayOf<String>("#E6EE9C", "#455A64")),
Pair("color set 09",arrayOf<String>("#CFD8DC", "#455A64")),
Pair("color set 10",arrayOf<String>("#FFF59D", "#37474F")),
Pair("color set 21",arrayOf<String>("#263238","#E1F5FE")),
Pair("color set 22",arrayOf<String>("#37474F","#F0F4C3")),
Pair("color set 23",arrayOf<String>("#455A64","#ECEFF1")),
Pair("color set 24",arrayOf<String>("#263238","#E0F7FA")),
Pair("color set 25",arrayOf<String>("#263238","#F5F5F5")),
Pair("color set 26",arrayOf<String>("#263238","#ECEFF1")),
Pair("color set 27",arrayOf<String>("#263238","#F8BBD0")),
Pair("color set 28",arrayOf<String>("#455A64","#E6EE9C")),
Pair("color set 29",arrayOf<String>("#455A64","#CFD8DC")),
Pair("color set 30",arrayOf<String>("#37474F","#FFF59D")),
Pair("color set 31",arrayOf<String>("#FFFFFF","#1C1B1B")),
Pair("color set 32",arrayOf<String>("#272727","#FFFFFF")),
Pair("color set 33",arrayOf<String>("#1C1B1B","#FFFFFF")),
Pair("color set 34",arrayOf<String>("#FFFFFF","#272727"))
)
val typesfacez : PairArray<Int> = arrayOf<Pair<String,Int>>(
Pair("정선 아리랑 혼", R.font.jsarirang_hon),
Pair("정선 아리랑 뿌리", R.font.jsarirang_ppuri),
Pair("정선 동강 레귤러", R.font.jsdongkang_regular),
Pair("손기정체", R.font.kcc_sonkeechung),
Pair("교보 손글씨", R.font.kyobo_handwriting_2021sjy),
Pair("태백 은하수", R.font.taebaek_milkyway),
Pair("taebaek_milkyway",R.font.taebaek_milkyway),
Pair("kccahnjunggeun",R.font.kccahnjunggeun),
Pair("kotra_songeulssi",R.font.kotra_songeulssi),
Pair("kotra_bold",R.font.kotra_bold),
Pair("cafe24oneprettynight",R.font.cafe24oneprettynight),
Pair("nnsgc_wsjidyp",R.font.nnsgc_wsjidyp),
Pair("nnsgc_yjc",R.font.nnsgc_yjc),
Pair("nnsgc_brhp",R.font.nnsgc_brhp),
Pair("nnsgc_md",R.font.nnsgc_md),
Pair("nnsgc_gd_an_gd",R.font.nnsgc_gd_an_gd),
Pair("dovemayo",R.font.dovemayo),
Pair("gabia_solmee",R.font.gabia_solmee),
Pair("ylee_mortal_heart_immortal_memory",R.font.ylee_mortal_heart_immortal_memory),
Pair("kcc_kimhoon",R.font.kcc_kimhoon),
Pair("taefont_tsthlml",R.font.taefont_tsthlml),
Pair("ssshinb7",R.font.ssshinb7),
Pair("godomaum",R.font.godomaum),
Pair("tvn_jguiyg_medium",R.font.tvn_jguiyg_medium),
Pair("tvn_jguiyg_light",R.font.tvn_jguiyg_light),
Pair("on_jsuhr",R.font.on_jsuhr),
Pair("on_jsuhl",R.font.on_jsuhl),
Pair("on_ychyuhr",R.font.on_ychyuhr),
Pair("on_ychyuhl",R.font.on_ychyuhl),
Pair("on_treeususimgul_r",R.font.on_treeususimgul_r),
Pair("on_treeususimgul",R.font.on_treeususimgul),
Pair("on_wibsr",R.font.on_wibsr),
Pair("on_wisbl",R.font.on_wisbl),
Pair("on_sbsjl",R.font.on_sbsjl),
Pair("on_sbsjr",R.font.on_sbsjr),
Pair("wandohoper",R.font.wandohoper),
Pair("ebs_r",R.font.ebs_r),
)
@JvmName("getIndexAny")
fun PairArray<Any>.getIndex(key : String) = getIndex(this, key)
fun getIndex(collection : PairArray<Any>, key : String) : Int {
var index = 0
var returns = 0
for (item in collection) {
if(item.first.equals(key)) {
returns = index
}
index = index.inc()
}
return returns
}
enum class TouchArea {
Left,Center,Right, DoubleLeft, DoubleRight
}

View File

@ -1,29 +0,0 @@
package bums.lunatic.launcher.tokiz.common
import android.content.Context
import android.content.SharedPreferences
import bums.lunatic.launcher.utils.Blog
object PrefManager {
private val mainName = "Main_Pref_"
private val domainKey = "Last_Domain_"
private lateinit var main : SharedPreferences
fun init(context: Context) {
main = context.getSharedPreferences(mainName,Context.MODE_PRIVATE)
}
fun save(key : String, value : String?) {
main.edit().putString(key,value).apply()
}
fun load(key : String) : String? {
return main.getString(key, "")
}
// fun getLastDomain() : String {
// return main.getString(domainKey, BooktokiStruct.getLastedDoamin()) ?: BooktokiStruct.getLastedDoamin()
// }
fun putLastDomain(domain : String) {
Blog.LOGE("domain >>> ${domain}")
main.edit().putString(domainKey,domain).apply()
}
}

View File

@ -1,189 +0,0 @@
package bums.lunatic.launcher.tokiz.data
import bums.lunatic.launcher.tokiz.data.model.ContentsCollection
import bums.lunatic.launcher.tokiz.data.model.ContentsPageInfo
import bums.lunatic.launcher.tokiz.data.model.HistoryItem
import bums.lunatic.launcher.tokiz.data.model.LastInfo
import bums.lunatic.launcher.tokiz.data.model.ReaderConfig
import bums.lunatic.launcher.utils.Blog
import bums.lunatic.launcher.workers.WorkersDb
import io.realm.kotlin.Realm
import io.realm.kotlin.UpdatePolicy
object HistoryManager {
val openRealm : Realm = WorkersDb.getRealm()
fun save(lastInfo: LastInfo) {
openRealm.apply{
this.writeBlocking {
copyToRealm(lastInfo, UpdatePolicy.ALL)
}
}
}
fun save(historyItem: HistoryItem) {
openRealm.apply{
this.writeBlocking {
copyToRealm(historyItem, UpdatePolicy.ALL)
}
}
}
fun requestLastInfo(callback : (LastInfo)->Unit) {
openRealm.apply{
}
}
fun save(config : ReaderConfig) {
openRealm.apply{
this.writeBlocking {
copyToRealm(config,UpdatePolicy.ALL)
}
}
}
fun getBookInfos(contentsType : String,aUrl : String, callback : (ContentsCollection?)->Unit) {
var url : String = aUrl
Blog.LOGE("aUrl >>> ${aUrl} , contentsType ${contentsType}")
openRealm.apply{
if (url.startsWith("//")) {
while (url.startsWith("//")) {
url = url.replace("//","/").trim()
}
}
Blog.LOGE("aUrl >>> ${url}")
var contentsPageInfo = this.query(ContentsPageInfo::class).query("contentsType == $0", contentsType).query("pathUrl == $0 || bookPageUrl == $0","${url}").find()
if (contentsPageInfo != null && contentsPageInfo.count() > 0) {
Blog.LOGE("get ${contentsPageInfo}" )
var pgs = this.query(ContentsCollection::class,"bookPageUrl == $0", contentsPageInfo.first().bookPageUrl).find()
if (pgs.size > 0) {
pgs.first().let {
Blog.LOGE("get ${it} , ${it?.pages}")
callback.invoke(this.copyFromRealm(it))
}
} else {
callback.invoke(null)
}
} else {
callback.invoke(null)
}
}
}
fun getBookPageInfo(contentsType : String, aUrl : String, callback : (ContentsPageInfo?)->Unit) {
var url : String = aUrl
openRealm.apply{
if (url.startsWith("//")) {
while (url.startsWith("//")) {
url = url.replace("//","/").trim()
}
}
var result = this.query(ContentsPageInfo::class).query("contentsType == $0", contentsType).query("pathUrl == $0","${url}").find()
if (result.size > 0) {
var bookPageInfo = result?.first()
if (bookPageInfo != null) {
callback.invoke(bookPageInfo)
} else {
callback.invoke(null)
}
} else {
callback.invoke(null)
}
}
}
fun setBookPageInfo(contentsType : String,aUrl : String, page :Int) {
var url : String = aUrl
openRealm.writeBlocking {
if (url.startsWith("//")) {
while (url.startsWith("//")) {
url = url.replace("//","/").trim()
}
}
var result = this.query(ContentsPageInfo::class).query("contentsType == $0", contentsType).query("pathUrl == $0","${url}").find()
if (result.size > 0) {
var bookPageInfo = result?.first()
if (bookPageInfo != null) {
bookPageInfo.lastPage = page
}
}
}
}
fun getBooPageInfoContentsSave(contentsType : String,aUrl : String, contents : String) {
var url : String = if (aUrl.startsWith("//") || aUrl.startsWith("///") || aUrl.startsWith("////")) {
aUrl.replace("////","/").replace("///","/").replace("//","/")
} else aUrl
openRealm.writeBlocking {
Blog.LOGE("getBooPageInfoContentsSave ${url}")
val result = query(ContentsPageInfo::class).query("contentsType == $0", contentsType).query("pathUrl == $0", "${url}").find()
if (result.size > 0) {
result.first().contents = contents
copyToRealm(result.first(), UpdatePolicy.ALL)
}
}
}
fun getNextPage(contentsType : String,aUrl : String ,callback : (ContentsPageInfo?)->Unit) {
var url : String = aUrl
openRealm.apply{
if (url.startsWith("//")) {
while (url.startsWith("//")) {
url = url.replace("//","/").trim()
}
}
var contentsPageInfo =
this.query(ContentsPageInfo::class).query("contentsType == $0", contentsType).query("pathUrl == $0", url).find()
if (contentsPageInfo.size > 0) {
Blog.LOGE("getNextPage 2 => chapterNum : ${contentsPageInfo.first().chapterNum} , bookPageInfo.bookPageUrl : ${contentsPageInfo.first().bookPageUrl}" )
var results = this.query(ContentsPageInfo::class).query("chapterNum == $0",contentsPageInfo.first().chapterNum + 1).query("bookPageUrl == $0","${contentsPageInfo.first().bookPageUrl}").find()
if(results.size > 0) {
results.first().let {
Blog.LOGE("getNextPage 2 nextBook pathUrl : ${it.pathUrl}" )
callback.invoke(it)
}
} else {callback.invoke(null)}
} else {callback.invoke(null)}
}
}
fun getPrevPage(contentsType : String,aUrl : String ,callback : (ContentsPageInfo?)->Unit) {
var url : String = aUrl
openRealm.apply{
Blog.LOGE("getPrevPage ${url}" )
if (url.startsWith("//")) {
while (url.startsWith("//")) {
url = url.replace("//","/").trim()
}
}
Blog.LOGE("getPrevPage ${url}" )
var contentsPageInfo =
this.query(ContentsPageInfo::class).query("contentsType == $0", contentsType).query("pathUrl == $0", url).find()
Blog.LOGE("getPrevPage ${contentsPageInfo}" )
if (contentsPageInfo.size > 0) {
Blog.LOGE("getPrevPage 2 ${contentsPageInfo?.first()?.chapterNum}" )
Blog.LOGE("getPrevPage 2 ${contentsPageInfo?.first()?.bookPageUrl}" )
var results = this.query(ContentsPageInfo::class).query("chapterNum == $0",contentsPageInfo.first().chapterNum - 1).query("bookPageUrl == $0","${contentsPageInfo.first().bookPageUrl}").find()
if(results.size > 0) {
results.first()?.let {
Blog.LOGE("getPrevPage 2 ${it.bookPageUrl}" )
Blog.LOGE("getPrevPage 2 ${it.pathUrl}" )
callback.invoke(it)
}
} else {
callback.invoke(null)
}
} else {
callback.invoke(null)
}
}
}
}

View File

@ -1,143 +0,0 @@
package bums.lunatic.launcher.tokiz.data.model
import bums.lunatic.launcher.model.RssData
import io.realm.kotlin.ext.realmListOf
import io.realm.kotlin.types.RealmList
import io.realm.kotlin.types.RealmObject
import io.realm.kotlin.types.annotations.PrimaryKey
class PortMessage {
var type : String? = ""
var bookInfos : PageInfosJ? = null
var book : BookContents? = null
var msg : String? = null
var contents : String? = null
var privates : ArrayList<RssData>? = null
var currentPage : String? = null
var cookies : String? = null
var urls : List<String> = emptyList()
var imgSrc: String? = null
var base64Data: String? = null
}
class BookContents {
var chapterTitle : String? = null
var bookContents : String? = null
}
class PageInfosJ {
var bookTitle : String = ""
var bookPageUrl : String = ""
var contentsType : String? = ""
var pages : ArrayList<PageInfoJ> = arrayListOf<PageInfoJ>()
fun getTitleArray() : ArrayList<String> {
var arrayList = ArrayList<String>()
pages.forEach { arrayList.add(it.bookTitle ?: "") }
return arrayList
}
fun getR() : ContentsCollection{
var r = ContentsCollection()
r.bookTitle = this.bookTitle
r.bookPageUrl = this.bookPageUrl
r.contentsType = this.contentsType
return r
}
}
class PageInfoJ {
var chapterID : Int = 0
var contents : String? = ""
var bookPageUrl : String? = ""
var chapterTitle : String? = ""
var bookTitle : String? = ""
var chapterNum : Int = 0
var lastPage : Int? = 0
var pathUrl : String? = ""
var contentsType : String? = ""
fun getRealm() : ContentsPageInfo {
var r = ContentsPageInfo()
r.chapterID = this.chapterID
r.contents = this.contents
r.bookPageUrl = this.bookPageUrl ?: ""
r.chapterTitle = this.chapterTitle
r.bookTitle = this.bookTitle ?: ""
r.chapterNum = this.chapterNum
r.lastPage = this.lastPage
r.pathUrl = this.pathUrl?.replace("'","")
r.contentsType = this.contentsType
return r
}
}
class ContentsCollection : RealmObject {
var bookTitle : String = ""
@PrimaryKey
var bookPageUrl : String? = ""
var pages : RealmList<ContentsPageInfo> = realmListOf()
var contentsType : String? = ""
fun getTitleArray() : ArrayList<String> {
var arrayList = ArrayList<String>()
pages.forEach {
arrayList.add(it.getTitleItem())}
return arrayList
}
fun sort() {
val comparator : Comparator<ContentsPageInfo> = compareBy { it.chapterID }
pages.sortWith(comparator)
}
fun hasItem(item: ContentsPageInfo) : Boolean {
var hasItem = false
for (c in pages) {
if (!hasItem) {
hasItem = c.pathUrl.equals(item.pathUrl)
}
}
return hasItem
}
}
class ContentsPageInfo : RealmObject {
var chapterID : Int = 0
var contents : String? = ""
var bookPageUrl : String? = ""
var chapterTitle : String? = ""
var bookTitle : String? = ""
var chapterNum : Int = 0
var lastPage : Int? = 0
var contentsType : String? = ""
fun isValidBook() = (pathUrl?.length ?: 0) > 1
@PrimaryKey
var pathUrl : String? = ""
fun getTitleItem() : String {
var result = StringBuilder()
result.append(if ((contents?.length ?: 0) > 10) {
"S:[0] "
} else {
"[X] "
})
result.append(chapterTitle?: "")
result.append(if ((lastPage ?: 0) > 0) {
" [0] "
} else {
" [X] "
})
return result.toString()
}
}

View File

@ -1,47 +0,0 @@
package bums.lunatic.launcher.tokiz.data.model
class FakeSessions : ArrayList<FakeSession>{
constructor(initialCapacity: Int) : super(initialCapacity)
constructor() : super()
constructor(c: MutableCollection<out FakeSession>) : super(c)
}
data class FakeSession (val scrolldata: ScrollData, val history: History )
data class ScrollData(
val scroll: String,
val zoom: Zoom
)
data class Zoom(
val resolution: Int,
val displaySize: DisplaySize
)
data class DisplaySize(
val height: Int,
val width: Int
)
data class History(
val entries: List<HistoryEntry>,
val requestedIndex: Int,
val fromIdx: Int,
val index: Int
)
data class HistoryEntry(
val persist: Boolean,
val cacheKey: Int,
val ID: Int,
val url: String,
val title: String,
val loadReplace: Boolean,
val docIdentifier: Long,
val loadReplace2: Boolean,
val partitionedPrincipalToInherit_base64: Map<String, Map<String, String>>,
val triggeringPrincipal_base64: Map<String, Map<String, String>>,
val principalToInherit_base64: Map<String, Map<String, String>>,
val resultPrincipalURI: String,
val hasUserInteraction: Boolean,
val originalURI: String,
val docshellUUID: String
)

View File

@ -1,70 +0,0 @@
package bums.lunatic.launcher.tokiz.data.model
import android.content.pm.ActivityInfo
import io.realm.kotlin.types.RealmObject
import io.realm.kotlin.types.annotations.PrimaryKey
import java.text.SimpleDateFormat
import java.util.Date
class LastInfo : RealmObject {
@PrimaryKey
var _id : String = ""
var pageUrl : String = ""
var title : String = ""
var chapter : Int = 0
var pageIndex : Int = 0
var contentsName : String = ""
var contentsType : String? = ""
set(value) {
_id = value ?: ""
field = value
}
var displayOrientation : Int = ActivityInfo.SCREEN_ORIENTATION_PORTRAIT
fun makeHistoryItem() : HistoryItem = HistoryItem().apply {
title = this@LastInfo.title
pageUrl = this@LastInfo.pageUrl
chapter = this@LastInfo.chapter
pageIndex = this@LastInfo.pageIndex
contentsName = this@LastInfo.contentsName
displayOrientation = this@LastInfo.displayOrientation
contentsType = this@LastInfo.contentsType
}
}
class HistoryItem : RealmObject {
@PrimaryKey
var title : String = ""
var pageUrl : String = ""
var chapter : Int = 0
var pageIndex : Int = 0
var contentsName : String = ""
var displayOrientation : Int = ActivityInfo.SCREEN_ORIENTATION_PORTRAIT
var contentsType : String? = ""
fun makeLastInfo() = LastInfo().apply{
_id = "UniqLastId"
title = this@HistoryItem.title
pageUrl = this@HistoryItem.pageUrl
chapter = this@HistoryItem.chapter
pageIndex = this@HistoryItem.pageIndex
contentsName = this@HistoryItem.contentsName
displayOrientation = this@HistoryItem.displayOrientation
contentsType = this@HistoryItem.contentsType
}
fun putHistory(contentsPageInfo: ContentsPageInfo?, currentPath : String) : HistoryItem {
title = contentsPageInfo?.bookTitle ?: SimpleDateFormat("YY-mm-DD-HH:mm").format(Date())
pageUrl = contentsPageInfo?.pathUrl ?: currentPath
chapter = contentsPageInfo?.chapterNum ?: 0
pageIndex = contentsPageInfo?.lastPage ?: 0
contentsName = contentsPageInfo?.chapterTitle ?: ""
contentsType = contentsPageInfo?.contentsType ?: ""
return this
}
}
class Bookmark() : RealmObject {
@PrimaryKey
var pageUrl : String = ""
}

View File

@ -1,17 +0,0 @@
package bums.lunatic.launcher.tokiz.data.model
import io.realm.kotlin.types.RealmObject
import io.realm.kotlin.types.annotations.PrimaryKey
class ReaderConfig : RealmObject {
@PrimaryKey
var id : String? = "ReaderConfig"
var textSize : Int? = 14
var textColor : String? = "#FFFFFF"
var bgColor : String? = "#000000"
var style : Int? = 0
var lineSpace : Int? = 1
var letterSpace : Int? = 1
var font : String? = ""
var padding : Int? = 5
}

View File

@ -1,55 +0,0 @@
package bums.lunatic.launcher.tokiz.dialog
import android.R
import android.content.Context
import android.content.DialogInterface
import android.widget.ArrayAdapter
import androidx.appcompat.app.AlertDialog
import bums.lunatic.launcher.tokiz.data.model.ContentsPageInfo
object DefaultList {
fun showDefaultList(context: Context, title : String, items : Collection<ContentsPageInfo>, firstPosition : Int, choosedTitle : (Int)->String, chooedPositive : (Int)->Unit, saveCalback : (Int)->Unit ) {
val builderSingle: AlertDialog.Builder = AlertDialog.Builder(context)
builderSingle.setTitle(title)
val arrayAdapter =
ArrayAdapter<String>(context, R.layout.select_dialog_singlechoice)
for (item in items) {
arrayAdapter.add(item.getTitleItem())
}
builderSingle.setNeutralButton("전체 저장") { dialog, which ->
saveCalback.invoke(-1)
dialog.dismiss()
}
builderSingle.setNegativeButton("닫기",
DialogInterface.OnClickListener { dialog, which ->
dialog.dismiss() })
builderSingle.setAdapter(arrayAdapter,
DialogInterface.OnClickListener { dialog, position ->
val strName = arrayAdapter.getItem(position)
val builderInner: AlertDialog.Builder = AlertDialog.Builder(context)
builderInner.setMessage(strName)
builderInner.setTitle(choosedTitle.invoke(position))
builderInner.setNegativeButton("닫기") { dialog, which ->
}
// builderInner.setNeutralButton("자동 저장") { dialog, which ->
// saveCalback.invoke(position)
// }
builderInner.setPositiveButton("이동"){ dialog, which ->
chooedPositive.invoke(position)
dialog.dismiss()
}
builderInner.show().apply {
DialogManager.add(this)
}
})
builderSingle.create()?.apply{
setOnShowListener { d->
(d as? AlertDialog)?.let{
it.listView?.setSelection(firstPosition)
}
}
DialogManager.add(this)
}?.show()
}
}

View File

@ -1,17 +0,0 @@
package bums.lunatic.launcher.tokiz.dialog
import androidx.activity.ComponentDialog
object DialogManager {
val dialogs = arrayListOf<ComponentDialog>()
fun add(item : ComponentDialog) = dialogs.add(item)
fun closeAll() {
for (dialog in dialogs) {
try {
dialog?.dismiss()
} catch(e : Exception) {
}
}
}
}

View File

@ -1,97 +0,0 @@
package bums.lunatic.launcher.tokiz.dialog//package com.mime.dualscreenview.dialog
//
//import android.app.Dialog
//import android.content.Context
//import android.content.DialogInterface
//import android.graphics.Color
//import android.os.Bundle
//import android.view.LayoutInflater
//import android.view.View
//import android.view.ViewGroup
//import android.view.Window
//import android.widget.TextView
//import androidx.recyclerview.widget.GridLayoutManager
//import androidx.recyclerview.widget.RecyclerView
//import com.mime.dualscreenview.R
//import kotlin.random.Random
//
//interface StyleSelectInterface {
// fun onSelectStyle(bgColor : String, textColor : String)
//}
//class Stylez : Dialog {
// constructor(context: Context) : super(context) {initView(context)}
// constructor(context: Context, themeResId: Int) : super(context, themeResId) {initView(context)}
// constructor(
// context: Context,
// cancelable: Boolean,
// cancelListener: DialogInterface.OnCancelListener?
// ) : super(context, cancelable, cancelListener) {initView(context)}
//
// var styleSelectInterface : StyleSelectInterface? = null
//
// fun initView(context: Context) {
//
// }
//
// override fun onCreate(savedInstanceState: Bundle?) {
// super.onCreate(savedInstanceState)
// this.requestWindowFeature(Window.FEATURE_NO_TITLE);
// setCancelable(true)
// setContentView(R.layout.dialog_stylesz)
// val recyclerView: RecyclerView = findViewById(R.id.stylez_recyclerview)
// val adapterRe = AdapterRe(context, colorz)
// recyclerView.adapter = adapterRe
// recyclerView.layoutManager =
// GridLayoutManager(context, 2, GridLayoutManager.VERTICAL, false)
// }
//
// inner class AdapterRe(ctx: Context, myImageNameList: Array<Array<String>>) :
// RecyclerView.Adapter<StylezViewHolder>() {
// private val inflater: LayoutInflater
// private val myImageNameList: Array<Array<String>>
// private val ctx : Context
// init {
// inflater = LayoutInflater.from(ctx)
// this.ctx = ctx
// this.myImageNameList = myImageNameList
// }
//
// override fun onCreateViewHolder (
// parent: ViewGroup,
// viewType: Int
// ): StylezViewHolder {
// val view: View = inflater.inflate(R.layout.item_colorz, parent, false)
// return StylezViewHolder(view)
// }
//
// override fun onBindViewHolder(holder: StylezViewHolder, position: Int) {
// var colorz = myImageNameList.get(position)
// var sampleTextz = ctx.resources.getStringArray(R.array.sample_textz)
// holder?.setStyle(bgColor = colorz.get(1), textColor = colorz.get(0),sampleTextz.get(Random.nextInt(9876) % sampleTextz.size))
// }
//
//
// override fun getItemCount(): Int {
// return myImageNameList.size
// }
//
// }
//
// inner class StylezViewHolder(itemView: View) : RecyclerView.ViewHolder(itemView) {
// var textView: TextView
// var bg : View
// init {
// textView = itemView.findViewById(R.id.textview_sample)
// bg = itemView.findViewById(R.id.bg_sample)
// }
// fun setStyle(bgColor : String, textColor : String, sampleText : String ) {
// bg.setBackgroundColor(Color.parseColor(bgColor))
// textView.setTextColor(Color.parseColor(textColor))
// textView.text = sampleText
// itemView?.setOnClickListener { v ->
// styleSelectInterface?.onSelectStyle(bgColor,textColor)
// dismiss()
// }
// }
// }
//}

View File

@ -1,5 +0,0 @@
package bums.lunatic.launcher.tokiz.view
interface PagedTextGenerateInterface {
fun completePagination(pageList: ArrayList<CharSequence>)
}

View File

@ -6,16 +6,280 @@ import android.graphics.Color
import android.graphics.Typeface import android.graphics.Typeface
import android.os.Build import android.os.Build
import android.os.Handler import android.os.Handler
import android.text.Layout
import android.text.StaticLayout
import android.util.AttributeSet import android.util.AttributeSet
import android.util.TypedValue
import android.view.View import android.view.View
import android.widget.TextView import android.widget.TextView
import android.widget.TextView.BufferType
import androidx.appcompat.widget.AppCompatTextView
import androidx.constraintlayout.widget.ConstraintLayout import androidx.constraintlayout.widget.ConstraintLayout
import androidx.constraintlayout.widget.Guideline import androidx.constraintlayout.widget.Guideline
import bums.lunatic.launcher.R import bums.lunatic.launcher.R
import bums.lunatic.launcher.tokiz.common.TouchArea import bums.lunatic.launcher.tokiz.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 kotlinx.coroutines.MainScope
import kotlinx.coroutines.launch
import kotlin.math.min
interface PagedTextViewInterface {
fun onTouch(touchArea: TouchArea)
fun onTimeoverTouch()
fun onSwipeLeft(touchCount : Int)
fun onSwipeRight(touchCount : Int)
fun onSwipeDown(touchCount : Int)
fun onSwipeUp(touchCount : Int)
fun onLongClick()
}
class PagedTextView : AppCompatTextView {
private var needPaginate = false
private var isPaginating = false
private val pageList = arrayListOf<CharSequence>()
private var pageIndex: Int = 0
private var pageHeight: Int = 0
private var originalText: CharSequence = ""
var mPagedTextGenerateInterface : PagedTextGenerateInterface? = null
constructor(context: Context?) : super(context!!){initView(context)}
constructor(context: Context?, attrs: AttributeSet?) : super(context!!, attrs){initView(context)}
constructor(context: Context?, attrs: AttributeSet?, defStyleAttr: Int) : super(context!!, attrs, defStyleAttr){initView(context)}
fun initView(context: Context?){
}
fun size(): Int = pageList.size
fun current() : Int = pageIndex
fun doPrev() {
if (pageIndex > 0 )
pageIndex = pageIndex - 1
setPageText()
}
fun doNext() {
if (pageIndex < pageList.size)
pageIndex = pageIndex + 1
setPageText()
}
fun next(index: Int) {
pageIndex = index
setPageText()
}
private fun setPageText() {
if(pageList.size > 0) {
isPaginating = true
text = pageList[pageIndex]
isPaginating = false
}
}
fun setTxtF(text: CharSequence?) {
needPaginate = true
this.setText(text , null)
}
override fun setText(text: CharSequence?, type: BufferType?) {
if (!isPaginating) {
needPaginate = true
originalText = text ?: ""
}
super.setText(text, type)
}
override fun setTextSize(size: Float) {
setTextSize(TypedValue.COMPLEX_UNIT_SP, size)
}
override fun setTextSize(unit: Int, size: Float) {
super.setTextSize(unit, size)
paint.textSize = TypedValue.applyDimension(unit, size, context.resources.getDisplayMetrics())
needPaginate = true
}
override fun setPadding(left: Int, top: Int, right: Int, bottom: Int) {
super.setPadding(left, top, right, bottom)
needPaginate = true
}
override fun setPaddingRelative(start: Int, top: Int, end: Int, bottom: Int) {
super.setPaddingRelative(start, top, end, bottom)
needPaginate = true
}
override fun setTextScaleX(size: Float) {
if (size != textScaleX) {
needPaginate = true
}
super.setTextScaleX(size)
}
override fun setTypeface(tf: Typeface?) {
if (typeface != null && tf != typeface) {
needPaginate = true
paint.typeface = tf
}
super.setTypeface(tf)
}
@TargetApi(Build.VERSION_CODES.LOLLIPOP)
override fun setLetterSpacing(letterSpacing: Float) {
if (letterSpacing != this.letterSpacing) {
needPaginate = true
}
super.setLetterSpacing(letterSpacing)
}
override fun setHorizontallyScrolling(whether: Boolean) {
super.setHorizontallyScrolling(false)
}
override fun setLineSpacing(add: Float, mult: Float) {
if (add != lineSpacingExtra || mult != lineSpacingMultiplier) {
needPaginate = true
}
super.setLineSpacing(add, mult)
}
override fun setMaxLines(maxLines: Int) {
if (maxLines != this.maxLines) {
needPaginate = true
}
super.setMaxLines(maxLines)
}
override fun setLines(lines: Int) {
super.setLines(lines)
if (lines != this.lineCount) {
needPaginate = true
}
}
override fun onSizeChanged(w: Int, h: Int, oldw: Int, oldh: Int) {
super.onSizeChanged(w, h, oldw, oldh)
pageHeight = h - (paddingTop + paddingBottom) // 마진 제외
}
override fun onLayout(changed: Boolean, left: Int, top: Int, right: Int, bottom: Int) {
super.onLayout(changed, left, top, right, bottom)
Blog.LOGD(log = "onLayout>> ${this::class.java.name} changed >> ${changed}")
if (changed || needPaginate) {
paginate()
setPageText()
needPaginate = false
}
}
fun doUpdate() {
if (needPaginate && layout != null) {
paginate()
setPageText()
needPaginate = false
}
}
private fun paginate() {
if (layout != null) {
MainScope().launch {
pageList.clear()
// Blog.LOGD(log = "paginate>> ${this::class.java.name} && ${layout.text}")
val layout = from(layout)
val lines = if(min(maxLines, layout.lineCount) > 10) {min(maxLines, layout.lineCount) - 1} else {min(maxLines, layout.lineCount)}
var startOffset = 0
val heightWithoutPaddings = pageHeight //- (marginTop + marginBottom + paddingTop + paddingBottom)
var height = heightWithoutPaddings
for (i in 0 until lines) {
if (height < layout.getLineBottom(i)) {
pageList.add(
layout.text.subSequence(startOffset, layout.getLineStart(i))
)
startOffset = layout.getLineStart(i)
height = layout.getLineTop(i) + heightWithoutPaddings
}
if (i == lines - 1) {
pageList.add(
if(layout.lineCount > i) {
layout.text.subSequence(startOffset, layout.getLineEnd(i + 1))
} else {
layout.text.subSequence(startOffset, layout.getLineEnd(i))
}
)
}
}
mPagedTextGenerateInterface?.completePagination(pageList)
}
}
}
private fun from(layout: Layout): Layout =
if (Build.VERSION.SDK_INT < Build.VERSION_CODES.M) {
@Suppress("DEPRECATION")
StaticLayout(
originalText,
paint,
layout.width - paddingLeft - paddingRight, // margin 제외
layout.alignment,
lineSpacingMultiplier,
lineSpacingExtra,
includeFontPadding
)
} else {
StaticLayout.Builder
.obtain(
originalText, 0, originalText.length, paint,
(layout.width - paddingLeft - paddingRight)
)
.setAlignment(layout.alignment)
.setLineSpacing(lineSpacingExtra, lineSpacingMultiplier)
.setIncludePad(includeFontPadding)
.setUseLineSpacingFromFallbacks()
.setBreakStrategy(breakStrategy)
.setHyphenationFrequency(hyphenationFrequency)
.setMaxLines(maxLines)
.build()
}
private fun StaticLayout.Builder.setUseLineSpacingFromFallbacks(): StaticLayout.Builder {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.P) {
this.setUseLineSpacingFromFallbacks(isFallbackLineSpacing)
}
return this
}
private fun StaticLayout.Builder.setJustificationMode(): StaticLayout.Builder {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
this.setJustificationMode(justificationMode)
}
return this
}
}
interface PagedTextGenerateInterface {
fun completePagination(pageList: ArrayList<CharSequence>)
}
class PagedTextLayout : ConstraintLayout , PagedTextGenerateInterface { class PagedTextLayout : ConstraintLayout , PagedTextGenerateInterface {
constructor(context: Context) : super(context) {initView(context)} constructor(context: Context) : super(context) {initView(context)}
constructor(context: Context, attrs: AttributeSet?) : super(context, attrs) {initView(context)} constructor(context: Context, attrs: AttributeSet?) : super(context, attrs) {initView(context)}

View File

@ -1,259 +0,0 @@
package bums.lunatic.launcher.tokiz.view
import android.annotation.TargetApi
import android.content.Context
import android.graphics.Typeface
import android.os.Build
import android.text.Layout
import android.text.StaticLayout
import android.util.AttributeSet
import android.util.TypedValue
import androidx.appcompat.widget.AppCompatTextView
import bums.lunatic.launcher.utils.Blog
import kotlinx.coroutines.MainScope
import kotlinx.coroutines.launch
import kotlin.math.min
class PagedTextView : AppCompatTextView {
private var needPaginate = false
private var isPaginating = false
private val pageList = arrayListOf<CharSequence>()
private var pageIndex: Int = 0
private var pageHeight: Int = 0
private var originalText: CharSequence = ""
var mPagedTextGenerateInterface : PagedTextGenerateInterface? = null
constructor(context: Context?) : super(context!!){initView(context)}
constructor(context: Context?, attrs: AttributeSet?) : super(context!!, attrs){initView(context)}
constructor(context: Context?, attrs: AttributeSet?, defStyleAttr: Int) : super(context!!, attrs, defStyleAttr){initView(context)}
fun initView(context: Context?){
}
fun size(): Int = pageList.size
fun current() : Int = pageIndex
fun doPrev() {
if (pageIndex > 0 )
pageIndex = pageIndex - 1
setPageText()
}
fun doNext() {
if (pageIndex < pageList.size)
pageIndex = pageIndex + 1
setPageText()
}
fun next(index: Int) {
pageIndex = index
setPageText()
}
private fun setPageText() {
if(pageList.size > 0) {
isPaginating = true
text = pageList[pageIndex]
isPaginating = false
}
}
fun setTxtF(text: CharSequence?) {
needPaginate = true
this.setText(text , null)
}
override fun setText(text: CharSequence?, type: BufferType?) {
if (!isPaginating) {
needPaginate = true
originalText = text ?: ""
}
super.setText(text, type)
}
override fun setTextSize(size: Float) {
setTextSize(TypedValue.COMPLEX_UNIT_SP, size)
}
override fun setTextSize(unit: Int, size: Float) {
super.setTextSize(unit, size)
paint.textSize = TypedValue.applyDimension(unit, size, context.resources.getDisplayMetrics())
needPaginate = true
}
override fun setPadding(left: Int, top: Int, right: Int, bottom: Int) {
super.setPadding(left, top, right, bottom)
needPaginate = true
}
override fun setPaddingRelative(start: Int, top: Int, end: Int, bottom: Int) {
super.setPaddingRelative(start, top, end, bottom)
needPaginate = true
}
override fun setTextScaleX(size: Float) {
if (size != textScaleX) {
needPaginate = true
}
super.setTextScaleX(size)
}
override fun setTypeface(tf: Typeface?) {
if (typeface != null && tf != typeface) {
needPaginate = true
paint.typeface = tf
}
super.setTypeface(tf)
}
@TargetApi(Build.VERSION_CODES.LOLLIPOP)
override fun setLetterSpacing(letterSpacing: Float) {
if (letterSpacing != this.letterSpacing) {
needPaginate = true
}
super.setLetterSpacing(letterSpacing)
}
override fun setHorizontallyScrolling(whether: Boolean) {
super.setHorizontallyScrolling(false)
}
override fun setLineSpacing(add: Float, mult: Float) {
if (add != lineSpacingExtra || mult != lineSpacingMultiplier) {
needPaginate = true
}
super.setLineSpacing(add, mult)
}
override fun setMaxLines(maxLines: Int) {
if (maxLines != this.maxLines) {
needPaginate = true
}
super.setMaxLines(maxLines)
}
override fun setLines(lines: Int) {
super.setLines(lines)
if (lines != this.lineCount) {
needPaginate = true
}
}
override fun onSizeChanged(w: Int, h: Int, oldw: Int, oldh: Int) {
super.onSizeChanged(w, h, oldw, oldh)
pageHeight = h - (paddingTop + paddingBottom) // 마진 제외
}
override fun onLayout(changed: Boolean, left: Int, top: Int, right: Int, bottom: Int) {
super.onLayout(changed, left, top, right, bottom)
Blog.LOGD(log = "onLayout>> ${this::class.java.name} changed >> ${changed}")
if (changed || needPaginate) {
paginate()
setPageText()
needPaginate = false
}
}
fun doUpdate() {
if (needPaginate && layout != null) {
paginate()
setPageText()
needPaginate = false
}
}
private fun paginate() {
if (layout != null) {
MainScope().launch {
pageList.clear()
// Blog.LOGD(log = "paginate>> ${this::class.java.name} && ${layout.text}")
val layout = from(layout)
val lines = if(min(maxLines, layout.lineCount) > 10) {min(maxLines, layout.lineCount) - 1} else {min(maxLines, layout.lineCount)}
var startOffset = 0
val heightWithoutPaddings = pageHeight //- (marginTop + marginBottom + paddingTop + paddingBottom)
var height = heightWithoutPaddings
for (i in 0 until lines) {
if (height < layout.getLineBottom(i)) {
pageList.add(
layout.text.subSequence(startOffset, layout.getLineStart(i))
)
startOffset = layout.getLineStart(i)
height = layout.getLineTop(i) + heightWithoutPaddings
}
if (i == lines - 1) {
pageList.add(
if(layout.lineCount > i) {
layout.text.subSequence(startOffset, layout.getLineEnd(i + 1))
} else {
layout.text.subSequence(startOffset, layout.getLineEnd(i))
}
)
}
}
mPagedTextGenerateInterface?.completePagination(pageList)
}
}
}
private fun from(layout: Layout): Layout =
if (Build.VERSION.SDK_INT < Build.VERSION_CODES.M) {
@Suppress("DEPRECATION")
StaticLayout(
originalText,
paint,
layout.width - paddingLeft - paddingRight, // margin 제외
layout.alignment,
lineSpacingMultiplier,
lineSpacingExtra,
includeFontPadding
)
} else {
StaticLayout.Builder
.obtain(
originalText, 0, originalText.length, paint,
(layout.width - paddingLeft - paddingRight)
)
.setAlignment(layout.alignment)
.setLineSpacing(lineSpacingExtra, lineSpacingMultiplier)
.setIncludePad(includeFontPadding)
.setUseLineSpacingFromFallbacks()
.setBreakStrategy(breakStrategy)
.setHyphenationFrequency(hyphenationFrequency)
.setMaxLines(maxLines)
.build()
}
private fun StaticLayout.Builder.setUseLineSpacingFromFallbacks(): StaticLayout.Builder {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.P) {
this.setUseLineSpacingFromFallbacks(isFallbackLineSpacing)
}
return this
}
private fun StaticLayout.Builder.setJustificationMode(): StaticLayout.Builder {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
this.setJustificationMode(justificationMode)
}
return this
}
}

View File

@ -1,13 +0,0 @@
package bums.lunatic.launcher.tokiz.view
import bums.lunatic.launcher.tokiz.common.TouchArea
interface PagedTextViewInterface {
fun onTouch(touchArea: TouchArea)
fun onTimeoverTouch()
fun onSwipeLeft(touchCount : Int)
fun onSwipeRight(touchCount : Int)
fun onSwipeDown(touchCount : Int)
fun onSwipeUp(touchCount : Int)
fun onLongClick()
}

View File

@ -1,61 +0,0 @@
package bums.lunatic.launcher.tokiz.view
import android.content.Context
import android.util.AttributeSet
class ScopeEditor: SideButtonTextView {
constructor(context: Context) : super(context)
constructor(context: Context, attrs: AttributeSet?) : super(context, attrs)
constructor(context: Context, attrs: AttributeSet?, defStyleAttr: Int) : super(
context,
attrs,
defStyleAttr
)
var titleArray : Array<String>? = null
set(value) {
if(value != null && value.size < 1) {
Error("titleArray는 최소 한개 이상이여야됨.")
return
}
field = value
maxValue = field!!.size
}
var maxValue : Int = 1
set(value) {
if (value < 1) {
Error("maxValue는 무조건 0보다 커야하눈뎅....")
return
}
field = value
}
override var value : Int = 14
set(newValue) {
field = newValue
text_value?.text = displayFormat.format(titleArray?.get(field) ?:"defulat")
mValueChange?.invoke(field)
}
constructor(
context: Context,
attrs: AttributeSet?,
defStyleAttr: Int,
defStyleRes: Int
) : super(context, attrs, defStyleAttr, defStyleRes)
init {
// super.i
// inflate(context, R.layout.layout_steps_editor,this)
btn_decrement?.setOnClickListener { value = Math.abs(value.dec()).rem(maxValue) }
btn_increment?.setOnClickListener { value = value.inc().rem(maxValue) }
leftButtonTitle = "<"
rightButtonTitle = ">"
}
}

View File

@ -6,6 +6,7 @@ import android.widget.TextView
import androidx.appcompat.widget.AppCompatButton import androidx.appcompat.widget.AppCompatButton
import androidx.constraintlayout.widget.ConstraintLayout import androidx.constraintlayout.widget.ConstraintLayout
import bums.lunatic.launcher.R import bums.lunatic.launcher.R
typealias ValueChange = (Int)->Unit
open class SideButtonTextView : ConstraintLayout { open class SideButtonTextView : ConstraintLayout {
constructor(context: Context) : super(context) constructor(context: Context) : super(context)
@ -72,4 +73,84 @@ open class SideButtonTextView : ConstraintLayout {
btn_decrement?.setOnClickListener { value = value.dec() } btn_decrement?.setOnClickListener { value = value.dec() }
btn_increment?.setOnClickListener { value = value.inc() } btn_increment?.setOnClickListener { value = value.inc() }
} }
}
class ScopeEditor: SideButtonTextView {
constructor(context: Context) : super(context)
constructor(context: Context, attrs: AttributeSet?) : super(context, attrs)
constructor(context: Context, attrs: AttributeSet?, defStyleAttr: Int) : super(
context,
attrs,
defStyleAttr
)
var titleArray : Array<String>? = null
set(value) {
if(value != null && value.size < 1) {
Error("titleArray는 최소 한개 이상이여야됨.")
return
}
field = value
maxValue = field!!.size
}
var maxValue : Int = 1
set(value) {
if (value < 1) {
Error("maxValue는 무조건 0보다 커야하눈뎅....")
return
}
field = value
}
override var value : Int = 14
set(newValue) {
field = newValue
text_value?.text = displayFormat.format(titleArray?.get(field) ?:"defulat")
mValueChange?.invoke(field)
}
constructor(
context: Context,
attrs: AttributeSet?,
defStyleAttr: Int,
defStyleRes: Int
) : super(context, attrs, defStyleAttr, defStyleRes)
init {
// super.i
// inflate(context, R.layout.layout_steps_editor,this)
btn_decrement?.setOnClickListener { value = Math.abs(value.dec()).rem(maxValue) }
btn_increment?.setOnClickListener { value = value.inc().rem(maxValue) }
leftButtonTitle = "<"
rightButtonTitle = ">"
}
}
class StepsEditor : SideButtonTextView {
constructor(context: Context) : super(context)
constructor(context: Context, attrs: AttributeSet?) : super(context, attrs)
constructor(context: Context, attrs: AttributeSet?, defStyleAttr: Int) : super(
context,
attrs,
defStyleAttr
)
constructor(
context: Context,
attrs: AttributeSet?,
defStyleAttr: Int,
defStyleRes: Int
) : super(context, attrs, defStyleAttr, defStyleRes)
init {
// inflate(context, R.layout.layout_steps_editor,this)
btn_decrement?.setOnClickListener { value = value.dec() }
btn_increment?.setOnClickListener { value = value.inc() }
leftButtonTitle = "-"
rightButtonTitle = "+"
}
} }

View File

@ -1,31 +0,0 @@
package bums.lunatic.launcher.tokiz.view
import android.content.Context
import android.util.AttributeSet
typealias ValueChange = (Int)->Unit
class StepsEditor : SideButtonTextView {
constructor(context: Context) : super(context)
constructor(context: Context, attrs: AttributeSet?) : super(context, attrs)
constructor(context: Context, attrs: AttributeSet?, defStyleAttr: Int) : super(
context,
attrs,
defStyleAttr
)
constructor(
context: Context,
attrs: AttributeSet?,
defStyleAttr: Int,
defStyleRes: Int
) : super(context, attrs, defStyleAttr, defStyleRes)
init {
// inflate(context, R.layout.layout_steps_editor,this)
btn_decrement?.setOnClickListener { value = value.dec() }
btn_increment?.setOnClickListener { value = value.inc() }
leftButtonTitle = "-"
rightButtonTitle = "+"
}
}

View File

@ -1,226 +0,0 @@
package bums.lunatic.launcher.tokiz.webcontents//package com.mime.dualscreenview.webcontents
//
//import android.annotation.SuppressLint
//import android.content.Context
//import android.graphics.Bitmap
//import android.net.http.SslError
//import android.os.Build
//import android.util.Log
//import android.webkit.SslErrorHandler
//import android.webkit.WebResourceRequest
//import android.webkit.WebResourceResponse
//import android.webkit.WebView
//import android.webkit.WebViewClient
//import androidx.core.net.toUri
//import com.mime.dualscreenview.common.Blog
//import com.mime.dualscreenview.common.PrefManager
//import com.mime.dualscreenview.data.model.LastInfo
//
//import okhttp3.ConnectionPool
//import okhttp3.Headers
//import okhttp3.Headers.Companion.toHeaders
//import okhttp3.Interceptor
//import okhttp3.MediaType.Companion.toMediaTypeOrNull
//import okhttp3.OkHttpClient
//import okhttp3.Request
//import okhttp3.RequestBody
//import okhttp3.Response
//
//import java.io.IOException
//import java.net.SocketException
//import java.util.concurrent.TimeUnit
//
//
//class BWebviewClient
// (
// private val mainControllInterface : MainControllInterface,
// private val context: Context, ) : WebViewClient() {
//
// var currentContentsProvider : BaseWebContents? = null
// // OkHttp 클라이언트 (싱글톤 권장)
// private val httpClient by lazy {
// OkHttpClient.Builder()
// .retryOnConnectionFailure(true)
// .connectionPool(ConnectionPool(5, 30, TimeUnit.SECONDS))
// .pingInterval(20, TimeUnit.SECONDS)
// .addInterceptor(RetryInterceptor(maxRetries = 3))
// .build()
// }
//
// override fun shouldInterceptRequest(
// view: WebView?,
// request: WebResourceRequest?
// ): WebResourceResponse? {
// request ?: return null
//
// // HTTPS/HTTP 요청만 처리
// if (request.url.scheme !in listOf("http", "https")) {
// return super.shouldInterceptRequest(view, request)
// }
//
// if (request.method != "GET" ||
// request.url.scheme !in listOf("http", "https")) {
// return super.shouldInterceptRequest(view, request)
// }
//
// // 웹뷰 요청을 OkHttp로 변환
// return try {
// val okHttpRequest = Request.Builder()
// .url(request.url.toString())
// .headers(request.requestHeaders.toHeaders())
// .get() // GET 요청으로 고정
// .build()
//
// val response = httpClient.newCall(okHttpRequest).execute()
// createWebResourceResponse(response)
//
// } catch (e: SocketException) {
// // Connection reset 오류 처리
// Log.e("WebViewClient", "SocketException: ${e.message}")
// null // WebView 기본 동작 사용
// } catch (e: IOException) {
// null // 오류 시 WebView 기본 동작
// }
// }
//
//// private fun getRequestBody(request: WebResourceRequest): RequestBody? {
//// // POST 요청 바디 처리 (API 21+)
//// return if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP &&
//// request.method == "POST" &&
//// request.requestBody != null) {
////
//// val body = request.requestBody!!
//// RequestBody.create(
//// body.mimeType?.toMediaTypeOrNull(),
//// body.inputStream.readBytes()
//// )
//// } else {
//// null
//// }
//// }
//
// private fun createWebResourceResponse(response: Response): WebResourceResponse {
// return WebResourceResponse(
// response.body?.contentType()?.type + "/" + response.body?.contentType()?.subtype,
// response.body?.contentType()?.charset()?.name(),
// response.code,
// response.message,
// response.headers.toMultimap().mapValues { it.value.joinToString(",") },
// response.body?.byteStream()
// )
// }
//
// // Connection reset 재시도 인터셉터
// inner class RetryInterceptor(
// private val maxRetries: Int
// ) : Interceptor {
// override fun intercept(chain: Interceptor.Chain): Response {
// var response: Response? = null
// var retryCount = 0
// var lastException: Exception? = null
//
// while (retryCount <= maxRetries) {
// try {
// response = chain.proceed(chain.request())
// if (response.isSuccessful) return response
// } catch (e: SocketException) {
// lastException = e
// if (e.message?.contains("Connection reset") == true) {
// Thread.sleep(1000L * (retryCount + 1))
// } else throw e
// } catch (e: IOException) {
// lastException = e
// }
// retryCount++
// }
// throw lastException ?: IOException("Max retries reached")
// }
// }
//
//
// override fun shouldOverrideUrlLoading(
// view: WebView?,
// request: WebResourceRequest?
// ): Boolean {
// Log.e("shouldOverrideUrlLoading", " >>>> ${request?.url?.toString()} ")
// return super.shouldOverrideUrlLoading(view, request)
// }
//
//
// override fun onPageStarted(view: WebView?, url: String?, favicon: Bitmap?) {
// super.onPageStarted(view, url, favicon)
// mainControllInterface?.onStartLoad()
// }
//
// @SuppressLint("WebViewClientOnReceivedSslError")
// override fun onReceivedSslError(
// view: WebView?,
// handler: SslErrorHandler?,
// error: SslError?
// ) {
//// super.onReceivedSslError(view, handler, error)
// Blog.LOGE(log= "onReceivedSslError >> ${error}")
// handler?.proceed()
// }
// override fun onReceivedHttpError(
// view: WebView?,
// request: WebResourceRequest?,
// errorResponse: WebResourceResponse?
// ) {
// Blog.LOGE(log= "onReceivedHttpError >> ${errorResponse?.reasonPhrase}")
//
// super.onReceivedHttpError(view, request, errorResponse)
// }
//
//
// override fun onPageFinished(view: WebView?, url: String?) {
// super.onPageFinished(view, url)
// finishedUrl = url ?: ""
//
// view?.let {
// url?.toUri()?.let {
// PrefManager.putLastDomain(it.scheme.plus("::/").plus(it.host))
// }
//
// if(url?.contains("/list/") ?: false && url?.contains("agit") ?: false){
// findListItem {
// Blog.LOGE("onPageFinished", url ?: "")
// }
// } else if (url?.contains("booktoki") ?: false){
//// findListItem {
//// Blog.LOGE("onPageFinished", url ?: "")
//// }
// }
// view?.postDelayed({
// if (url?.contains("booktoki") ?: false){
// findListItem {
// Blog.LOGE("onPageFinished", url ?: "")
// }
// }
//// view?.evaluateJavascript(
//// "function getAll() {\n" +
//// " MyJavaScriptInterface.sendValueFromHtml(document.getElementsByTagName('html')[0].innerHTML)" +
//// " };getAll()"
//// ) { result ->
//// (result as? String)?.let {
////
//// }
//// }
//
// }, 500L)
// currentContentsProvider?.doOnloaded(it , { result ->
// result?.let { mainControllInterface.onLoadedContents(it) }
// } , { complete ->
// if(complete) {
// mainControllInterface?.completePageLoad(LastInfo().apply {
// this.pageUrl = url?.toUri()?.path ?: currentContentsProvider?.getLastedDoamin() ?: ""
// this.contentsName = currentContentsProvider?.getWebcontentsName() ?: ""
// this.pageIndex = 0
// })
// }
// })
//
// }
// }
//
//}

View File

@ -1,416 +0,0 @@
package bums.lunatic.launcher.tokiz.webcontents
import org.jsoup.select.Elements
//open class BaseWebContentsViewer {
//
//// var currentContentsProvider : BaseWebContents? = null
//// lateinit var webview : BWebview
// lateinit var webview: BWebview
// lateinit var mainControllInterface : MainControllInterface
////
//// @JavascriptInterface
//// fun onBookInfo(jsonData : String) {
//// GlobalScope.launch {
//// try {
//// Blog.LOGE("BaseWebContentsViewer",jsonData)
//// val data: JSONObject = JSONObject(jsonData)
//// Blog.LOGE("BaseWebContentsViewer",data.toString())
//// mainControllInterface?.onBookInfos(jsonData)
//// } catch (e : Exception) {
////
//// }
//// }
//// }
//
// fun getDeviceIpAddress(): String? {
// try {
// val en = NetworkInterface.getNetworkInterfaces()
// while (en.hasMoreElements()) {
// val intf = en.nextElement()
// val enumIpAddr = intf.inetAddresses
// while (enumIpAddr.hasMoreElements()) {
// val inetAddress = enumIpAddr.nextElement()
// if (!inetAddress.isLoopbackAddress && inetAddress is Inet4Address) {
// return inetAddress.getHostAddress()
// }
// }
// }
// } catch (ex: SocketException) {
// ex.printStackTrace()
// }
// return null
// }
//
// constructor(geckoView: BWebview, mainControllInterface : MainControllInterface ) {
//// val wifiManager = webview.context.getSystemService(Context.WIFI_SERVICE) as WifiManager
//// wifiManager.disconnect()
//// Thread.sleep(1000) // 잠시 대기
//// wifiManager.reconnect()
//
// this.webview = geckoView
//// this.mainControllInterface = mainControllInterface
//
// }
////
////// @SuppressLint("JavascriptInterface", "SetJavaScriptEnabled")
////// constructor(webview : BWebview, mainControllInterface : MainControllInterface ) {
//////// val wifiManager = webview.context.getSystemService(Context.WIFI_SERVICE) as WifiManager
//////// wifiManager.disconnect()
//////// Thread.sleep(1000) // 잠시 대기
//////// wifiManager.reconnect()
//////
////// this.webview = webview
////// this.mainControllInterface = mainControllInterface
////// //137.0.0.0
////// webview.clearHistory();
////// webview.clearSslPreferences();
////// WebView.setWebContentsDebuggingEnabled(true)
////// webview.clearCache(true) // 디스크와 메모리 캐시 모두 삭제
//////
////// val cookieManager = CookieManager.getInstance()
////// cookieManager.removeAllCookies(null) // 모든 쿠키 삭제
////// cookieManager.flush()
//////// webview.settings.userAgentString = "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/119.0.0.0 Safari/537.36"
//////// webview.settings.userAgentString ="Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/119.0.0.0 Safari/537.36"
//////// webview.settings.userAgentString ="Mozilla/5.0 (Linux; Android 10; K) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/137.0.0.0 Mobile Safari/537.36"
////// webview.webChromeClient = rootWebChromeClient
////// webview.webViewClient = rootWebViewClient
////// webview.settings.textZoom = 100
////// webview.addJavascriptInterface(this,"PAgit")
////// webview.settings.javaScriptEnabled = true
////// webview.settings.javaScriptCanOpenWindowsAutomatically = false
////// webview.settings.loadWithOverviewMode = true
////// webview.settings.setPluginState(WebSettings.PluginState.ON)
////// webview.settings.domStorageEnabled = true
////// webview.settings.allowContentAccess = true
////// webview.settings.mixedContentMode = 0
//////
////// webview.getSettings().setJavaScriptEnabled(true)
//////// webview.loadUrl(stringExtra)
//////// webview.setWebViewClient(WebViewClientClass())
////// webview.setScrollBarStyle(0)
////// webview.settings.safeBrowsingEnabled = false
////// webview.settings.loadsImagesAutomatically = true
////// webview.getSettings().setCacheMode(-1)
////// webview.getSettings().setJavaScriptCanOpenWindowsAutomatically(false)
////// webview.getSettings().setLoadsImagesAutomatically(true)
////// webview.getSettings().setUseWideViewPort(true)
////// webview.getSettings().setDomStorageEnabled(true)
////// webview.getSettings().setAllowFileAccess(true)
//////
////// webview.getSettings()
////// .setUserAgentString("Mozilla/5.0 (Linux; Android 6.0; Android SDK built for x86 Build/MASTER; wv) AppleWebKit/537.36 (KHTML, like Gecko) Version/4.0 Chrome/44.0.2403.119 Mobile Safari/537.36")
////// webview.settings.userAgentString = "Mozilla/5.0 (Linux; Android 6.0; Android SDK built for x86 Build/MASTER; wv) AppleWebKit/537.36 (KHTML, like Gecko) Version/4.0 Chrome/44.0.2403.119 Mobile Safari/537.36"
////// webview.getSettings().setSupportZoom(true)
////// webview.getSettings().setBuiltInZoomControls(true)
////// webview.getSettings().setDisplayZoomControls(false)
////// val settings: WebSettings = webview.getSettings()
////// settings.javaScriptEnabled = true
////// settings.javaScriptCanOpenWindowsAutomatically = false
////// settings.setSupportMultipleWindows(false)
////// webview.clearCache(true);
//////
//////
//////
//////
////// try {
////// val settings: WebSettings =webview.getSettings()
//////// 네트워크 및 기능 관련
////// settings.javaScriptEnabled = true // 자바스크립트 활성화
////// settings.javaScriptCanOpenWindowsAutomatically = true // JS로 새창 열기 허용
////// settings.loadsImagesAutomatically = true // 이미지 자동 로드
////// settings.domStorageEnabled = true // DOM Storage 활성화
////// settings.databaseEnabled = true // DB 저장소 활성화
//////// settings.app
//////// settings.setAppCacheEnabled(true) // 앱 캐시 활성화 (deprecated, 참고용)
////// settings.allowFileAccess = true // 파일 접근 허용
////// settings.allowContentAccess = true // 컨텐츠 접근 허용
////// settings.allowFileAccessFromFileURLs = true // file://에서 file:// 접근 허용
////// settings.allowUniversalAccessFromFileURLs = true // file://에서 모든 도메인 접근 허용
////// settings.setSupportMultipleWindows(true) // 멀티 윈도우 지원
////// settings.useWideViewPort = true // 뷰포트 확대 지원
////// settings.loadWithOverviewMode = true // 화면에 맞게 컨텐츠 축소
////// settings.setSupportZoom(true) // 줌 지원
////// settings.builtInZoomControls = true // 기본 줌 컨트롤 활성화
////// settings.displayZoomControls = false // 줌 컨트롤 UI 숨김
//////
//////
//////// 보안 및 고급
////// settings.mixedContentMode =
////// WebSettings.MIXED_CONTENT_ALWAYS_ALLOW // HTTP/HTTPS 혼합 콘텐츠 허용
////// if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
////// settings.safeBrowsingEnabled = true // Safe Browsing 활성화
////// }
////// settings.mediaPlaybackRequiresUserGesture = false // 미디어 자동재생 허용
//////
//////
//////// 기타
////// settings.cacheMode = WebSettings.LOAD_NO_CACHE // 기본 캐시 모드
//////// settings.setGeolocationEnabled(true) // 위치 정보 허용
////// webview.removeJavascriptInterface("MyJavaScriptInterface")
////// }catch (e :Exception){e.printStackTrace()}
////// webview.addJavascriptInterface( BookHelper(),"MyJavaScriptInterface")
////// }
////
//// constructor()
////
//// fun loadContents(url: String) {
//// webview.loadUrl(url)
//// }
////
//// val rootWebChromeClient = object : WebChromeClient() {
//// override fun onProgressChanged(view: WebView?, newProgress: Int) {
//// super.onProgressChanged(view, newProgress)
//// }
////
//// override fun onJsAlert(
//// view: WebView?,
//// url: String?,
//// message: String?,
//// result: JsResult?
//// ): Boolean {
//// Blog.LOGE("message")
//// result?.cancel()
//// return super.onJsAlert(view, url, message, result)
//// }
////
//// override fun onJsPrompt(
//// view: WebView?,
//// url: String?,
//// message: String?,
//// defaultValue: String?,
//// result: JsPromptResult?
//// ): Boolean {
//// Blog.LOGE("message")
//// result?.cancel()
//// return super.onJsPrompt(view, url, message, defaultValue, result)
//// }
////
//// override fun onJsConfirm(
//// view: WebView?,
//// url: String?,
//// message: String?,
//// result: JsResult?
//// ): Boolean {
//// Blog.LOGE("message")
//// result?.cancel()
//// return super.onJsConfirm(view, url, message, result)
//// }
//// }
////
//// fun findListItem(callBakItems : DidFindContents) {
////// currentContentsProvider?.findListItem(webview,callBakItems)
//// }
////
// fun loadLastInfo(lastInfo: LastInfo) {
// lastInfo?.let { last ->
// if (last.pageUrl.startsWith("https://")) {
// webview.loadUrl(last.pageUrl)
// } else {
// try {
// webview.loadUrl(PrefManager.getLastDomain().plus(last.pageUrl))
// } catch (e : Exception) {
// webview.loadUrl(PrefManager.getLastDomain())
// }
// }
// }
// }
////
//// val rootWebViewClient = object : WebViewClient() {
//// override fun shouldOverrideUrlLoading(
//// view: WebView?,
//// request: WebResourceRequest?
//// ): Boolean {
//// Log.e("shouldOverrideUrlLoading", " >>>> ${request?.url?.toString()} ")
//// return super.shouldOverrideUrlLoading(view, request)
//// }
//// override fun shouldInterceptRequest(
//// view: WebView?,
//// request: WebResourceRequest?
//// ): WebResourceResponse? {
//// Log.e("shouldInterceptRequest", " >>>> ${request?.url?.toString()} , ${request?.url?.toString()?.contains("gif")}")
////
////// if(request?.url?.toString()?.contains("gif") ?: false) {
////// return WebResourceResponse("text/javascript", "UTF-8", null);
////// }
////// if(request?.url?.toString()?.contains(currentContentsProvider?.acccceptResourceKeyword() ?: "") == false && request?.url?.toString()?.contains(currentContentsProvider?.getLastedDoamin() ?: "") == false) {
////// return WebResourceResponse("text/javascript", "UTF-8", null);
////// }
//// return super.shouldInterceptRequest(view, request)
//// }
////
//// override fun onPageStarted(view: WebView?, url: String?, favicon: Bitmap?) {
//// super.onPageStarted(view, url, favicon)
//// mainControllInterface?.onStartLoad()
//// try {
//// handler.removeCallbacks(reloadPostHandle)
//// }catch (e : Exception) {
////
//// }
//// }
////
////// @SuppressLint("WebViewClientOnReceivedSslError")
//// override fun onReceivedSslError(
//// view: WebView?,
//// handler: SslErrorHandler?,
//// error: SslError?
//// ) {
////// super.onReceivedSslError(view, handler, error)
//// Blog.LOGE(log= "onReceivedSslError >> ${error}")
//// handler?.cancel()
////
//// }
////
//// val maxRetryCount = 10;
//// var webView : WebView? = null
//// var reloadPostHandle = Runnable {
//// webView?.reload()
//// BWebview.currentRetryCount += 1
//// webView?.context?.let {
//// Toast.makeText(it,"retry reload currnent : ${BWebview.currentRetryCount}", Toast.LENGTH_SHORT).show()
//// }
//// }
//// override fun onReceivedError(
//// view: WebView?,
//// request: WebResourceRequest?,
//// error: WebResourceError?
//// ) {
//// super.onReceivedError(view, request, error)
//// handler.removeCallbacks(reloadPostHandle)
//// if ((error!!.errorCode == ERROR_CONNECT || error!!.errorCode == ERROR_TIMEOUT) && BWebview.currentRetryCount < maxRetryCount) {
//// webView = view
////
//// handler.postDelayed(reloadPostHandle,5000)
//// } else {
//// view?.context?.let {
//// Toast.makeText(it,"fail load cause: ${error.description} : ${error.errorCode}", Toast.LENGTH_SHORT).show()
//// }
//// }
//// }
////
//// val handler : Handler = Handler(Looper.getMainLooper())
////// override fun onReceivedHttpError(
////// view: WebView?,
////// request: WebResourceRequest?,
////// errorResponse: WebResourceResponse?
////// ) {
////// Blog.LOGE(log= "onReceivedHttpError >> ${errorResponse?.reasonPhrase}")
//////
//////
////// }
////
////
//// override fun onPageFinished(view: WebView?, url: String?) {
//// super.onPageFinished(view, url)
//// finishedUrl = url ?: ""
////
//// view?.let {
//// url?.toUri()?.let {
//// PrefManager.putLastDomain(it.scheme.plus("::/").plus(it.host))
//// }
////
//// if(url?.contains("/list/") ?: false && url?.contains("agit") ?: false){
//// findListItem {
//// Blog.LOGE("onPageFinished", url ?: "")
//// }
//// } else if (url?.contains("booktoki") ?: false){
////// findListItem {
////// Blog.LOGE("onPageFinished", url ?: "")
////// }
//// }
//// view?.postDelayed({
//// if (url?.contains("booktoki") ?: false){
//// findListItem {
//// Blog.LOGE("onPageFinished", url ?: "")
//// }
//// }
////// view?.evaluateJavascript(
////// "function getAll() {\n" +
////// " MyJavaScriptInterface.sendValueFromHtml(document.getElementsByTagName('html')[0].innerHTML)" +
////// " };getAll()"
////// ) { result ->
////// (result as? String)?.let {
//////
////// }
////// }
////
//// }, 500L)
//// currentContentsProvider?.doOnloaded(it , { result ->
//// result?.let { mainControllInterface.onLoadedContents(it) }
//// } , { complete ->
//// if(complete) {
//// mainControllInterface?.completePageLoad(LastInfo().apply {
//// this.pageUrl = url?.toUri()?.path ?: currentContentsProvider?.getLastedDoamin() ?: ""
//// this.contentsName = currentContentsProvider?.getWebcontentsName() ?: ""
//// this.pageIndex = 0
//// })
//// }
//// })
////
//// }
//// }
//// }
//// var finishedUrl : String = ""
//// inner class BookHelper {
//// @JavascriptInterface
//// fun sendValueFromHtml(string: String) {
////
//// Jsoup.parse(string)?.let { html ->
////
//// val toon_intro = html.getElementById("toon_intro")
//// val view_padding = html.getElementsByClass("view-padding")
//// if (toon_intro != null) {
////// Blog.LOGE("finishedUrl >>> ${finishedUrl} :::: ${html.title()}")
//// val bookPageInfos = BookPageInfos()
//// bookPageInfos.bookPageUrl = Uri.parse(finishedUrl).path
//// bookPageInfos.bookTitle = if (toon_intro.getElementsByTag("h3").size > 0) toon_intro.getElementsByTag("h3").get(0).text() else ""
//// bookPageInfos.pages = realmListOf<BookPageInfo>()
////// Blog.LOGE("finishedUrl >>> ${finishedUrl} :::: bookPageInfos >>>> ${Gson().toJson(bookPageInfos)}")
//// val listParent = html.getElementById("list_type")
//// if (listParent != null) {
//// listParent.getElementsByClass("row").forEach { bookitem ->
////// Blog.LOGE("finishedUrl >>> ${finishedUrl} :::: bookItemInfo ${bookitem}")
//// try {
//// val bookPageInfo = BookPageInfo()
//// bookPageInfo.bookTitle = bookPageInfos.bookTitle
//// bookPageInfo.chapterNum = bookitem.getElementsByClass("cell_num").getT().toInt()
//// bookPageInfo.chapterID = bookitem.getElementsByClass("cell_num").getT().toInt()
//// bookPageInfo.chapterTitle = bookitem.getElementsByTag("a").getT()
//// bookPageInfo.bookPageUrl = bookPageInfos.bookPageUrl
//// val href = bookitem.getElementsByTag("a").get(0).attr("href")
//// bookPageInfo.pathUrl = Uri.parse(href).path
//// bookPageInfos.pages.add(bookPageInfo)
//// }catch (nfe : NumberFormatException) {
//// nfe.printStackTrace()
//// }
//// }.apply {
////
//// HistoryManager.openRealm.writeBlocking {
//// copyToRealm(bookPageInfos, UpdatePolicy.ALL)
////// Blog.LOGE("finishedUrl >>> ${finishedUrl} :::: bookPageInfos saved >>>> ${bookPageInfos.bookPageUrl}")
//// }
//// mainControllInterface.onBookInfos(bookPageInfos)
//// }
//// }
//// }else if (view_padding.size > 0){
////// Blog.LOGE("finishedUrl >>> ${finishedUrl} :::: ${html.title()}")
//// val contents = view_padding.get(0).children().html().replace("<p>"," ").replace("</p>","\n\n")
////// Blog.LOGE("finishedUrl >>> ${finishedUrl} :::: view_padding.get(0)\n${contents}")
//// if (contents.length > 20) {
//// Uri.parse(finishedUrl).path?.let {
//// HistoryManager.getBooPageInfoContentsSave(it, contents)
//// mainControllInterface.onLoadedContents(contents)
//// }
//// }
//// } else {
//// Blog.LOGE("finishedUrl >>> ${finishedUrl} :::: ${html.title()}")
//// Blog.LOGE("finishedUrl >>> ${finishedUrl} :::: whole body ${html}")
//// }
//// }
//// }
//// }
//}
fun Elements.getT() = if (size > 0) get(0).text() else ""

View File

@ -1,5 +0,0 @@
package bums.lunatic.launcher.tokiz.webcontents//package bums.lunatic.launcher.booktoki.webcontents
//
//typealias ActionByBool = (Boolean) -> Unit
//typealias DidFindContents = (String?) -> Unit
//typealias GotoSomeWhere = () -> Unit

View File

@ -1,22 +0,0 @@
package bums.lunatic.launcher.tokiz.webcontents//package bums.lunatic.launcher.booktoki.webcontents
//
//import com.mime.dualscreenview.data.model.BookPageInfos
//import com.mime.dualscreenview.data.model.LastInfo
//import com.mime.dualscreenview.webcontents.contentsinfo.GotoSomeWhere
//
//interface MainControllInterface {
// fun onStartLoad()
// fun completePageLoad(apply: LastInfo)
//
// fun showNextBtn(finnd : Boolean, onClickAction: GotoSomeWhere)
// fun showPrevBtn(finnd : Boolean,onClickAction: GotoSomeWhere)
//
// fun showAlert(alert :String)
//
// fun onLoadedContents(contents :String)
// fun onFindTitle(contents :String)
//
// fun onBookInfos(jsonString : String)
// fun onBookInfos(infos : BookPageInfos)
//
//}

View File

@ -1,20 +0,0 @@
package bums.lunatic.launcher.tokiz.webcontents//package bums.lunatic.launcher.booktoki.webcontents
//
//import com.mime.dualscreenview.webcontents.contentsinfo.Agit
//import com.mime.dualscreenview.webcontents.contentsinfo.Booktoki
//import com.mime.dualscreenview.webcontents.contentsinfo.NewtokiOne
//
//object WebContentsManger {
// val allContentsList : ArrayList<BaseWebContents> = arrayListOf(Booktoki)
//
// fun getBaseWebContentsBy(name : String) : BaseWebContents {
// var correctContents : BaseWebContents = Booktoki
// for (contents in allContentsList) {
// if(name.equals(contents.getWebcontentsName())) {
// correctContents = contents
// break
// }
// }
// return correctContents
// }
//}

View File

@ -1,5 +0,0 @@
package bums.lunatic.launcher.tokiz.webcontents.contentsinfo
abstract class BaseWebContents : ContentsInfoInterface {
open var lastNumber : Int = 221
}

View File

@ -1,16 +0,0 @@
//package bums.lunatic.launcher.tokiz.webcontents.contentsinfo
//
//
//object BooktokiStruct : BaseWebContents() {
//
// override var lastNumber : Int = 468
//
// override fun getWebcontentsName(): String {
// return "Booktoki"
// }
//
// override fun getLastedDoamin(): String {
// return String.format("https://booktoki%d.com", lastNumber)
// }
//
//}

View File

@ -1,20 +0,0 @@
package bums.lunatic.launcher.tokiz.webcontents.contentsinfo
typealias ActionByBool = (Boolean) -> Unit
typealias DidFindContents = (String?) -> Unit
typealias GotoSomeWhere = () -> Unit
interface ContentsInfoInterface {
fun getWebcontentsName() : String
// fun getNextButtonJs() : String
// fun getPrevButtonJs() : String
// fun getTitleJs() : String
// fun getFindContentsJs() : String
// fun checkCorrectContents(contents: String) : String
fun getLastedDoamin() : String
// fun onLoadedJs() : String
// fun acccceptResourceKeyword() : String
// fun getContentsList() : String
}

View File

@ -25,11 +25,11 @@ import bums.lunatic.launcher.model.TelegramData
import bums.lunatic.launcher.model.TelegramFrom import bums.lunatic.launcher.model.TelegramFrom
import bums.lunatic.launcher.model.TelegramMessage import bums.lunatic.launcher.model.TelegramMessage
import bums.lunatic.launcher.model.WeatherForcast import bums.lunatic.launcher.model.WeatherForcast
import bums.lunatic.launcher.tokiz.data.model.ContentsCollection import bums.lunatic.launcher.tokiz.ContentsCollection
import bums.lunatic.launcher.tokiz.data.model.ContentsPageInfo import bums.lunatic.launcher.tokiz.ContentsPageInfo
import bums.lunatic.launcher.tokiz.data.model.HistoryItem import bums.lunatic.launcher.tokiz.HistoryItem
import bums.lunatic.launcher.tokiz.data.model.LastInfo import bums.lunatic.launcher.tokiz.LastInfo
import bums.lunatic.launcher.tokiz.data.model.ReaderConfig import bums.lunatic.launcher.tokiz.ReaderConfig
import bums.lunatic.launcher.utils.Blog 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

View File

@ -0,0 +1,26 @@
<?xml version="1.0" encoding="utf-8"?>
<layer-list xmlns:android="http://schemas.android.com/apk/res/android">
<item android:id="@android:id/background">
<shape
android:shape="ring"
android:innerRadiusRatio="2.5"
android:thicknessRatio="15.0"
android:useLevel="false">
<solid android:color="#E0E0E0" />
</shape>
</item>
<item android:id="@android:id/progress">
<rotate
android:fromDegrees="270"
android:toDegrees="270">
<shape
android:shape="ring"
android:innerRadiusRatio="2.5"
android:thicknessRatio="15.0"
android:useLevel="true"> <solid android:color="#2196F3" />
</shape>
</rotate>
</item>
</layer-list>

View File

@ -1,8 +1,24 @@
<ImageView <FrameLayout
xmlns:android="http://schemas.android.com/apk/res/android" xmlns:android="http://schemas.android.com/apk/res/android"
android:id="@+id/bookmarkImageView"
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:adjustViewBounds="true" android:layout_marginBottom="8dp">
android:layout_marginBottom="8dp"
android:scaleType="fitCenter" /> <ImageView
android:id="@+id/bookmarkImageView"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:adjustViewBounds="true"
android:scaleType="fitCenter" />
<ProgressBar
android:id="@+id/imageProgressBar"
style="?android:attr/progressBarStyleInverse"
android:layout_width="100dp"
android:layout_height="100dp"
android:layout_gravity="center"
android:indeterminate="true"
android:progressDrawable="@drawable/progress_bar_double_circle"
android:max="100"
android:progress="75"/>
</FrameLayout>

View File

@ -129,21 +129,14 @@
android:layout_width="wrap_content" android:layout_width="wrap_content"
android:layout_height="20dp"/> android:layout_height="20dp"/>
<bums.lunatic.launcher.view.FloatingActionButton <bums.lunatic.launcher.view.FloatingActionButton
app:fab_label="zota" app:fab_label="짤방"
android:id="@+id/zota" android:id="@+id/zota"
app:fab_showShadow="true" app:fab_showShadow="true"
app:fab_size="mini" app:fab_size="mini"
android:onClick="floatClick" android:onClick="floatClick"
android:layout_width="wrap_content" android:layout_width="wrap_content"
android:layout_height="20dp"/> android:layout_height="20dp"/>
<bums.lunatic.launcher.view.FloatingActionButton
app:fab_label="twitter"
android:id="@+id/twitter"
app:fab_showShadow="true"
app:fab_size="mini"
android:onClick="floatClick"
android:layout_width="wrap_content"
android:layout_height="20dp"/>
<bums.lunatic.launcher.view.FloatingActionButton <bums.lunatic.launcher.view.FloatingActionButton
app:fab_label="magnet" app:fab_label="magnet"
android:id="@+id/magnet" android:id="@+id/magnet"