This commit is contained in:
lunaticbum 2025-07-16 18:21:04 +09:00
parent 405b8c8fed
commit a00b2764b0
145 changed files with 6641 additions and 3219 deletions

View File

@ -14,7 +14,6 @@ android {
defaultConfig {
applicationId = "bums.lunatic.launcher"
minSdk = 26
targetSdk = 34
versionCode = 38
versionName = "2.8.2"
multiDexEnabled = true

View File

@ -109,20 +109,14 @@
<action android:name="android.intent.action.APPLICATION_PREFERENCES" />
</intent-filter>
</activity>
<!-- <activity-->
<!-- android:name=".PhotoFilter"-->
<!-- android:label="@string/lunar_settings"-->
<!-- android:exported="true">-->
<!-- </activity>-->
<activity
android:name=".feeds.Feeds"
android:name=".tokiz.Settings"
android:label="@string/lunar_settings"
android:launchMode="singleTask"
android:launchMode="singleInstance"
android:excludeFromRecents="true"
android:exported="true">
<intent-filter>
<action android:name="android.intent.action.APPLICATION_PREFERENCES" />
</intent-filter>
</activity>
<activity
android:name=".settings.SettingsActivity"

View File

@ -0,0 +1,40 @@
browser.webRequest.onHeadersReceived.addListener(
function(details) {
let headers = details.responseHeaders || [];
// Cache-Control 헤더가 없거나 no-store, no-cache 등일 때 수정
let found = false;
for (let header of headers) {
if (header.name.toLowerCase() === "cache-control") {
header.value = "public, max-age=31536000"; // 1년 캐시
found = true;
}
}
if (!found) {
headers.push({name: "Cache-Control", value: "public, max-age=31536000"});
}
return {responseHeaders: headers};
},
{urls: ["*://*/*.gif"], types: ["image"]},
["blocking", "responseHeaders"]
);
//const originalLog = console.log;
//console.log = function(...args) {
// // 메시지 가공 또는 네이티브로 전달
// originalLog.apply(console, args);
// browser.runtime.sendNativeMessage("browser", args);
//};
browser.webRequest.onBeforeRequest.addListener(
function(details) {
return { cancel: true };
},
{ urls: ["*://*/*.gif"], types: ["image"] },
["blocking"]
);
//window.addEventListener('error', function(event) {
// if (event.message && event.message.includes('No impl for message: MozAfterPaint')) {
// // 앱으로 오류 신호 전달
// browser.runtime.sendMessage({ type: 'RELOAD_REQUEST' });
// }
//});

View File

@ -0,0 +1,86 @@
function getList() {
const contentsType = location.hostname.search('newtoki') > -1 ? 'newtoki' : location.hostname.search('booktoki') > -1 ? 'booktoki' : 'manatoki';
const contentsArray = [];
var children = document.getElementsByClassName('list-body')[0].children;
var maxCount = children.length;
for (i= 0; i < maxCount; i++) {
var chapterNum = children[i].getElementsByClassName('wr-num')[0].textContent;
var pageUrl = children[i].getElementsByClassName('wr-subject')[0].getElementsByTagName('a')[0].href;
if (pageUrl != null && pageUrl.length > 0 && pageUrl.startsWith('http')) {
pageUrl = new URL(pageUrl).pathname;
if (pageUrl && pageUrl.startsWith('http')) {
var urlObj = new URL(pageUrl);
var paths = urlObj.pathname.split('/').filter(Boolean);
if (paths.length > 0) {
var last = paths[paths.length - 1];
if (!/^\\d+$/.test(last)) {
paths.pop();
}
}
pageUrl = '/' + paths.join('/');
}
console.log(pageUrl);
} else {
console.log("pageUrl.startsWith('http') == false" + pageUrl);
}
var chapterTitle = children[i].getElementsByClassName('wr-subject')[0].getElementsByTagName('a')[0].innerText;
if(chapterTitle.split('\\n').length > 1) {
chapterTitle = chapterTitle.split('\\n')[1];
}
var bookPageUrl = location.pathname;
var bookTitle = document.getElementsByClassName('view-title')[0].getElementsByTagName('span')[0].innerText;
var data = {
'contentsType': contentsType,
'chapterID': Number(chapterNum),
'chapterNum': Number(chapterNum),
'pathUrl': pageUrl,
'bookPageUrl': bookPageUrl,
'chapterTitle': chapterTitle,
'bookTitle': bookTitle,
};
contentsArray.push(
data
);
}
if(contentsArray.length > 0) {
window.webkit.messageHandlers.ContentsRcv.postMessage(JSON.stringify({
'contentsType': contentsType,
'bookTitle': bookTitle,
'bookPageUrl': new URL(location.href).pathname,
'pages': contentsArray ,
}));
}
}
getList();
function check2() {
var children = document.getElementsByClassName('list-body')[0].children;
var maxCount = children.length;
for (i= 0; i < maxCount; i++) {
var pageUrl = children[i].getElementsByClassName('wr-subject')[0].getElementsByTagName('a')[0].href;
if (pageUrl != null && pageUrl.length > 0 && pageUrl.startsWith('http')) {
if (pageUrl) {
var paths = pageUrl.split('/')
if (paths.length > 0) {
var last = paths[paths.length - 1];
if (last && Array.from(last).every(ch => ch >= '0' && ch <= '9')) {
console.log("only nums " + last)
} else {
console.log("not only nums " + last)
paths.pop();
}
}
pageUrl = paths.join('/');
pageUrl = new URL(pageUrl).pathname;
}
console.log(pageUrl);
} else {
}
}
}
check2();

View File

@ -0,0 +1,28 @@
{
"browser_specific_settings": {
"gecko": {
"id": "messaging@booktoki468.com"
}
},
"manifest_version": 2,
"version": "1.0",
"name": "Sample Extension",
"background": {
"scripts": ["background.js"]
},
"content_scripts": [
{
"matches": ["<all_urls>"],
"js": ["messaging.js"]
}
],
"permissions": [
"nativeMessaging",
"nativeMessagingFromContent",
"geckoViewAddons",
"webRequest",
"webRequestBlocking",
"*://*/*.gif"
]
}

View File

@ -0,0 +1,177 @@
const port = browser.runtime.connectNative("browser");
port.onMessage.addListener(response => {
var type= response["type"];
switch (type) {
case "getList": {
try {
// var listBody = null
// try {listBody = document.querySelector(".list-body");}catch (e) {}
// var title = null
// var contents = null
// try {title = toonTitle(document.querySelector(".page-desc")); }catch (e) {}
// try {contents = toonContents(document.querySelector("#novel_content"))}catch (e) {}
// console.log("listBody", listBody);
// console.log("title", title);
if(listBody) {
// getList(listBody.children)
} else if(title && contents) {
// if (toonTitle !== undefined && toonContents !== undefined && toonTitle !== "" && toonContents !=="") {
// sendMessage(
// {
// type: "BookContents",
// book : {
// chapterTitle : title,
// bookContents : contents
// }
// }
// );
// }
} else {
loadComplete()
}
} catch (e) {
loadComplete()
console.error(e);
}
}break;
case "scrollDown":{
var max = response["max"]
var current = response["current"]
var isUpDown = response["isUpDown"]
if (max > 0 && current > 0) { scrollByPercent(Number(current),Number(max)); }
else scrollByPercentUpDown(Number(isUpDown),100);
}
break;
case "onLoaded":{
}
break;
default:
port.postMessage(`Received: ${JSON.stringify(response)}`);
break
}
});
if(document.querySelector(".list-body")) {
var listBody = null
try {listBody = document.querySelector(".list-body");}catch (e) {}
getList(listBody.children)
} else if(document.querySelector("#novel_content")){
var title = null
var contents = null
try {title = toonTitle(document.querySelector(".page-desc")); }catch (e) {}
try {contents = toonContents(document.querySelector("#novel_content"))}catch (e) {}
if (toonTitle !== undefined && toonContents !== undefined && toonTitle !== "" && toonContents !=="") {
sendMessage(
{
type: "BookContents",
book : {
chapterTitle : title,
bookContents : contents
}
}
);
}
} else if(document.querySelector("#html_encoder_div")) {
sendMessage(
{
type: "WebtoonContents",
}
);
} else {
sendMessage({type:"MSG",msg:"connected has Nothings"});
loadComplete()
}
function getList(children) {
// port.postMessage("Start of getList!" + children);
const contentsArray = [];
var maxCount = children.length;
for (i= 0; i < maxCount; i++) {
var chapterNum = children[i].getElementsByClassName('wr-num')[0].textContent;
var pageUrl = children[i].getElementsByClassName('wr-subject')[0].getElementsByTagName('a')[0].href;
if (pageUrl != null && pageUrl.length > 0 && pageUrl.startsWith("http")) {
pageUrl = new URL(pageUrl).pathname;
}
var chapterTitle = children[i].getElementsByClassName('wr-subject')[0].getElementsByTagName('a')[0].innerText;
if(chapterTitle.split('\n').length > 1) {
chapterTitle = chapterTitle.split('\n')[1];
}
var bookPageUrl = location.pathname;
var bookTitle = document.getElementsByClassName('view-title')[0].getElementsByTagName('span')[0].innerText;
var data = {
'chapterID': Number(chapterNum),
'chapterNum': Number(chapterNum),
'pathUrl': pageUrl,
'bookPageUrl': bookPageUrl,
'chapterTitle': chapterTitle,
'bookTitle': bookTitle,
};
contentsArray.push(
data
);
}
if(contentsArray.length > 0) {
sendMessage(
{
type: "getListResult",
bookInfos: {
bookTitle: bookTitle,
bookPageUrl: new URL(location.href).pathname,
pages: contentsArray ,
}
}
);
}
}
function toonTitle(toon_title) {
return toon_title != null ? toon_title.innerText : null
}
function toonContents(novel_content) {
return novel_content != null ? novel_content.innerText : null
}
function scrollByPercent(current , max) {
const pageHeight = Math.max(
document.body.scrollHeight,
document.documentElement.scrollHeight,
document.body.offsetHeight,
document.documentElement.offsetHeight,
document.body.clientHeight,
document.documentElement.clientHeight
);
const currentScroll = window.pageYOffset || document.documentElement.scrollTop || document.body.scrollTop || 0;
const moveAmount = pageHeight / max;
window.scrollTo({ top: moveAmount * current, behavior: "smooth" });
}
function scrollByPercentUpDown(isToDown , max) {
const pageHeight = Math.max(
document.body.scrollHeight,
document.documentElement.scrollHeight,
document.body.offsetHeight,
document.documentElement.offsetHeight,
document.body.clientHeight,
document.documentElement.clientHeight
);
const currentScroll = window.pageYOffset || document.documentElement.scrollTop || document.body.scrollTop || 0;
const moveAmount = Math.max(pageHeight / max,100);
window.scrollTo({ top: currentScroll + (moveAmount * isToDown) , behavior: "smooth" });
}
function loadComplete() {
// try {port.postMessage(JSON.stringify({type: "NotRegistered"}));}catch (e) {}
}
function sendMessage(msg) {
port.postMessage(JSON.stringify(msg));
}
function dssd() {
}

View File

@ -20,17 +20,12 @@ package bums.lunatic.launcher
//import rasel.lunar.launcher.home.LauncherHome.Companion.rssSet
import android.Manifest
import android.annotation.SuppressLint
import android.app.NotificationManager
import android.appwidget.AppWidgetManager
import android.content.BroadcastReceiver
import android.content.ComponentName
import android.content.Context
import android.content.Intent
import android.content.SharedPreferences
import android.content.pm.PackageManager
import android.content.res.Configuration
import android.graphics.Color
import android.net.Uri
@ -40,8 +35,6 @@ import android.os.Environment.isExternalStorageManager
import android.os.Handler
import android.os.Looper
import android.provider.Settings
import android.support.v4.media.MediaBrowserCompat
import android.telephony.TelephonyManager
import android.view.KeyEvent
import android.view.KeyEvent.ACTION_UP
import android.view.KeyEvent.KEYCODE_BUTTON_A
@ -51,8 +44,6 @@ import android.view.KeyEvent.KEYCODE_BUTTON_START
import android.view.KeyEvent.KEYCODE_BUTTON_X
import android.view.KeyEvent.KEYCODE_BUTTON_Y
import android.view.KeyEvent.KEYCODE_DPAD_DOWN
import android.view.KeyEvent.KEYCODE_DPAD_LEFT
import android.view.KeyEvent.KEYCODE_DPAD_RIGHT
import android.view.KeyEvent.KEYCODE_DPAD_UP
import android.view.MotionEvent
import android.view.View
@ -67,6 +58,7 @@ import androidx.core.splashscreen.SplashScreen.Companion.installSplashScreen
import androidx.core.view.ViewCompat
import androidx.core.view.WindowCompat
import androidx.core.view.WindowInsetsCompat
import androidx.core.view.isVisible
import androidx.core.view.updatePadding
import androidx.work.ExistingPeriodicWorkPolicy
import androidx.work.OneTimeWorkRequest
@ -74,27 +66,26 @@ import androidx.work.PeriodicWorkRequestBuilder
import androidx.work.WorkManager
import bums.lunatic.launcher.LauncherActivity.Companion.lActivity
import bums.lunatic.launcher.apps.AppDrawer
import bums.lunatic.launcher.tokiz.Novels
import bums.lunatic.launcher.common.CommonActivity
import bums.lunatic.launcher.databinding.LauncherActivityBinding
import bums.lunatic.launcher.feeds.WidgetHost
import bums.lunatic.launcher.helpers.BluetoothManager
import bums.lunatic.launcher.helpers.Constants.Companion.KEY_APPLICATION_THEME
import bums.lunatic.launcher.helpers.Constants.Companion.KEY_FIRST_LAUNCH
import bums.lunatic.launcher.helpers.Constants.Companion.KEY_STATUS_BAR
import bums.lunatic.launcher.helpers.Constants.Companion.PREFS_FIRST_LAUNCH
import bums.lunatic.launcher.helpers.Constants.Companion.PREFS_SETTINGS
import bums.lunatic.launcher.helpers.Constants.Companion.widgetHostId
import bums.lunatic.launcher.helpers.HeadsetActionButtonReceiver
import bums.lunatic.launcher.helpers.PrefLong
import bums.lunatic.launcher.home.LauncherHome
import bums.lunatic.launcher.home.RssViewBuilder
import bums.lunatic.launcher.home.adapters.RssItemAdapter.Companion.rssList
import bums.lunatic.launcher.model.RssData
import bums.lunatic.launcher.model.RssDataType
import bums.lunatic.launcher.receiver.NLService
import bums.lunatic.launcher.utils.Blog
import bums.lunatic.launcher.utils.FeedParseManager
import bums.lunatic.launcher.utils.getJ
import bums.lunatic.launcher.view.TableRadioGroup
import bums.lunatic.launcher.workers.AppInfoGetter
import bums.lunatic.launcher.workers.ArcaGetter
import bums.lunatic.launcher.workers.CalendarGetter
@ -120,18 +111,19 @@ import bums.lunatic.launcher.workers.WorkersDb
import bums.lunatic.launcher.workers.YoutubeGetter
import bums.lunatic.launcher.workers.YoutubeGetter.Companion.YT_WORK_TAG
import com.google.android.material.color.DynamicColors
import com.google.android.material.dialog.MaterialAlertDialogBuilder
import io.realm.kotlin.ext.query
import io.realm.kotlin.query.Sort
import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.launch
import kr.lunaticbum.utils.ui.DisplayUtil
import java.text.SimpleDateFormat
import org.json.JSONObject
import org.mozilla.geckoview.ExperimentDelegate
import org.mozilla.geckoview.GeckoResult
import org.mozilla.geckoview.GeckoRuntime
import org.mozilla.geckoview.GeckoRuntimeSettings
import java.util.Base64
import java.util.Calendar
import java.util.Date
import java.util.Locale
import java.util.concurrent.Executors
import java.util.concurrent.TimeUnit
@ -143,6 +135,12 @@ internal class LauncherActivity : CommonActivity() {
// lateinit var viewPager: ViewPager2
companion object {
private var sRuntime: GeckoRuntime? = null
fun getRuntime() : GeckoRuntime? {
lActivity?.initGeckoRuntime()
return sRuntime
}
private var mWorkManager: WorkManager? = null
var isOpendFold = false
val qDayPeriod = 60L * 8L
@ -179,11 +177,11 @@ internal class LauncherActivity : CommonActivity() {
}
fun runWeatherGetter() {
Executors.newSingleThreadScheduledExecutor().schedule({
mWorkManager?.enqueue(OneTimeWorkRequest.from(OpenWeatherGetter::class.java))
}, 200L, TimeUnit.MILLISECONDS)
}
// fun runWeatherGetter() {
// Executors.newSingleThreadScheduledExecutor().schedule({
// mWorkManager?.enqueue(OneTimeWorkRequest.from(OpenWeatherGetter::class.java))
// }, 200L, TimeUnit.MILLISECONDS)
// }
fun getCal() {
Executors.newSingleThreadScheduledExecutor().schedule({
@ -276,6 +274,7 @@ internal class LauncherActivity : CommonActivity() {
}
@SuppressLint("MissingSuperCall")
override fun onConfigurationChanged(newConfig: Configuration) {
super.onConfigurationChanged(newConfig)
@ -284,13 +283,30 @@ internal class LauncherActivity : CommonActivity() {
Blog.LOGE("onConfigurationChanged newConfig?.screenWidthDp >> ${newConfig?.screenWidthDp}")
Blog.LOGE("onConfigurationChanged newConfig?.screenHeightDp >> ${newConfig?.screenHeightDp}")
isOpendFold = (newConfig.screenWidthDp * 1.1f) > newConfig.screenHeightDp
}
// override fun onKeyClick(keyCode: Int): Boolean {
// when (keyCode) {
// KeyEvent.KEYCODE_VOLUME_DOWN -> {
// actionNextEvent()
// }
//
// KeyEvent.KEYCODE_VOLUME_UP -> {
// actionPrevEvent()
// }
//
// KeyEvent.KEYCODE_VOLUME_MUTE -> {
// actionNextEvent()
// }
//
// }
// return super.onKeyClick(keyCode)
// }
var actionButtonPressX = 0f
var actionButtonPressY = 0f
var onExit = false
var lastAction = MotionEvent.ACTION_HOVER_EXIT
override fun dispatchKeyEvent(ev: KeyEvent): Boolean {
Blog.LOGE("dispatch ev?.device?.name >>> ${ev?.device?.name}")
if (ev?.device?.name?.contains("SM-031N Mouse") == true) {
@ -366,6 +382,25 @@ internal class LauncherActivity : CommonActivity() {
}
return true
}
else {
if(MotionEvent.ACTION_UP.equals(ev?.action ?: MotionEvent.ACTION_CANCEL) == true) {
when (ev.keyCode) {
KeyEvent.KEYCODE_VOLUME_DOWN -> {
novels?.actionNextEvent()
return true
}
KeyEvent.KEYCODE_VOLUME_UP -> {
novels?.actionPrevEvent()
return true
}
else -> return false
}
} else {
return false
}
}
return super.dispatchKeyEvent(ev)
}
@ -541,31 +576,68 @@ internal class LauncherActivity : CommonActivity() {
// }
super.onNewIntent(intent)
}
lateinit var home : LauncherHome
var home : LauncherHome? = null
var novels : Novels? = null
@SuppressLint("NewApi", "MissingPermission")
override fun onCreate(savedInstanceState: Bundle?) {
installSplashScreen()
lActivity = this
mWorkManager = WorkManager.getInstance(this)
DynamicColors.applyToActivityIfAvailable(this)
lActivity = this
settingsPrefs = getSharedPreferences(PREFS_SETTINGS, 0)
AppCompatDelegate.setDefaultNightMode(settingsPrefs.getInt(KEY_APPLICATION_THEME, MODE_NIGHT_FOLLOW_SYSTEM))
// AppCompatDelegate.setDefaultNightMode(settingsPrefs.getInt(KEY_APPLICATION_THEME, MODE_NIGHT_FOLLOW_SYSTEM))
super.onCreate(savedInstanceState)
WindowCompat.setDecorFitsSystemWindows(window, false)
binding = LauncherActivityBinding.inflate(layoutInflater)
setContentView(binding.root)
appWidgetManager = AppWidgetManager.getInstance(applicationContext)
appWidgetHost = WidgetHost(applicationContext, widgetHostId)
appWidgetHost?.startListening()
HeadsetActionButtonReceiver.register(this)
// MediaBrowserCompat.ConnectionCallback
/* if this is the first launch,
then remember the event and show the welcome dialog */
home = binding.home.getFragment<LauncherHome>()
binding.tabs.setOnCheckedChangeListener { g, id ->
when(id) {
R.id.feeds -> {
if(binding.feeds.isChecked) {
if (home == null) {
home = binding.home.getFragment<LauncherHome>()
}
binding.home.visibility = View.VISIBLE
binding.booktoki.visibility = View.GONE
} else {
binding.home.visibility = View.GONE
if (novels == null) {
novels = binding.booktoki.getFragment<Novels>()
} else {
novels?.onResume()
}
binding.booktoki.visibility = View.VISIBLE
}
}
R.id.book ->{
if(binding.book.isChecked) {
binding.home.visibility = View.GONE
if (novels == null) {
novels = binding.booktoki.getFragment<Novels>()
} else {
novels?.onResume()
}
binding.booktoki.visibility = View.VISIBLE
} else {
if (home == null) {
home = binding.home.getFragment<LauncherHome>()
}
binding.home.visibility = View.VISIBLE
binding.booktoki.visibility = View.GONE
}
}
else -> {}
}
}
/* handle navigation back events */
handleBackPress()
@ -592,13 +664,38 @@ internal class LauncherActivity : CommonActivity() {
}
}
updateLocationService()
binding.book.isChecked = true
}
private fun initGeckoRuntime() {
if (sRuntime == null) {
try {
sRuntime = GeckoRuntime.create(this, GeckoRuntimeSettings.Builder().extensionsProcessEnabled(true)
.extensionsWebAPIEnabled(true).experimentDelegate(experimentDelegate)
.remoteDebuggingEnabled(true).build())
} catch (e : Exception) {
e.printStackTrace()
}
}
}
override fun onTouchEvent(event: MotionEvent?): Boolean {
Blog.LOGE("event >>> ${event}")
return super.onTouchEvent(event)
}
override fun onDestroy() {
super.onDestroy()
appWidgetHost?.stopListening()
try {
sRuntime?.shutdown()
sRuntime = null
} catch (e: Exception) {e.printStackTrace()
}
super.onDestroy()
}
var blutoothManager : BluetoothManager? = null
override fun onStart() {
@ -608,132 +705,19 @@ internal class LauncherActivity : CommonActivity() {
blutoothManager?.initBluetoothAdapter()
blutoothManager?.blueToothState()
blutoothManager?.getPairedDevices()
Blog.LOGE("LauncherActivity onStart()")
statusBarView()
setBgColor()
welcomeDialog()
}
@RequiresApi(Build.VERSION_CODES.O_MR1)
override fun onResume() {
super.onResume()
refreshFeeds()
blutoothManager?.getPairedDevices()
Blog.LOGE("LauncherActivity onResume")
}
private fun welcomeDialog() {
var needAsk = if (
this.checkSelfPermission(Manifest.permission.BLUETOOTH_CONNECT) != PackageManager.PERMISSION_GRANTED ||
this.checkSelfPermission(Manifest.permission.READ_CALENDAR) != PackageManager.PERMISSION_GRANTED ||
this.checkSelfPermission(Manifest.permission.WRITE_CALENDAR) != PackageManager.PERMISSION_GRANTED ||
this.checkSelfPermission(Manifest.permission.READ_CONTACTS) != PackageManager.PERMISSION_GRANTED ||
this.checkSelfPermission(Manifest.permission.READ_CALL_LOG) != PackageManager.PERMISSION_GRANTED ||
this.checkSelfPermission(Manifest.permission.READ_PHONE_STATE) != PackageManager.PERMISSION_GRANTED ||
this.checkSelfPermission(Manifest.permission.RECEIVE_MMS) != PackageManager.PERMISSION_GRANTED ||
this.checkSelfPermission(Manifest.permission.RECEIVE_SMS) != PackageManager.PERMISSION_GRANTED ||
this.checkSelfPermission(Manifest.permission.CALL_PHONE) != PackageManager.PERMISSION_GRANTED ||
this.checkSelfPermission(Manifest.permission.READ_SMS) != PackageManager.PERMISSION_GRANTED ||
this.checkSelfPermission(Manifest.permission.ACCESS_COARSE_LOCATION) != PackageManager.PERMISSION_GRANTED ||
this.checkSelfPermission(Manifest.permission.ACCESS_BACKGROUND_LOCATION) != PackageManager.PERMISSION_GRANTED ||
this.checkSelfPermission(Manifest.permission.ACCESS_FINE_LOCATION) != PackageManager.PERMISSION_GRANTED
) {
true
} else false
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.R) {
if (!isExternalStorageManager()) {
needAsk = true
}
}
val cn = ComponentName(this, NLService::class.java)
val n = applicationContext.getSystemService(NOTIFICATION_SERVICE) as NotificationManager
if (n.isNotificationListenerAccessGranted(cn)) {
} else {
needAsk = true
}
getSharedPreferences(PREFS_FIRST_LAUNCH, 0).let {
if (it.getBoolean(KEY_FIRST_LAUNCH, true) || needAsk) {
it.edit().putBoolean(KEY_FIRST_LAUNCH, false).apply()
MaterialAlertDialogBuilder(this)
.setTitle(R.string.welcome)
.setMessage(R.string.welcome_description)
.setPositiveButton(R.string.got_it) { dialog, _ ->
dialog.dismiss()
askPermissions()
}.show()
}
}
if (!needAsk) {
refreshDeviceData()
refreshFeeds()
}
}
/* ask for the permissions */
private fun askPermissions() {
/* phone permission */
val cn = ComponentName(this, NLService::class.java)
val n = applicationContext.getSystemService(NOTIFICATION_SERVICE) as NotificationManager
if (
this.checkSelfPermission(Manifest.permission.BLUETOOTH_CONNECT) != PackageManager.PERMISSION_GRANTED ||
this.checkSelfPermission(Manifest.permission.READ_CALENDAR) != PackageManager.PERMISSION_GRANTED ||
this.checkSelfPermission(Manifest.permission.WRITE_CALENDAR) != PackageManager.PERMISSION_GRANTED ||
this.checkSelfPermission(Manifest.permission.READ_CONTACTS) != PackageManager.PERMISSION_GRANTED ||
this.checkSelfPermission(Manifest.permission.READ_CALL_LOG) != PackageManager.PERMISSION_GRANTED ||
this.checkSelfPermission(Manifest.permission.READ_PHONE_STATE) != PackageManager.PERMISSION_GRANTED ||
this.checkSelfPermission(Manifest.permission.RECEIVE_MMS) != PackageManager.PERMISSION_GRANTED ||
this.checkSelfPermission(Manifest.permission.RECEIVE_SMS) != PackageManager.PERMISSION_GRANTED ||
this.checkSelfPermission(Manifest.permission.CALL_PHONE) != PackageManager.PERMISSION_GRANTED ||
this.checkSelfPermission(Manifest.permission.READ_SMS) != PackageManager.PERMISSION_GRANTED ||
this.checkSelfPermission(Manifest.permission.ACCESS_COARSE_LOCATION) != PackageManager.PERMISSION_GRANTED ||
this.checkSelfPermission(Manifest.permission.ACCESS_BACKGROUND_LOCATION) != PackageManager.PERMISSION_GRANTED ||
this.checkSelfPermission(Manifest.permission.ACCESS_FINE_LOCATION) != PackageManager.PERMISSION_GRANTED
) {
this.requestPermissions(arrayOf(
Manifest.permission.BLUETOOTH_CONNECT,
Manifest.permission.READ_CALENDAR,
Manifest.permission.WRITE_CALENDAR,
Manifest.permission.READ_CONTACTS,
Manifest.permission.READ_CALL_LOG,
Manifest.permission.CALL_PHONE,
Manifest.permission.READ_SMS,
Manifest.permission.READ_PHONE_STATE,
Manifest.permission.RECEIVE_MMS,
Manifest.permission.RECEIVE_SMS,
Manifest.permission.ACCESS_COARSE_LOCATION,
Manifest.permission.ACCESS_BACKGROUND_LOCATION,
Manifest.permission.ACCESS_FINE_LOCATION,
Manifest.permission.CALL_PHONE,
Manifest.permission.READ_SMS), 1)
}
/* modify system settings */
if (!Settings.System.canWrite(this)) {
this.startActivity(
Intent(Settings.ACTION_MANAGE_WRITE_SETTINGS)
.setData(Uri.parse("package:" + this.packageName))
.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK)
)
} else if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.R) {
if (!isExternalStorageManager()) {
try {
startActivityForResult(Intent(Settings.ACTION_MANAGE_APP_ALL_FILES_ACCESS_PERMISSION).apply {
data = Uri.parse(String.format("package:%s", applicationContext.packageName))
}, 300)
} catch (e: Exception) {
startActivityForResult(Intent().apply {
action = Settings.ACTION_MANAGE_ALL_FILES_ACCESS_PERMISSION
}, 300)
}
}else if (!n.isNotificationListenerAccessGranted(cn)) {
val intent = Intent(Settings.ACTION_NOTIFICATION_LISTENER_SETTINGS)
startActivity(intent)
}
}
}
val appDrawer by lazy { AppDrawer() }
@ -776,14 +760,10 @@ internal class LauncherActivity : CommonActivity() {
private fun handleBackPress() {
onBackPressedDispatcher.addCallback(this, object : OnBackPressedCallback(true) {
override fun handleOnBackPressed() {
// if (binding.feeds.visibility == View.VISIBLE) {
// switchFeeds()
// } else
if (binding.appDrawer.visibility == View.VISIBLE) {
switchAppDrawer()
} else if (binding.home.visibility == View.VISIBLE) {
// switchAppDrawer()
if (binding.booktoki.isVisible) {
finish()
} else {
finish()
}
}
})
@ -804,313 +784,33 @@ internal class LauncherActivity : CommonActivity() {
}
val experimentDelegate = object : ExperimentDelegate {
override fun onGetExperimentFeature(feature: String): GeckoResult<JSONObject?> {
Blog.LOGE("onGetExperimentFeature $feature")
return super.onGetExperimentFeature(feature)
}
class EndCallReceiver : BroadcastReceiver() {
override fun onReceive(context: Context, intent: Intent) {
Blog.LOGE("EndCallReceiver >>> ${intent}")
val phoneState = intent.getStringExtra(TelephonyManager.EXTRA_STATE) ?: return
if (phoneState == TelephonyManager.EXTRA_STATE_IDLE) {
refreshDeviceData()
}
override fun onRecordExposureEvent(feature: String): GeckoResult<Void?> {
Blog.LOGE("onRecordExposureEvent $feature")
return super.onRecordExposureEvent(feature)
}
override fun onRecordExperimentExposureEvent(
feature: String,
slug: String
): GeckoResult<Void?> {
Blog.LOGE("onRecordExperimentExposureEvent $feature , $slug")
return super.onRecordExperimentExposureEvent(feature, slug)
}
override fun onRecordMalformedConfigurationEvent(
feature: String,
part: String
): GeckoResult<Void?> {
Blog.LOGE("onRecordMalformedConfigurationEvent $feature , $part")
return super.onRecordMalformedConfigurationEvent(feature, part)
}
}
class SMSReceiver : BroadcastReceiver() {
override fun onReceive(context: Context, intent: Intent) {
Blog.LOGE("SMSReceiver >>> ${intent}")
refreshDeviceData()
}
}
fun openDrive(gmmIntentUri : Uri, pakage : String? = null) {
val mapIntent = Intent(Intent.ACTION_MEDIA_SHARED, gmmIntentUri)
pakage?.let {
mapIntent.setPackage(pakage)
}
startActivity(mapIntent)
}
var callBack : CommadCallabck? = null
var isF = false
// fun doWebParseStart(url : String, callBack :CommadCallabck?) {
// isF = false
// this.callBack = callBack
// binding.searcher01.post { binding.searcher01.visibility = View.VISIBLE }
// BLog.LOGE("binding.otherCheck before ThreadRun")
// binding.searcher01.webViewClient = object : WebViewClient() {
// override fun shouldOverrideUrlLoading(view: WebView?, url: String?): Boolean {
// BLog.LOGE("binding.otherCheck before ${url}")
// if ((url?.contains("guru") == true || url?.contains("missav") == true) && !isF) {
// BLog.LOGE("binding.otherCheck before reload")
// view?.loadUrl(url!!)
// isF = true
// return false
// }
// return false
// }
//
// override fun onPageStarted(view: WebView?, url: String?, favicon: Bitmap?) {
// BLog.LOGE("binding.otherCheck searcher01 in onPageStarted ${url}")
// super.onPageStarted(view, url, favicon)
// }
// override fun onReceivedError(
// view: WebView?,
// request: WebResourceRequest?,
// error: WebResourceError?
// ) {
//// super.onReceivedError(view, request, error)
// }
// override fun onReceivedSslError(
// view: WebView?,
// handler: SslErrorHandler?,
// error: SslError?
// ) {
// handler?.proceed()
// }
//
// override fun onPageFinished(view: WebView?, url: String?) {
// super.onPageFinished(view, url)
// lastedFinishedPageUrl = url ?: ""
// BLog.LOGE("binding.otherCheck searcher01 in onPageFinished ${url}")
// //lastedFinishedPageUrl?.length ?: 0 > 10 &&
//// if(url?.startsWith("https://") == true) {
//// if (url?.contains("guru", true) == true) {
//// isF = true
//// view?.loadUrl(url)
//// }
// if (url?.contains("youtube", false) == true) {
// view?.evaluateJavascript(
// "function getAll() {\n" +
// " MyJavaScriptInterface.sendValueFromHtml(document.getElementsByTagName('html')[0].innerHTML)" +
// " };getAll()"
// ) { result ->
// (result as? String)?.let {}
// }
// } else if(url?.contains("translate.google.com") == true) {
// binding.searcher01.postDelayed({
// binding.searcher01.evaluateJavascript(
// "function getAll() {\n" +
// " MyJavaScriptInterface.sendValueFromHtml(document.getElementsByTagName('html')[0].innerHTML)" +
// " };getAll()"
// ) { result ->
// (result as? String)?.let {}
// }
// }, 6000L)
// } else if (url?.contains("guru", true) == true) {
// if (!isF) {
// binding.searcher01.postDelayed({
// view?.loadUrl(url)
// isF = true
// },5000)
// } else {
// binding.searcher01.postDelayed({
// binding.searcher01.evaluateJavascript(
// "function getAll() {\n" +
// " MyJavaScriptInterface.sendValueFromHtml(document.getElementsByTagName('html')[0].innerHTML)" +
// " };getAll()"
// ) { result ->
// (result as? String)?.let {}
// }
// }, 10000L)
// }
// }else {
// //
// view?.evaluateJavascript(
// "function getAll() {\n" +
// " MyJavaScriptInterface.sendValueFromHtml(document.getElementsByTagName('html')[0].innerHTML)" +
// " };getAll()"
// ) { result ->
// (result as? String)?.let {}
// }
// }
// if (isF) this@LauncherActivity.callBack?.collectComplete()
// }
// }
// WebView.setWebContentsDebuggingEnabled(false)
// binding.searcher01.apply {
//// Jsoup.connect("https://missav.com/dm11/ko").userAgent()
//// .timeout(30000).get()?.apply {
//// BLog.LOGE("Jsoup.connect(missAv).get() ${this}")
//// }
// try {
// this.removeJavascriptInterface("MyJavaScriptInterface")
// }catch (e :Exception) {}
// this.addJavascriptInterface(MyJavaScriptInterface(this),"MyJavaScriptInterface")
// setBackgroundColor(Color.WHITE) // 백그라운드 색상 설정
// setLayerType(View.LAYER_TYPE_SOFTWARE, null) // 랜더링 이슈 해결
// try {
// settings.apply {
// userAgentString = "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/127.0.0.0 Safari/537.36"
// javaScriptEnabled = true // 자바스크립트 사용 가능하도록 설정
// loadWithOverviewMode = true // 전체 웹페이지를 화면에 맞게 로드
// useWideViewPort = true // 화면에 맞게 페이지 확대/축소
// domStorageEnabled = true // DOM 저장소 사용 가능하도록 설정
// setSupportMultipleWindows(true)
// javaScriptCanOpenWindowsAutomatically = true // 팝업창 차단 해제
// cacheMode = WebSettings.LOAD_CACHE_ELSE_NETWORK
// textZoom = 100 // system 에 의한 글꼴 변형 방지
// defaultTextEncodingName = "UTF-8" // 인코딩 설정
// allowContentAccess = true // 웹뷰를 통해 content url에 접근할지 여부
// layoutAlgorithm = WebSettings.LayoutAlgorithm.TEXT_AUTOSIZING // 웹페이지의 레이아웃을 화면에 맞게 자동으로 조정
// }
// } catch (ignore: NoSuchMethodError) {
//
// }.apply {
// loadUrl(url) // 웹페이지 연결
// }
// }
// }
var maxDate : Long = Long.MIN_VALUE
var minDate : Long = Long.MAX_VALUE
val triple = 1000L * 60L * 60L * 24L * 2L
val simpldateFormat = SimpleDateFormat("d MMM, yy", Locale.US)
// fun jGuruToday(doc: Document) {
// var temp = arrayListOf<RssData>()
// doc.getElementsByTag("li").forEach {
// if (it.getElementsByTag("img").size > 0) {
// var title = it.getElementsByTag("a").get(0).attr("title")
// var model = title.replace("[", "").split("]")[0]
// var pageLink = it.getElementsByTag("a").get(0).attr("href")
// var imgg = it.getElementsByTag("img").get(0).attr("src")
// var actor = if (it.getElementsByClass("wpptax").size > 0 )it.getElementsByClass("wpptax").get(0).text() else ""
// if (pageLink.length > 0 && imgg.length > 0 && title.length > 0 && model.length > 0) {
// temp.add(
// JGuru(
// model = model,
// title = title,
// pageLink = pageLink,
// image = imgg,
// tags = actor,
// date = beforeDay(Date(),3) + 360000
// ).getRssData()
// )
// }
// }
// }.apply {
// this@LauncherActivity.callBack?.collectComplete()
// WorkersDb.insertBulkInteface(temp)
// Toast.makeText(this@LauncherActivity,
// "Stored rank data", Toast.LENGTH_LONG).show()
// binding.searcher01?.post { binding.searcher01.loadUrl(jGuruMain) }
// }
// }
// fun jGuruMain(doc: Document) {
// var temp = arrayListOf<RssData>()
// val prevUrl = doc.getElementsByClass("prev").get(0).getElementsByAttribute("href").get(0).attr("href")
// doc.getElementsByClass("column").forEach {
// var title = it.getElementsByAttribute("title").get(0).text()
// var model = title.replace("[","").split("]")[0]
// var pageLink = it.getElementsByClass("imgg").get(0).getElementsByAttribute("href").get(0).attr("href")
// var imgg = it.getElementsByClass("imgg").get(0).getElementsByAttribute("src").get(0).attr("src")
// var tags = it.getElementsByClass("tags").get(0).text()
// var date = it.getElementsByClass("date").get(0).text()
// var regDate = simpldateFormat.parse(date).time
//
// minDate = Math.min(minDate,regDate)
// maxDate = Math.max(maxDate,regDate)
// temp.add(JGuru(model = model, title = title, pageLink = pageLink, image = imgg, tags = tags, date = make0H(simpldateFormat.parse(date))).getRssData())
// }.apply {
// var itemC = 0
// WorkersDb.insertBulkInteface(temp)
// callBack?.onConsoleLog("Stored data :: ${simpldateFormat.format(Date(minDate))} ~ ${simpldateFormat.format(Date(maxDate))} set in ${itemC}")
// binding.searcher01?.post { binding.searcher01.loadData("<html></html>",null,null) }
// this@LauncherActivity.callBack?.collectComplete()
// }
// }
//
// fun jGuruTag(doc: Document) {
// doc.getElementsByTag("ul").forEach {
// it.children().forEach {
// if (it.tag().name.contains("li")) {
// listTags.add(
// jGuruTag(
// tagTitle = it.getElementsByTag("a").get(0).text(),
// link = it.getElementsByTag("a").get(0).attr("href")
// )
// )
//
// }
// }
// }.apply {
// binding.searcher01?.post { binding.searcher01.loadData("<html></html>",null,null) }
// this@LauncherActivity.callBack?.collectComplete()
// }
// }
// fun switchFeeds() {
// startActivity(Intent(this,Feeds::class.java))
// }
// inner class MyJavaScriptInterface(val webView: WebView) {
// @JavascriptInterface
// fun sendValueFromHtml(result: String) {
// if (lastedFinishedPageUrl.contains(jGuruMain)) {
// var htmlString = result.replace("\\u003","<")
// val doc: Document = Jsoup.parse(htmlString)
// if (lastedFinishedPageUrl?.contains("page") == true || lastedFinishedPageUrl?.equals(jGuruMain) == true) {
// jGuruMain(doc)
// } else if (lastedFinishedPageUrl?.contains("/most-watched-rank") == true) {
// jGuruToday(doc)
// } else if (lastedFinishedPageUrl?.contains("/tags/") == true) {
// jGuruTag(doc)
// }
// } else if (lastedFinishedPageUrl?.contains("missav")==true) {
// val doc: Document = Jsoup.parse(result)
// var temp = arrayListOf<RssData>()
// doc.getElementsByClass("thumbnail group").forEach { miss_li ->
// if (miss_li.getElementsByTag("img").size > 0 && miss_li.getElementsByTag("img").get(0).attr("data-src").length > 10 &&
// miss_li.getElementsByTag("img").get(0).attr("data-src").startsWith("https") &&
// miss_li.getElementsByTag("img").get(0).attr("data-src").endsWith("jpg")) {
// var link = if(miss_li.getElementsByTag("a").size > 0) miss_li.getElementsByTag("a").get(0).attr("href") else ""
// var title = miss_li.getElementsByClass("text-secondary group-hover:text-primary").getT()
// var thumb = miss_li.getElementsByTag("img").get(0).attr("data-src")
// var desc = miss_li.getElementsByTag("img").get(0).text()
// MissD().apply {
// this.link = link
// this.title = title
// this.thumb = thumb
// this.desc = desc
// temp.add(this.getRssData())
// }
// }
// }.apply {
// WorkersDb.insertBulkData(temp)
// }
// } else if(lastedFinishedPageUrl?.contains("https://translate.google.com") == true){
// callBackHandler.removeCallbacks(postNext)
// val doc: Document = Jsoup.parse(result)
// doc.getElementsByTag("span").forEach { span ->
//// BLog.LOGE("on getHangule ${span.text()}")
// if(span.hasAttr("jsaction") &&
// span.attr("jsaction").contains("mouseout") &&
// span.attr("jsaction").contains("contextmenu") &&
// span.attr("jsaction").contains("click") &&
// span.attr("jsaction").contains("mouseover")
// ) {
// BLog.LOGE("on getHangule $span")
// val resultString = span.text()
// if (resultString != null && resultString.length > 0) {
// callBackHandler.removeCallbacks(postNext)
// callBack?.onConsoleLog("result::${span.text()}")
// callBack = null
// }
// }
// }.apply {
// callBackHandler.removeCallbacks(postNext)
// callBackHandler.postDelayed(postNext,25000L)
// }
// } else {
// val doc: Document = Jsoup.parse(result)
// callBack?.onConsoleLog("lastedFinishedPageUrl >>> ${doc}")
// }
// BLog.LOGE("binding.otherCheck after ThreadRun")
// }
//
// }
var postNext : Runnable = Runnable{
callBack?.collectComplete()
}
val callBackHandler = Handler(Looper.getMainLooper())
}
@ -1127,18 +827,6 @@ fun beforeDay(date: Date): Long {
return cal.timeInMillis
}
interface CommadCallabck {
fun onConsoleLog(log : String)
fun collectComplete()
}
fun openNews(schemeString : String) {
val gmmIntentUri = Uri.parse(schemeString)
val mapIntent = Intent(Intent.ACTION_VIEW, gmmIntentUri)
mapIntent.setPackage("com.android.chrome")
lActivity?.startActivity(mapIntent)
}
fun openClient(url : String){
val browserIntent = Intent(
Intent.ACTION_VIEW, Uri.parse(
@ -1146,11 +834,9 @@ fun openClient(url : String){
)
)
browserIntent.addFlags(Intent.FLAG_ACTIVITY_EXCLUDE_FROM_RECENTS)
// browserIntent.setPackage("org.chromium.webapk.a74a80967bc356126_v2")
// org.chromium.webapk.a74a80967bc356126_v2/org.chromium.webapk.shell_apk.h2o.H2OOpaqueMainActivity
// browserIntent.setComponent(ComponentName("org.chromium.webapk.a74a80967bc356126_v2","org.chromium.webapk.shell_apk.h2o.H2OOpaqueMainActivity"))
lActivity?.startActivity(browserIntent)
}
fun openYouTube(schemeString : String) {
val gmmIntentUri = Uri.parse(schemeString)
val mapIntent = Intent(Intent.ACTION_VIEW, gmmIntentUri)

View File

@ -23,12 +23,19 @@ import android.content.ComponentCallbacks2
import android.content.Context
import android.database.sqlite.SQLiteDatabase
import bums.lunatic.launcher.helpers.PrefHelper
import bums.lunatic.launcher.utils.Blog
import kr.lunaticbum.Base
import org.json.JSONObject
import org.mozilla.geckoview.ExperimentDelegate
import org.mozilla.geckoview.GeckoResult
import org.mozilla.geckoview.GeckoRuntime
import org.mozilla.geckoview.GeckoRuntimeSettings
internal class LunaticLauncher : Application() {
companion object {
var appContext : Context? = null
var appContext : LunaticLauncher? = null
}
override fun onCreate() {
@ -37,6 +44,8 @@ internal class LunaticLauncher : Application() {
Base.initialize(this)
PrefHelper.initialize(this)
}
override fun onTrimMemory(level: Int) {
super.onTrimMemory(level)
// Picasso.

View File

@ -21,9 +21,7 @@ package bums.lunatic.launcher.apps
import android.content.Context
import android.content.Intent
import android.content.SharedPreferences
import android.content.pm.ApplicationInfo
import android.content.pm.PackageManager
import android.content.pm.ResolveInfo
import android.net.Uri
import android.os.Bundle
import android.os.Handler
@ -35,7 +33,6 @@ import android.view.inputmethod.InputMethodManager
import androidx.core.widget.doOnTextChanged
import androidx.recyclerview.widget.GridLayoutManager
import bums.lunatic.launcher.BuildConfig
import bums.lunatic.launcher.LauncherActivity
import bums.lunatic.launcher.LauncherActivity.Companion.lActivity
import bums.lunatic.launcher.common.CommonActivity
import bums.lunatic.launcher.common.letTrue
@ -55,7 +52,6 @@ import io.realm.kotlin.ext.query
import io.realm.kotlin.query.RealmResults
import io.realm.kotlin.query.Sort
import java.net.URLEncoder
import java.text.Normalizer
import java.util.concurrent.Executors
import java.util.concurrent.TimeUnit
import java.util.regex.Pattern

View File

@ -1,9 +1,7 @@
package bums.lunatic.launcher.behavior
import android.content.Intent
import android.graphics.Color
import android.os.Bundle
import android.util.Log
import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
@ -13,12 +11,9 @@ import androidx.appcompat.app.AppCompatActivity
import androidx.core.view.WindowCompat
import androidx.recyclerview.widget.RecyclerView
import bums.lunatic.launcher.R
import bums.lunatic.launcher.behavior.calendar.CalendarAdapter
import bums.lunatic.launcher.behavior.calendar.CalendarBean
import bums.lunatic.launcher.behavior.calendar.CalendarDateView
import bums.lunatic.launcher.behavior.calendar.CalendarFactory.getMonthOfDayList
import bums.lunatic.launcher.behavior.calendar.CalendarUtil
import bums.lunatic.launcher.behavior.calendar.CalendarView
import bums.lunatic.launcher.databinding.ItemCalendarBinding
import com.google.android.material.appbar.AppBarLayout
import java.util.Date

View File

@ -5,7 +5,6 @@ import android.util.AttributeSet
import android.util.DisplayMetrics
import android.util.TypedValue
import android.view.View
import android.widget.TextView
import androidx.annotation.NonNull
import androidx.coordinatorlayout.widget.CoordinatorLayout
import androidx.recyclerview.widget.RecyclerView

View File

@ -3,19 +3,12 @@ package bums.lunatic.launcher.common
import android.content.Intent
import android.os.Environment
import androidx.appcompat.app.AppCompatActivity
import androidx.core.app.ComponentActivity
import bums.lunatic.launcher.R
import bums.lunatic.launcher.apps.SearchMenu
import bums.lunatic.launcher.helpers.PrefBoolean
import bums.lunatic.launcher.helpers.PrefHelper
import bums.lunatic.launcher.utils.Blog
import bums.lunatic.launcher.workers.LocationUpdateService
import com.google.android.material.dialog.MaterialAlertDialogBuilder
import com.google.gson.Gson
import com.google.gson.JsonArray
import com.google.gson.reflect.TypeToken
import org.json.JSONArray
import org.json.JSONObject
import java.io.BufferedReader
import java.io.File
import java.io.FileInputStream
@ -26,7 +19,6 @@ import java.io.InputStream
import java.io.InputStreamReader
import java.io.OutputStreamWriter
import java.util.Base64
import kotlin.system.exitProcess
abstract class CommonActivity : AppCompatActivity() {

View File

@ -8,7 +8,6 @@ import android.media.AudioManager
import android.view.KeyEvent
import bums.lunatic.launcher.utils.Blog
import java.util.Timer
import java.util.TimerTask
class HeadsetActionButtonReceiver : BroadcastReceiver() {

View File

@ -1,9 +1,6 @@
package bums.lunatic.launcher.helpers
import android.content.SharedPreferences
import bums.lunatic.launcher.model.RssDataType
import bums.lunatic.launcher.utils.Blog
import kr.lunaticbum.utils.preferences.PrefJsonConvert
import kr.lunaticbum.utils.preferences.PrefKey
import kr.lunaticbum.utils.preferences.PreferencesHelper
import java.math.BigDecimal

View File

@ -16,8 +16,12 @@ import android.view.KeyEvent.KEYCODE_BUTTON_X
import android.view.KeyEvent.KEYCODE_BUTTON_Y
import android.view.KeyEvent.KEYCODE_DPAD_DOWN
import android.view.KeyEvent.KEYCODE_DPAD_UP
import bums.lunatic.launcher.LauncherActivity.Companion.getRuntime
import bums.lunatic.launcher.tokiz.view.BWebview
import bums.lunatic.launcher.tokiz.view.JxEvent
import bums.lunatic.launcher.utils.Blog
import com.google.gson.Gson
import org.json.JSONException
import org.json.JSONObject
import org.mozilla.gecko.util.ThreadUtils
import org.mozilla.geckoview.ExperimentDelegate
@ -33,33 +37,47 @@ import org.mozilla.geckoview.WebExtension.PortDelegate
import org.mozilla.geckoview.WebExtensionController.AddonManagerDelegate
import org.mozilla.geckoview.WebRequestError
class GeckoWeb : GeckoView {
class GeckoWeb : BWebview {
constructor(context: Context?) : super(context) {
initWithContext(context)
buildWeb()
}
constructor(context: Context?, attrs: AttributeSet?) : super(context, attrs) {
initWithContext(context)
buildWeb()
}
fun loadUrl(url: String) {
Blog.LOGE("url >>>> ${url}")
if (url.split("//").size > 1) {
url.replace("//","/").replace("https:/","https://").let {
Blog.LOGE("url >> ${url} , it >>> ${it}")
this.session?.loadUri(url)
}
} else {
this.session?.loadUri(url)
}
currentRetryCount = 0;
}
val handle = object : Handler(Looper.getMainLooper()) {
override fun handleMessage(msg: Message) {
if (msg.what == 0) {
(msg.obj as? ReaderConfig)?.let {
}
}
val mPortNam = "browser"
val extPath = "resource://android/assets/extensions/my_extension/"
val extId = "messaging@booktoki468.com"
private fun buildWeb() {
getRuntime()?.let {
val session: GeckoSession = GeckoSession()
session.open(it)
this.setSession(session)
session.contentDelegate = contentDelegate
session.progressDelegate = progressDelegate
session.navigationDelegate = navigationDelegate
it.webExtensionController.setAddonManagerDelegate(addonManagerDelegate)
session.mediaDelegate = mediaDelegate
session.mediaSessionDelegate = mediaSessionDelegate
it.webExtensionController
.ensureBuiltIn(extPath, extId)
.accept( // Register message delegate for background script
{ extension: WebExtension? ->
ThreadUtils.runOnUiThread(
Runnable {
if (extension != null) {
session.webExtensionController.setMessageDelegate(
extension,
messageDelegate,
mPortNam
)
}
})
},
{ e: Throwable? -> Log.e("MessageDelegate", "Error registering WebExtension", e) })
}
}
@ -72,6 +90,17 @@ class GeckoWeb : GeckoView {
val extPath = "resource://android/assets/extensions/my_extension/"
val extId = "messaging@booktoki468.com"
}
fun sendScrollDown(isUp: Boolean) {
val message: JSONObject = JSONObject()
try {
message.put("type", "scrollDown")
message.put("isUpDown", if (isUp) +1 else -1)
} catch (ex: JSONException) {
throw RuntimeException(ex)
}
Blog.LOGE(Gson().toJson(message))
mPort?.postMessage(message)
}
var mExtension: WebExtension? = null
var mSession: GeckoSession? = null
@ -91,32 +120,7 @@ class GeckoWeb : GeckoView {
}
}
private fun initWithContext(context: Context?) {
context?.let { context ->
initGeckoRuntime(context)
mSession = GeckoSession()
mSession?.contentDelegate = contentDelegate
mSession?.progressDelegate = progressDelegate
mSession?.navigationDelegate = navigationDelegate
sRuntime?.apply {
webExtensionController.setAddonManagerDelegate(addonManagerDelegate)
webExtensionController.ensureBuiltIn(WebExtensionInfo.extPath, WebExtensionInfo.extId)
.accept( // Register message delegate for background script
{ extension: WebExtension? ->
ThreadUtils.runOnUiThread(Runnable { mSession?.let{session-> extension?.let { session.webExtensionController.setMessageDelegate(it,messageDelegate,WebExtensionInfo.mPortNam) }} })
},
{ e: Throwable? -> Log.e("MessageDelegate", "Error registering WebExtension", e) })
mSession?.mediaDelegate = mediaDelegate
mSession?.mediaSessionDelegate = mediaSessionDelegate
mSession?.open(sRuntime!!)
}.let {
this.setSession(mSession!!)
this.loadUrl("https://booktoki468.com") // Or any other URL...
}
}
}
val mediaDelegate = object : GeckoSession.MediaDelegate {
override fun onRecordingStatusChanged(
session: GeckoSession,
@ -203,21 +207,6 @@ class GeckoWeb : GeckoView {
super.onFullscreen(session, mediaSession, enabled, meta)
}
}
private fun initGeckoRuntime(context : Context) {
if (sRuntime == null) {
try {
val settings: GeckoRuntimeSettings =
GeckoRuntimeSettings.Builder().extensionsProcessEnabled(true)
.extensionsWebAPIEnabled(true)
.experimentDelegate(experimentDelegate)
.remoteDebuggingEnabled(true).build()
sRuntime = GeckoRuntime.create(context, settings)
} catch (e: Exception) {
}
}
}
val experimentDelegate = object : ExperimentDelegate {
override fun onGetExperimentFeature(feature: String): GeckoResult<JSONObject?> {
@ -261,12 +250,11 @@ class GeckoWeb : GeckoView {
}
override fun onPaintStatusReset(session: GeckoSession) {
Blog.LOGE("onPaintStatusReset")
super.onPaintStatusReset(session)
}
override fun onFirstContentfulPaint(session: GeckoSession) {
Blog.LOGE("onFirstContentfulPaint")
super.onFirstContentfulPaint(session)
}
}
@ -410,13 +398,6 @@ class GeckoWeb : GeckoView {
}
fun onDestroy() {
sRuntime = null
}
override fun dispatchKeyEvent(ev: KeyEvent): Boolean {
Blog.LOGE("dispatch ev?.device?.name >>> ${ev?.device?.name}")
if (ev?.device?.name?.contains("SM-031N Mouse") == true) {
@ -467,7 +448,6 @@ class GeckoWeb : GeckoView {
companion object {
private const val TAG = "DualScreenStatus"
var sRuntime: GeckoRuntime? = null
var currentRetryCount = 0
}
}

View File

@ -19,107 +19,53 @@
package bums.lunatic.launcher.home
import android.annotation.SuppressLint
import android.content.ComponentName
import android.content.Context.AUDIO_SERVICE
import android.content.DialogInterface
import android.content.Intent
import android.content.IntentFilter
import android.content.SharedPreferences
import android.content.pm.PackageManager
import android.media.AudioManager
import android.net.Uri
import android.os.Build
import android.os.Bundle
import android.os.Handler
import android.os.Looper
import android.os.SystemClock
import android.provider.AlarmClock
import android.view.HapticFeedbackConstants
import android.view.KeyEvent
import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
import android.webkit.WebSettings.LOAD_NO_CACHE
import android.webkit.WebSettings.MIXED_CONTENT_ALWAYS_ALLOW
import android.widget.CheckBox
import android.widget.EditText
import android.widget.TableRow
import android.widget.Toast
import androidx.annotation.NonNull
import androidx.appcompat.app.AlertDialog
import androidx.biometric.BiometricPrompt
import androidx.core.view.children
import androidx.annotation.RequiresApi
import androidx.fragment.app.Fragment
import androidx.fragment.app.FragmentManager
import androidx.recyclerview.widget.DividerItemDecoration
import androidx.recyclerview.widget.ItemTouchHelper
import androidx.recyclerview.widget.RecyclerView
import androidx.viewpager2.widget.ViewPager2
import bums.lunatic.launcher.LauncherActivity.Companion.lActivity
import bums.lunatic.launcher.R
import bums.lunatic.launcher.apps.AppsAdapter
import bums.lunatic.launcher.behavior.Behavior
import bums.lunatic.launcher.common.letTrue
import bums.lunatic.launcher.databinding.LauncherHomeBinding
import bums.lunatic.launcher.helpers.Constants.Companion.BOTTOM_SHEET_TAG
import bums.lunatic.launcher.helpers.Constants.Companion.KEY_LOCK_METHOD
import bums.lunatic.launcher.helpers.Constants.Companion.PREFS_SETTINGS
import bums.lunatic.launcher.helpers.PrefBoolean
import bums.lunatic.launcher.helpers.UniUtils.Companion.expandNotificationPanel
import bums.lunatic.launcher.helpers.UniUtils.Companion.lockMethod
import bums.lunatic.launcher.home.adapters.NotificationItemAdapter
import bums.lunatic.launcher.home.adapters.RecentCallsAdapter
import bums.lunatic.launcher.home.adapters.RssItemAdapter
import bums.lunatic.launcher.home.adapters.SmsLogsAdapter
import bums.lunatic.launcher.home.adapters.RssItemAdapter.Companion.rssList
import bums.lunatic.launcher.home.adapters.SwipeToDeleteCallback
import bums.lunatic.launcher.home.adapters.WeatherAdapter
import bums.lunatic.launcher.home.adapters.WeatherDressAdatper
import bums.lunatic.launcher.home.adapters.WeatherHourlyAdapter
import bums.lunatic.launcher.model.AppInfo
import bums.lunatic.launcher.model.CurrentPlayItem
import bums.lunatic.launcher.model.Hour
import bums.lunatic.launcher.model.NotificationItem
import bums.lunatic.launcher.model.RssData
import bums.lunatic.launcher.model.RssDataInterface
import bums.lunatic.launcher.model.RssDataType
import bums.lunatic.launcher.model.WeatherForcast
import bums.lunatic.launcher.model.WeatherInfoManager
import bums.lunatic.launcher.qaccess.QuickAccess
import bums.lunatic.launcher.settings.SettingsActivity
import bums.lunatic.launcher.openClient
import bums.lunatic.launcher.openReddit
import bums.lunatic.launcher.openYouTube
import bums.lunatic.launcher.tokiz.view.JxEvent
import bums.lunatic.launcher.utils.Blog
import bums.lunatic.launcher.utils.BitmapConverter
import bums.lunatic.launcher.utils.SimpleFingerGestures
import bums.lunatic.launcher.utils.USAGT
import bums.lunatic.launcher.utils.beforeDay
import bums.lunatic.launcher.utils.beforeOneDay
import bums.lunatic.launcher.view.TableRadioGroup
import bums.lunatic.launcher.workers.LocationGetter
import bums.lunatic.launcher.workers.RecentCall
import bums.lunatic.launcher.workers.RecentSms
import bums.lunatic.launcher.workers.WorkersDb
import bums.lunatic.launcher.workers.latitudeRange
import bums.lunatic.launcher.workers.longitudeRange
import com.google.android.material.imageview.ShapeableImageView
import io.realm.kotlin.UpdatePolicy
import io.realm.kotlin.ext.query
import io.realm.kotlin.notifications.InitialResults
import io.realm.kotlin.notifications.ResultsChange
import io.realm.kotlin.notifications.UpdatedResults
import io.realm.kotlin.query.RealmQuery
import io.realm.kotlin.query.RealmResults
import io.realm.kotlin.query.Sort
import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.Job
import kotlinx.coroutines.flow.cancellable
import kotlinx.coroutines.flow.collect
import kotlinx.coroutines.launch
import okhttp3.Dns
import org.json.JSONArray
import org.json.JSONObject
import java.math.BigDecimal
import java.math.RoundingMode
import java.net.URLEncoder
import java.util.Calendar
import kotlin.jvm.java
internal class LauncherHome : Fragment() {
@ -143,15 +89,164 @@ internal class LauncherHome : Fragment() {
fun rssStateVote() = (lasted?.filter { it.vote == true }?.size ?: -1) == (lasted?.size ?: 0)
var lasted: List<RssData>? = null
var infosJob: Job? = null
var rssId = ""
lateinit var mRssAdapter: RssItemAdapter
var mRssDataResult: RealmResults<RssData>? = null
val mSimpleFingerGestures = SimpleFingerGestures(omfgl = object : SimpleFingerGestures.OnFingerGestureListener{
override fun onSwipeUp(
targetView: View,
fingers: Int,
gestureDuration: Long,
gestureDistance: Double
): Boolean {
Blog.LOGE("")
return true
}
override fun onSwipeDown(
targetView: View,
fingers: Int,
gestureDuration: Long,
gestureDistance: Double
): Boolean {
Blog.LOGE("")
return true
}
override fun onSwipeLeft(
targetView: View,
fingers: Int,
gestureDuration: Long,
gestureDistance: Double
): Boolean {
Blog.LOGE("")
return true
}
override fun onSwipeRight(
targetView: View,
fingers: Int,
gestureDuration: Long,
gestureDistance: Double
): Boolean {
Blog.LOGE("")
return true
}
override fun onPinch(
targetView: View,
fingers: Int,
gestureDuration: Long,
gestureDistance: Double
): Boolean {
Blog.LOGE("onPinch")
return false
}
override fun onUnpinch(
targetView: View,
fingers: Int,
gestureDuration: Long,
gestureDistance: Double
): Boolean {
Blog.LOGE("")
return true
}
override fun onDoubleTap(
targetView: View,
fingers: Int
): Boolean {
Blog.LOGE("")
return true
}
override fun onLongPress(
targetView: View,
fingers: Int
): Boolean {
Blog.LOGE("onLongPress")
return false
}
override fun onClick(
targetView: View,
fingers: Int
): Boolean {
Blog.LOGE("onClick")
return false
}
})
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
home = this
}
var targetList = arrayListOf<String>()
val dateViewClick = View.OnClickListener { v ->
Blog.LOGE("click view >> ${v}")
(v?.tag as? RssData)?.let { rss ->
WorkersDb.getRealm().apply {
writeBlocking {
rss.read = rss.read + 1
if(rss.getCho()?.length ?: 0 < 1) {
rss.chosung = rss.title
}
copyToRealm(rss,UpdatePolicy.ALL)
}
}
when(rss.category()) {
RssDataType.GURU,RssDataType.MOST,RssDataType.REDDIT_NSFW -> {
v.findViewById<ShapeableImageView>(R.id.circle_preview)?.let {
if (it.visibility == View.GONE) {
it.visibility = View.VISIBLE
it.postDelayed({
it.visibility = View.GONE
}, 2000L)
} else {
if (RssDataType.REDDIT_NSFW.equals(rss.category())) {
openReddit(rss.originPage())
} else {
openGecko(rss.originPage())
}
}
}
}
RssDataType.REDDIT -> {
openReddit(rss.originPage())
}
RssDataType.DOTAX -> {
openGecko(rss.originPage())
}
RssDataType.YOUTUBE -> { openYouTube(rss.originPage())
}
RssDataType.CLIEN -> {
openGecko(rss.originPage())
}
else -> {
openGecko(rss.originPage())
}
}
}
}
fun openGecko(originPage: String) {
rssId = originPage
targetList.clear()
var setString = hashSetOf<String>()
setString.addAll(rssList)
setString.removeAll { it.equals(rssId) }
targetList.addAll(setString)
binding.geckoWeb.loadUrl(rssId)
}
@SuppressLint("ClickableViewAccessibility")
override fun onCreateView(
inflater: LayoutInflater,
container: ViewGroup?,
@ -160,15 +255,75 @@ internal class LauncherHome : Fragment() {
binding = LauncherHomeBinding.inflate(inflater, container, false)
fragManager = lActivity!!.supportFragmentManager
settingsPrefs = requireContext().getSharedPreferences(PREFS_SETTINGS, 0)
mRssAdapter = RssItemAdapter(requireContext())
mRssAdapter = RssItemAdapter(requireContext(),dateViewClick)
val decoration = DividerItemDecoration(requireContext(), DividerItemDecoration.VERTICAL)
binding.infoList.addItemDecoration(decoration)
binding.infoList.visibility = View.VISIBLE
binding.infoList.adapter = mRssAdapter
binding.infoList.setOnTouchListener { v,e ->
if (e.device.name?.contains("JX-12",true) == true) {
Blog.LOGE("touchEvent -> ${e}")
return@setOnTouchListener mSimpleFingerGestures.onTouch(v,e)
} else {
return@setOnTouchListener false
}
}
queryInfos()
binding.geckoWeb.jxInteface = { jxEvent ->
when(jxEvent) {
JxEvent.SCROLL_UP -> binding.geckoWeb.sendScrollDown(false)
JxEvent.SCROLL_DOWN -> binding.geckoWeb.sendScrollDown(true)
JxEvent.ON_CLICK -> {
binding.geckoWeb.visibility = View.GONE
}
JxEvent.SWIPE_LEFT -> {
doNextPage()
}
JxEvent.SWIPE_RIGHT -> {
vote()
}
}
}
return binding.root
}
fun vote(){
Blog.LOGE("Arrow Center Click")
WorkersDb.getRealm().apply {
writeBlocking {
val result = query<RssData>().query("originPage == $0", rssId).find()
if (result.size > 0) {
result.forEach { it.vote = true }
}
}
}
doNextPage()
}
@SuppressLint("NewApi")
fun doNextPage() {
WorkersDb.getRealm().apply {
writeBlocking {
val result = query<RssData>().query("originPage == $0", rssId).find()
if (result.size > 0) {
result.forEach {
it.read = it.read + nomoreShowCount
}
}
}
}
targetList.removeAll { it.equals(rssId) }
if (targetList.size > 0) {
rssId = targetList.removeFirst()
binding.geckoWeb.loadUrl(rssId)
} else {
Toast.makeText(requireContext(), "없어 끄자", Toast.LENGTH_LONG).show()
binding.geckoWeb.visibility = View.GONE
}
}
fun clearJob(job : Job?) {
try { job?.cancel() } catch (e: Exception) { e.printStackTrace() }
try { System.gc() } catch (e: Exception) { e.printStackTrace() }
@ -258,6 +413,7 @@ internal class LauncherHome : Fragment() {
private fun enableSwipeToDeleteAndUndo() {
val swipeToDeleteCallback: SwipeToDeleteCallback =
object : SwipeToDeleteCallback(requireContext()) {
override fun onSwiped(@NonNull viewHolder: RecyclerView.ViewHolder, direction: Int) {
Blog.LOGE("onSwiped direction >>>> $direction")
(viewHolder.itemView.tag as? RssData)?.let { rss ->
@ -290,7 +446,9 @@ internal class LauncherHome : Fragment() {
}
}
else -> {}
else -> {
}
}
binding.infoList.post { mRssAdapter.refresh() }
}

View File

@ -2,15 +2,11 @@ package bums.lunatic.launcher.home
import android.content.ClipData
import android.content.ClipboardManager
import android.content.ComponentName
import android.content.Context
import android.content.Intent
import android.net.Uri
import android.os.Bundle
import android.print.PDFPrint
import android.provider.AlarmClock
import android.util.Base64
import android.view.HapticFeedbackConstants
import android.view.KeyEvent
import android.view.KeyEvent.ACTION_UP
import android.view.KeyEvent.KEYCODE_BUTTON_A
@ -29,28 +25,15 @@ import android.view.View
import android.webkit.CookieManager
import android.webkit.CookieSyncManager
import android.webkit.JavascriptInterface
import android.webkit.ValueCallback
import android.widget.Toast
import androidx.appcompat.app.AlertDialog
import androidx.core.net.toUri
import androidx.core.view.postDelayed
import bums.lunatic.launcher.LauncherActivity.Companion.lActivity
import bums.lunatic.launcher.behavior.Behavior
import bums.lunatic.launcher.helpers.Constants.Companion.BOTTOM_SHEET_TAG
import bums.lunatic.launcher.helpers.Constants.Companion.KEY_LOCK_METHOD
import bums.lunatic.launcher.helpers.UniUtils.Companion.expandNotificationPanel
import bums.lunatic.launcher.helpers.UniUtils.Companion.lockMethod
import bums.lunatic.launcher.model.CiliMagnet
import bums.lunatic.launcher.model.RssData
import bums.lunatic.launcher.qaccess.QuickAccess
import bums.lunatic.launcher.settings.SettingsActivity
import bums.lunatic.launcher.utils.Blog
import bums.lunatic.launcher.utils.SimpleFingerGestures
import bums.lunatic.launcher.workers.WorkersDb
import com.google.gson.Gson
import io.realm.kotlin.UpdatePolicy
import io.realm.kotlin.ext.query
import io.realm.kotlin.ext.realmListOf
import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.launch

View File

@ -21,6 +21,7 @@ package bums.lunatic.launcher.home.adapters
import android.annotation.SuppressLint
import android.content.Context
import android.view.LayoutInflater
import android.view.MotionEvent
import android.view.View
import android.view.ViewGroup
import androidx.constraintlayout.widget.ConstraintLayout
@ -36,19 +37,17 @@ import bums.lunatic.launcher.model.RssData
import bums.lunatic.launcher.model.RssDataInterface
import bums.lunatic.launcher.model.RssDataType
import bums.lunatic.launcher.openClient
import bums.lunatic.launcher.openDotax
import bums.lunatic.launcher.openReddit
import bums.lunatic.launcher.openYouTube
import bums.lunatic.launcher.tokiz.view.JxEvent
import bums.lunatic.launcher.utils.Blog
import bums.lunatic.launcher.utils.SimpleFingerGestures
import bums.lunatic.launcher.workers.WorkersDb
import com.google.android.material.imageview.ShapeableImageView
import com.google.gson.Gson
import com.squareup.picasso.Picasso
import kr.lunaticbum.awesomewebview.AwesomeWebView
import io.realm.kotlin.UpdatePolicy
import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.GlobalScope
import kotlinx.coroutines.launch
import kr.lunaticbum.awesomewebview.listeners.WebViewListener
import java.text.SimpleDateFormat
@ -56,7 +55,8 @@ import java.util.Date
internal class RssItemAdapter (
private val context: Context) : RecyclerView.Adapter<RssHolder>() {
private val context: Context,
private val dateViewClick : View.OnClickListener) : RecyclerView.Adapter<RssHolder>() {
companion object {
@SuppressLint("SimpleDateFormat")
val dateFormat = SimpleDateFormat("a HH:mm / yy - MM - dd")
@ -70,75 +70,7 @@ internal class RssItemAdapter (
}
}
}
val dateViewClick = View.OnClickListener { v ->
(v?.tag as? RssData)?.let { rss ->
WorkersDb.getRealm().apply {
writeBlocking {
rss.read = rss.read + 1
if(rss.getCho()?.length ?: 0 < 1) {
rss.chosung = rss.title
}
copyToRealm(rss,UpdatePolicy.ALL)
}
}
when(rss.category()) {
RssDataType.GURU,RssDataType.MOST,RssDataType.REDDIT_NSFW -> {
v.findViewById<ShapeableImageView>(R.id.circle_preview)?.let {
if (it.visibility == View.GONE) {
it.visibility = View.VISIBLE
it.postDelayed({
it.visibility = View.GONE
}, 2000L)
} else {
if (RssDataType.REDDIT_NSFW.equals(rss.category())) {
openReddit(rss.originPage())
} else {
RssViewBuilder(lActivity!!)
.setRssList(arrayListOf<String>().apply {
var jjjj = hashSetOf<String>()
jjjj.addAll(rssList)
this.addAll(jjjj)
})
.setRssId(rss.originPage())
.showIconClose(true).showIconBack(false).showProgressBar(true).backPressToClose(false).webViewMixedContentMode(1)
.show(rss.originPage!!)
}
}
}
}
RssDataType.REDDIT -> {
openReddit(rss.originPage())
}
RssDataType.DOTAX -> {
RssViewBuilder(lActivity!!)
.setRssList(arrayListOf<String>().apply {
var jjjj = hashSetOf<String>()
jjjj.addAll(rssList)
this.addAll(jjjj)
})
.setRssId(rss.originPage())
.showIconClose(true).showIconBack(false).showProgressBar(true).webViewMixedContentMode(0)
.show(rss.originPage!!)
}
RssDataType.YOUTUBE -> { openYouTube(rss.originPage())
}
RssDataType.CLIEN -> {
openClient(rss.originPage())
}
else -> {
RssViewBuilder(lActivity!!)
.setRssList(arrayListOf<String>().apply {
var jjjj = hashSetOf<String>()
jjjj.addAll(rssList)
this.addAll(jjjj)
})
.setRssId(rss.originPage())
.showIconClose(true).showIconBack(false).showProgressBar(true).webViewMixedContentMode(0)
.show(rss.originPage!!)
}
}
}
}
private var rssDataItemLis: ArrayList<RssData> = arrayListOf()
val mLongClickListener = View.OnLongClickListener { v ->
(v?.tag as? RssData)?.let { rss ->
@ -166,8 +98,95 @@ internal class RssItemAdapter (
}
val mSimpleFingerGestures = SimpleFingerGestures(omfgl = object : SimpleFingerGestures.OnFingerGestureListener{
@SuppressLint("SetTextI18n")
override fun onSwipeUp(
targetView: View,
fingers: Int,
gestureDuration: Long,
gestureDistance: Double
): Boolean {
Blog.LOGE("")
return true
}
override fun onSwipeDown(
targetView: View,
fingers: Int,
gestureDuration: Long,
gestureDistance: Double
): Boolean {
Blog.LOGE("")
return true
}
override fun onSwipeLeft(
targetView: View,
fingers: Int,
gestureDuration: Long,
gestureDistance: Double
): Boolean {
Blog.LOGE("")
return true
}
override fun onSwipeRight(
targetView: View,
fingers: Int,
gestureDuration: Long,
gestureDistance: Double
): Boolean {
Blog.LOGE("")
return true
}
override fun onPinch(
targetView: View,
fingers: Int,
gestureDuration: Long,
gestureDistance: Double
): Boolean {
Blog.LOGE("onPinch")
return false
}
override fun onUnpinch(
targetView: View,
fingers: Int,
gestureDuration: Long,
gestureDistance: Double
): Boolean {
Blog.LOGE("")
return true
}
override fun onDoubleTap(
targetView: View,
fingers: Int
): Boolean {
Blog.LOGE("")
return true
}
override fun onLongPress(
targetView: View,
fingers: Int
): Boolean {
Blog.LOGE("onLongPress")
return true
}
override fun onClick(
targetView: View,
fingers: Int
): Boolean {
Blog.LOGE("onClick")
return true
}
})
@SuppressLint("SetTextI18n", "ClickableViewAccessibility")
override fun onBindViewHolder(holder: RssHolder, position: Int) {
val rssData = rssDataItemLis[position]
if (rssData.pubDate() > 1000L) {
@ -176,9 +195,6 @@ internal class RssItemAdapter (
holder.view.date.text = emptyDate
}
// if(RssDataType.NEWSFEED.equals(rssData.category())) {
// Blog.LOGE("rssData >>>> ${rssData.thumbnailUrl()}")
// }
holder.view.title.text = "".plus(if(rssData.vote) " * " else "").plus(rssData.title().plus("[R:${rssData.read}]"))
holder.view.desc.text = rssData.description()
@ -198,6 +214,19 @@ internal class RssItemAdapter (
holder.itemView.tag = rssData
holder.itemView.setOnClickListener(dateViewClick)
holder.itemView.setOnTouchListener(object : View.OnTouchListener{
override fun onTouch(
v: View,
event: MotionEvent
): Boolean {
Blog.LOGE("event.device.name >>> ${event.device.name}")
if (event.device.name?.contains("JX-12",true) == true) {
return true//mSimpleFingerGestures.onTouch(v,event)
} else {
return false
}
}
})
// v.setOnLongClickListener {
// WorkersDb.getRealm().apply {
// copyFromRealm(rss)

View File

@ -7,7 +7,6 @@ import androidx.recyclerview.widget.RecyclerView
import bums.lunatic.launcher.databinding.ItemHourlyWeatherBinding
import bums.lunatic.launcher.model.Hour
import bums.lunatic.launcher.model.WeatherInfoManager
import bums.lunatic.launcher.utils.Blog
import com.squareup.picasso.Picasso
class WeatherHourlyAdapter(private val dataSet: ArrayList<Hour>): RecyclerView.Adapter<WeatherHourlyAdapter.ViewHolder>() {

View File

@ -1,8 +1,6 @@
package bums.lunatic.launcher.model
import bums.lunatic.launcher.beforeDay
import bums.lunatic.launcher.utils.JamoUtils
import java.util.Date
class MostItem : JGuru , RssDataInterface {

View File

@ -1,9 +1,6 @@
package bums.lunatic.launcher.model
import com.ibm.icu.util.ChineseCalendar
import io.realm.kotlin.types.RealmObject
import java.util.Calendar
import java.util.Date
class UserActionModel: RealmObject {

View File

@ -15,7 +15,6 @@ import androidx.annotation.RequiresApi
import androidx.core.content.getSystemService
import bums.lunatic.launcher.model.CurrentPlayItem
import bums.lunatic.launcher.model.NotificationItem
import bums.lunatic.launcher.utils.Blog
import bums.lunatic.launcher.utils.BitmapConverter
import bums.lunatic.launcher.workers.WorkersDb
import io.realm.kotlin.UpdatePolicy

View File

@ -28,7 +28,6 @@ import android.view.ViewGroup
import bums.lunatic.launcher.R
import bums.lunatic.launcher.databinding.SettingsAppsBinding
import bums.lunatic.launcher.helpers.PrefBoolean
import bums.lunatic.launcher.helpers.PrefHelper
import bums.lunatic.launcher.helpers.PrefLong
import bums.lunatic.launcher.utils.Blog
import com.google.android.material.bottomsheet.BottomSheetBehavior

View File

@ -26,17 +26,11 @@ import android.view.ViewGroup
import androidx.core.widget.doOnTextChanged
import bums.lunatic.launcher.R
import bums.lunatic.launcher.databinding.SettingsWeatherBinding
import bums.lunatic.launcher.helpers.Constants.Companion.KEY_CITY_NAME
import bums.lunatic.launcher.helpers.Constants.Companion.KEY_OWM_API
import bums.lunatic.launcher.helpers.Constants.Companion.KEY_SHOW_CITY
import bums.lunatic.launcher.helpers.Constants.Companion.KEY_TEMP_UNIT
import bums.lunatic.launcher.helpers.PrefBoolean
import bums.lunatic.launcher.helpers.PrefString
import bums.lunatic.launcher.settings.SettingsActivity.Companion.settingsPrefs
import com.google.android.material.bottomsheet.BottomSheetDialog
import com.google.android.material.bottomsheet.BottomSheetDialogFragment
import com.google.android.material.dialog.MaterialAlertDialogBuilder
import java.util.Objects
import kotlin.system.exitProcess
open class SettingChild : BottomSheetDialogFragment() {

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,130 @@
package bums.lunatic.launcher.tokiz
import android.graphics.Color
import android.os.Build
import android.os.Bundle
import androidx.annotation.RequiresApi
import androidx.databinding.DataBindingUtil
import bums.lunatic.launcher.R
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 bums.lunatic.launcher.common.CommonActivity
import bums.lunatic.launcher.databinding.SettingsBinding
import io.realm.kotlin.UpdatePolicy
import io.realm.kotlin.ext.query
import kotlin.collections.first
import kotlin.collections.last
import kotlin.collections.map
import kotlin.collections.toTypedArray
import kotlin.let
class Settings : CommonActivity() {
lateinit var binding : SettingsBinding
var readerConfig : ReaderConfig? = null
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
binding = DataBindingUtil.setContentView(this, R.layout.settings)
// setContentView(R.layout.settings)
var realm = HistoryManager.openRealm
realm.writeBlocking {
this.query<ReaderConfig>()?.find()?.let {
if (it.size > 0) {
readerConfig = copyFromRealm(it.first())
} else {
readerConfig = ReaderConfig()
}
}
}
}
@RequiresApi(Build.VERSION_CODES.O)
override fun onResume() {
super.onResume()
binding.textSize.displayFormat = "글자 크기 : %d"
binding.textSize.value = readerConfig?.textSize ?: 14
binding.textSize.mValueChange = {
binding.preview.textSize = it.toFloat() ;
if (readerConfig?.textSize != it) {
readerConfig?.textSize = it
configSave()
}
}
binding.pagePadding.displayFormat = "페이지 여백 : %d"
binding.pagePadding.value = readerConfig?.padding ?: 5
binding.pagePadding.mValueChange = {
binding.preview.setPadding(it,it,it,it) ;
if (readerConfig?.padding != it) {
readerConfig?.padding = it
configSave()
}
}
binding.letterSpace.displayFormat = "자간 : %d"
binding.letterSpace.value = readerConfig?.letterSpace ?: 1
binding.letterSpace.mValueChange = {
binding.preview.letterSpacing = it.times(0.01).toFloat() ;
if (readerConfig?.letterSpace != it) {
readerConfig?.letterSpace = it
configSave()
}
}
binding.lineSpace.displayFormat = "행간 : %d"
binding.lineSpace.value = readerConfig?.lineSpace ?: 1
binding.lineSpace.mValueChange = {
binding.preview.setLineSpacing(1f, 1f.plus(it.times(0.01f))) ;
if (readerConfig?.lineSpace != it) {
readerConfig?.lineSpace = it
configSave()
}
}
binding.pageTypesface.displayFormat = "폰트 : %s"
binding.pageTypesface.titleArray = typesfacez.map { it.first }.toTypedArray()
binding.pageTypesface.value = getIndex(typesfacez as PairArray<Any>,readerConfig?.font ?: "")
binding.pageTypesface.mValueChange = {
val pair = typesfacez.get(it)
binding.preview.setTypeface(resources.getFont(pair.second))
if (readerConfig?.font != pair.first) {
readerConfig?.font = pair.first ?: ""
configSave()
}
}
binding.pageStyle.displayFormat = "스타일 : %s"
binding.pageStyle.titleArray = colorz.map { it.first }.toTypedArray()
binding.pageStyle.value = readerConfig?.style ?: 0
binding.pageStyle.mValueChange = {
val pair = colorz.get(it)
binding.preview.setBackgroundColor(Color.parseColor(pair.second.last()))
binding.preview.setTextColor(Color.parseColor(pair.second.first()))
if (readerConfig?.style != it) {
readerConfig?.style = it ?: 0
configSave()
}
}
}
fun configSave() {
var realm = HistoryManager.openRealm
realm.writeBlocking {
copyToRealm(readerConfig!!, UpdatePolicy.ALL)
}
}
}

View File

@ -0,0 +1,88 @@
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

@ -0,0 +1,30 @@
package bums.lunatic.launcher.tokiz.common
import android.content.Context
import android.content.SharedPreferences
import bums.lunatic.launcher.tokiz.webcontents.contentsinfo.BooktokiStruct
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

@ -0,0 +1,187 @@
package bums.lunatic.launcher.tokiz.data
import bums.lunatic.launcher.tokiz.data.model.BookPageInfo
import bums.lunatic.launcher.tokiz.data.model.BookPageInfos
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(aUrl : String, callback : (BookPageInfos?)->Unit) {
var url : String = aUrl
Blog.LOGE("aUrl >>> ${aUrl}")
openRealm.apply{
if (url.startsWith("//")) {
while (url.startsWith("//")) {
url = url.replace("//","/").trim()
}
}
Blog.LOGE("aUrl >>> ${url}")
var bookPageInfo = this.query(BookPageInfo::class).query("pathUrl == $0 || bookPageUrl == $0","${url}").find()
if (bookPageInfo != null && bookPageInfo.count() > 0) {
Blog.LOGE("get ${bookPageInfo}" )
var pgs = this.query(BookPageInfos::class,"bookPageUrl == $0", bookPageInfo.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)
}
}
}
fun getBookPageInfo(aUrl : String, callback : (BookPageInfo?)->Unit) {
var url : String = aUrl
openRealm.apply{
if (url.startsWith("//")) {
while (url.startsWith("//")) {
url = url.replace("//","/").trim()
}
}
var result = this.query(BookPageInfo::class).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(aUrl : String, page :Int) {
var url : String = aUrl
openRealm.writeBlocking {
if (url.startsWith("//")) {
while (url.startsWith("//")) {
url = url.replace("//","/").trim()
}
}
var result = this.query(BookPageInfo::class).query("pathUrl == $0","${url}").find()
if (result.size > 0) {
var bookPageInfo = result?.first()
if (bookPageInfo != null) {
bookPageInfo.lastPage = page
}
}
}
}
fun getBooPageInfoContentsSave(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(BookPageInfo::class).query("pathUrl == $0", "${url}").find()
if (result.size > 0) {
result.first().contents = contents
copyToRealm(result.first(), UpdatePolicy.ALL)
}
}
}
fun getNextPage(aUrl : String ,callback : (BookPageInfo?)->Unit) {
var url : String = aUrl
openRealm.apply{
if (url.startsWith("//")) {
while (url.startsWith("//")) {
url = url.replace("//","/").trim()
}
}
var bookPageInfo =
this.query(BookPageInfo::class).query("pathUrl == $0", url).find()
if (bookPageInfo.size > 0) {
Blog.LOGE("getNextPage 2 => chapterNum : ${bookPageInfo.first().chapterNum} , bookPageInfo.bookPageUrl : ${bookPageInfo.first().bookPageUrl}" )
var results = this.query(BookPageInfo::class).query("chapterNum == $0",bookPageInfo.first().chapterNum + 1).query("bookPageUrl == $0","${bookPageInfo.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(aUrl : String ,callback : (BookPageInfo?)->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 bookPageInfo =
this.query(BookPageInfo::class).query("pathUrl == $0", url).find()
Blog.LOGE("getPrevPage ${bookPageInfo}" )
if (bookPageInfo.size > 0) {
Blog.LOGE("getPrevPage 2 ${bookPageInfo?.first()?.chapterNum}" )
Blog.LOGE("getPrevPage 2 ${bookPageInfo?.first()?.bookPageUrl}" )
var results = this.query(BookPageInfo::class).query("chapterNum == $0",bookPageInfo.first().chapterNum - 1).query("bookPageUrl == $0","${bookPageInfo.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

@ -0,0 +1,131 @@
package bums.lunatic.launcher.tokiz.data.model
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 : BookPageInfosJ? = null
var book : BookContents? = null
var msg : String? = null
}
class BookContents {
var chapterTitle : String? = null
var bookContents : String? = null
}
class BookPageInfosJ {
var bookTitle : String = ""
var bookPageUrl : String = ""
var pages : ArrayList<BookPageInfoJ> = arrayListOf<BookPageInfoJ>()
fun getTitleArray() : ArrayList<String> {
var arrayList = ArrayList<String>()
pages.forEach { arrayList.add(it.bookTitle ?: "") }
return arrayList
}
fun getR() : BookPageInfos{
var r = BookPageInfos()
r.bookTitle = this.bookTitle
r.bookPageUrl = this.bookPageUrl
return r
}
}
class BookPageInfoJ {
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? = ""
fun getRealm() : BookPageInfo {
var r = BookPageInfo()
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("'","")
return r
}
}
class BookPageInfos : RealmObject {
var bookTitle : String = ""
@PrimaryKey
var bookPageUrl : String? = ""
var pages : RealmList<BookPageInfo> = realmListOf()
fun getTitleArray() : ArrayList<String> {
var arrayList = ArrayList<String>()
pages.forEach {
arrayList.add(it.getTitleItem())}
return arrayList
}
fun sort() {
val comparator : Comparator<BookPageInfo> = compareBy { it.chapterID }
pages.sortWith(comparator)
}
fun hasItem(item: BookPageInfo) : Boolean {
var hasItem = false
for (c in pages) {
if (!hasItem) {
hasItem = c.pathUrl.equals(item.pathUrl)
}
}
return hasItem
}
}
class BookPageInfo : 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
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

@ -0,0 +1,61 @@
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 = "UniqLastId"
var pageUrl : String = ""
var title : String = ""
var chapter : Int = 0
var pageIndex : Int = 0
var contentsName : String = ""
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
}
}
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
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
}
fun putHistory(bookPageInfo: BookPageInfo? , currentPath : String) : HistoryItem {
title = bookPageInfo?.bookTitle ?: SimpleDateFormat("YY-mm-DD-HH:mm").format(Date())
pageUrl = bookPageInfo?.pathUrl ?: currentPath
chapter = bookPageInfo?.chapterNum ?: 0
pageIndex = bookPageInfo?.lastPage ?: 0
contentsName = bookPageInfo?.chapterTitle ?: ""
return this
}
}
class Bookmark() : RealmObject {
@PrimaryKey
var pageUrl : String = ""
}

View File

@ -0,0 +1,17 @@
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

@ -0,0 +1,55 @@
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.BookPageInfo
object DefaultList {
fun showDefaultList(context: Context, title : String, items : Collection<BookPageInfo>, 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

@ -0,0 +1,17 @@
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

@ -0,0 +1,97 @@
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

@ -0,0 +1,218 @@
package bums.lunatic.launcher.tokiz.view
import android.annotation.SuppressLint
import android.content.Context
import android.util.AttributeSet
import android.view.MotionEvent
import android.view.View
import androidx.core.view.isVisible
import bums.lunatic.launcher.tokiz.common.TouchArea
import bums.lunatic.launcher.tokiz.webcontents.contentsinfo.BooktokiStruct
import bums.lunatic.launcher.utils.Blog
import bums.lunatic.launcher.utils.SimpleFingerGestures
import org.mozilla.geckoview.GeckoView
enum class JxEvent {
SCROLL_UP,
SCROLL_DOWN,
SWIPE_LEFT,
SWIPE_RIGHT,
ON_CLICK,
}
typealias JxInteface = (JxEvent)->Unit
open class BWebview : GeckoView {
@SuppressLint("ClickableViewAccessibility")
constructor(context: Context?) : super(context) {
this.setOnTouchListener { v,e ->
if (e.device.name.contains("JX-12",true) == true) {
return@setOnTouchListener mSimpleFingerGestures.onTouch(v,e)
} else {
return@setOnTouchListener super.onTouchEvent(e)
}
}
}
@SuppressLint("ClickableViewAccessibility")
constructor(context: Context?, attrs: AttributeSet?) : super(context, attrs) {
this.setOnTouchListener { v,e ->
if (e.device.name.contains("JX-12",true) == true) {
return@setOnTouchListener mSimpleFingerGestures.onTouch(v,e)
} else {
return@setOnTouchListener super.onTouchEvent(e)
}
}
}
val mSimpleFingerGestures = SimpleFingerGestures(omfgl = object : SimpleFingerGestures.OnFingerGestureListener{
override fun onSwipeUp(
targetView: View,
fingers: Int,
gestureDuration: Long,
gestureDistance: Double
): Boolean {
Blog.LOGE("")
jxInteface?.invoke(JxEvent.SCROLL_UP )
return true
}
override fun onSwipeDown(
targetView: View,
fingers: Int,
gestureDuration: Long,
gestureDistance: Double
): Boolean {
Blog.LOGE("")
jxInteface?.invoke(JxEvent.SCROLL_DOWN)
return true
}
override fun onSwipeLeft(
targetView: View,
fingers: Int,
gestureDuration: Long,
gestureDistance: Double
): Boolean {
Blog.LOGE("")
jxInteface?.invoke(JxEvent.SWIPE_LEFT)
return true
}
override fun onSwipeRight(
targetView: View,
fingers: Int,
gestureDuration: Long,
gestureDistance: Double
): Boolean {
Blog.LOGE("")
jxInteface?.invoke(JxEvent.SWIPE_RIGHT)
return true
}
override fun onPinch(
targetView: View,
fingers: Int,
gestureDuration: Long,
gestureDistance: Double
): Boolean {
Blog.LOGE("onPinch")
return false
}
override fun onUnpinch(
targetView: View,
fingers: Int,
gestureDuration: Long,
gestureDistance: Double
): Boolean {
Blog.LOGE("")
return true
}
override fun onDoubleTap(
targetView: View,
fingers: Int
): Boolean {
Blog.LOGE("")
return true
}
override fun onLongPress(
targetView: View,
fingers: Int
): Boolean {
Blog.LOGE("onLongPress")
return false
}
override fun onClick(
targetView: View,
fingers: Int
): Boolean {
Blog.LOGE("onClick")
jxInteface?.invoke(JxEvent.ON_CLICK)
return false
}
})
companion object {
var currentRetryCount = 0
}
var jxInteface : JxInteface? = null
fun loadUrl(url: String) {
if (this.isVisible == false) {
this.visibility = View.VISIBLE
}
Blog.LOGE("url >>>> ${url}")
var nUrl = url
if (url.startsWith("http") == false) {
nUrl = BooktokiStruct.getLastedDoamin().plus(url)
}
nUrl?.let { url ->
if (url.split("//").size > 1) {
url.replace("//","/").replace("https:/","https://").let {
Blog.LOGE("url >> ${url} , it >>> ${it}")
this.session?.loadUri(it)
}
} else {
this.session?.loadUri(url)
}
}
currentRetryCount = 0;
}
private var lastX = 0f
private var lastY = 0f
override fun onTouchEvent(event: MotionEvent): Boolean {
Blog.LOGE("event.device.name >>> ${event.device.name}")
if (event.device.name.contains("JX-12", true)) {
Blog.LOGE("BWebview onTouchEvent $event")
when (event.action) {
MotionEvent.ACTION_DOWN -> {
lastX = event.x
lastY = event.y
return true
}
MotionEvent.ACTION_MOVE -> {
val deltaX = event.x - lastX
val deltaY = event.y - lastY
// 상하 이동이 더 크면(즉, 거의 수직 이동이면)만 처리
if (Math.abs(deltaY) > Math.abs(deltaX)) {
// 원하는 감도 적용
val scrollFactor = 0.1f
// scrollBy(0, (-deltaY * scrollFactor).toInt())
jxInteface?.invoke(if ((-deltaY * scrollFactor).toInt() > 0){
JxEvent.SCROLL_DOWN
} else {
JxEvent.SCROLL_UP
})
lastY = event.y
lastX = event.x
Blog.LOGE("return true for scroll")
return true
}
// 좌우 이동은 무시
lastY = event.y
lastX = event.x
Blog.LOGE("return false")
return false
}
else -> {
Blog.LOGE("call super")
return super.onTouchEvent(event)
}
}
} else {
return super.onTouchEvent(event)
}
}
}

View File

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

View File

@ -0,0 +1,316 @@
package bums.lunatic.launcher.tokiz.view
import android.annotation.TargetApi
import android.content.Context
import android.graphics.Color
import android.graphics.Typeface
import android.os.Build
import android.os.Handler
import android.util.AttributeSet
import android.view.View
import android.widget.TextView
import androidx.constraintlayout.widget.ConstraintLayout
import androidx.constraintlayout.widget.Guideline
import bums.lunatic.launcher.R
import bums.lunatic.launcher.tokiz.common.TouchArea
import bums.lunatic.launcher.utils.Blog
import bums.lunatic.launcher.utils.SimpleFingerGestures
class PagedTextLayout : ConstraintLayout , PagedTextGenerateInterface {
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)}
constructor(
context: Context,
attrs: AttributeSet?,
defStyleAttr: Int,
defStyleRes: Int
) : super(context, attrs, defStyleAttr, defStyleRes) {initView(context)}
var mainTextView : TextView? = null
var sencondTextView : TextView? = null
var demp : View? = null
var hiddenTextView : PagedTextView? = null
var guideLine : Guideline? = null
var pageList: ArrayList<CharSequence>? = null
var summaryText : String = ""
var text : String = ""
set(new) {
// Blog.LOGE("field >> ${field}")
// Blog.LOGE("new >> ${new}")
field = new
val summary = new.replace(" " ,"").replace("\n" ,"").substring(0,Math.min(30,new.length))
if (summary.equals(summaryText)) {
} else {
// Blog.LOGE("field >> ${field}")
hiddenTextView?.setTxtF(field)
hiddenTextView?.visibility = VISIBLE
}
summaryText = summary
}
private val hanler = Handler()
var mPagedTextViewInterface : PagedTextViewInterface? = null
val touchTimeover = Runnable {
mPagedTextViewInterface?.onTimeoverTouch()
}
var currentPageTextView : TextView? = null
fun initView(context: Context) {
inflate(context, R.layout.layout_textviewer, this)
mainTextView = findViewById(R.id.first_view)
sencondTextView = findViewById(R.id.sencond_view)
demp = findViewById(R.id.demp)
currentPageTextView = findViewById(R.id.current_page)
hiddenTextView = findViewById(R.id.hidden_view)
hiddenTextView?.mPagedTextGenerateInterface = this
currentPageTextView?.text = ""
hanler.removeCallbacks(touchTimeover)
setOnLongClickListener { v ->
mPagedTextViewInterface?.onLongClick()
return@setOnLongClickListener false
}
setOnTouchListener(SimpleFingerGestures(omfgl = object : SimpleFingerGestures.OnFingerGestureListener{
override fun onSwipeUp(
targetView: View,
fingers: Int,
gestureDuration: Long,
gestureDistance: Double
): Boolean {
mPagedTextViewInterface?.onSwipeUp(fingers)
return true
}
override fun onSwipeDown(
targetView: View,
fingers: Int,
gestureDuration: Long,
gestureDistance: Double
): Boolean {
mPagedTextViewInterface?.onSwipeDown(fingers)
return true
}
override fun onSwipeLeft(
targetView: View,
fingers: Int,
gestureDuration: Long,
gestureDistance: Double
): Boolean {
mPagedTextViewInterface?.onSwipeLeft(fingers)
return true
}
override fun onSwipeRight(
targetView: View,
fingers: Int,
gestureDuration: Long,
gestureDistance: Double
): Boolean {
mPagedTextViewInterface?.onSwipeRight(fingers)
return true
}
override fun onPinch(
targetView: View,
fingers: Int,
gestureDuration: Long,
gestureDistance: Double
): Boolean {
Blog.LOGE("onPinch")
return false
}
override fun onUnpinch(
targetView: View,
fingers: Int,
gestureDuration: Long,
gestureDistance: Double
): Boolean {
mPagedTextViewInterface?.onLongClick()
return true
}
override fun onDoubleTap(
targetView: View,
fingers: Int
): Boolean {
hanler.removeCallbacks(touchTimeover)
mPagedTextViewInterface?.onLongClick()
hanler?.postDelayed(touchTimeover, 3000L)
return true
}
override fun onLongPress(
targetView: View,
fingers: Int
): Boolean {
Blog.LOGE("onLongPress")
return false
}
override fun onClick(
targetView: View,
fingers: Int
): Boolean {
Blog.LOGE("onClick")
mPagedTextViewInterface?.onTouch(TouchArea.Center)
return false
}
}))
}
fun layoutChange(needDualPage: Boolean) {
Blog.LOGD(log = "layoutChange>> ${this::class.java.name}")
if (needDualPage) {
sencondTextView?.visibility = VISIBLE
demp?.visibility = VISIBLE
} else {
sencondTextView?.visibility = GONE
demp?.visibility = GONE
}
}
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) {
hiddenTextView?.text = text
forceUpdateUI()
}
}
override fun onSizeChanged(w: Int, h: Int, oldw: Int, oldh: Int) {
super.onSizeChanged(w, h, oldw, oldh)
Blog.LOGD(log = "onSizeChanged>> ${this::class.java.name}")
if (w != oldw || oldh != h) {
postDelayed(Runnable {
layoutChange(w > (h * 0.7f))
},20)
}else {
}
}
var currentPage = 0
override fun completePagination(pageList: ArrayList<CharSequence>) {
// Blog.LOGD(log = "completePagination>> ${this::class.java.name} >> pageList ${pageList}")
if(text.length > 0 && pageList!= null && pageList.size == 0) {
} else {
this.pageList = pageList
setPageBy(0)
}
hiddenTextView?.visibility = GONE
}
fun setColorStyle(colors : Array<String>) {
setBackgroundColor(Color.parseColor(colors.get(1)))
mainTextView?.setBackgroundColor(Color.parseColor(colors.get(1)))
sencondTextView?.setBackgroundColor(Color.parseColor(colors.get(1)))
mainTextView?.setTextColor(Color.parseColor(colors.get(0)))
sencondTextView?.setTextColor(Color.parseColor(colors.get(0)))
}
// fun setPagedTextViewInterface(pagedTextViewInterface: PagedTextViewInterface) = hiddenTextView?.setPagedTextViewInterface(pagedTextViewInterface)
// fun setText(replace: String) = hiddenTextView?.setText(replace)
fun setTextSize(fl: Float) {
hiddenTextView?.setTextSize(fl)
mainTextView?.setTextSize(fl)
sencondTextView?.setTextSize(fl)
}
fun next(page : Int) {
}
fun isDualPage() : Boolean {
return sencondTextView?.visibility == VISIBLE
}
fun setPageBy(num : Int) {
currentPage = num
var realPage = if(isDualPage()) currentPage * 2 else currentPage
Blog.LOGE("realPage = if(${pageList?.size} ?: 0 > ${realPage}) { realPage} else { ${(pageList?.size ?: 0) - 1 }}")
realPage = if(pageList?.size ?: 0 > realPage) { realPage} else { (pageList?.size ?: 0) - 1 }
currentPageTextView?.text = "${realPage + 1 }/${ pageList?.size ?: 0 + 1}"
mainTextView?.text = pageList?.get(realPage) ?: "NONE"
if(isDualPage()) {
realPage = realPage.inc()
sencondTextView?.text = if(pageList?.size ?: 0 > realPage) { pageList?.get(realPage)} else { ""}
} else {
sencondTextView?.text = ""
}
}
fun size(): Int = if(isDualPage()) Math.round((hiddenTextView?.size() ?:0) * 0.5f) else hiddenTextView?.size() ?: 0
fun getFastPageCount() = if(isDualPage()) 3 else 6
fun current(): Int = currentPage
fun doNext(fast : Boolean = false) {
if (fast) {
setPageBy(if((currentPage + getFastPageCount()) >= 0) {
currentPage + getFastPageCount()
} else {size()})
} else {
setPageBy(currentPage.inc())
}
}
fun doPrev(fast : Boolean = false) {
if (fast) {
setPageBy(if((currentPage - getFastPageCount()) >= 0) {
currentPage - getFastPageCount()
} else {0})
} else {
setPageBy(if(currentPage > 0 )currentPage.dec() else 0)
}
}
fun forceUpdateUI() {
hiddenTextView?.doUpdate()
}
override fun setPadding(left: Int, top: Int, right: Int, bottom: Int) {
hiddenTextView?.setPadding(left,top,right, bottom)
mainTextView?.setPadding(left,top,right, bottom)
sencondTextView?.setPadding(left,top,right, bottom)
}
fun setTypeface(tf: Typeface?) {
hiddenTextView?.setTypeface(tf)
mainTextView?.setTypeface(tf)
sencondTextView?.setTypeface(tf)
}
@TargetApi(Build.VERSION_CODES.LOLLIPOP)
fun setLetterSpacing(letterSpacing: Float) {
hiddenTextView?.letterSpacing = letterSpacing.times(0.01f)
mainTextView?.letterSpacing = letterSpacing.times(0.01f)
sencondTextView?.letterSpacing = letterSpacing.times(0.01f)
}
fun setLineSpacing(mult: Float) {
hiddenTextView?.setLineSpacing(1f, 1f.plus(mult.times(0.01f)))
mainTextView?.setLineSpacing(1f, 1f.plus(mult.times(0.01f)))
sencondTextView?.setLineSpacing(1f, 1f.plus(mult.times(0.01f)))
}
}

View File

@ -0,0 +1,263 @@
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 androidx.core.view.marginBottom
import androidx.core.view.marginLeft
import androidx.core.view.marginRight
import androidx.core.view.marginTop
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)
Blog.LOGD(log = "onSizeChanged>> ${this::class.java.name}")
pageHeight = ((h - (marginTop + marginBottom + paddingTop + paddingBottom)) * 1f).toInt()
}
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,
layout.alignment,
lineSpacingMultiplier,
lineSpacingExtra,
includeFontPadding
))
} else {
StaticLayout.Builder
.obtain(originalText, 0, originalText.length, paint, ((layout.width - (paddingLeft + paddingRight + marginLeft + marginRight) * 0.85f)).toInt())
.setAlignment(layout.alignment)
.setLineSpacing(lineSpacingExtra, lineSpacingMultiplier)
.setIncludePad(includeFontPadding)
.setUseLineSpacingFromFallbacks()
.setBreakStrategy(breakStrategy)
.setHyphenationFrequency(hyphenationFrequency)
// .setJustificationMode()
.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

@ -0,0 +1,13 @@
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

@ -0,0 +1,61 @@
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

@ -0,0 +1,75 @@
package bums.lunatic.launcher.tokiz.view
import android.content.Context
import android.util.AttributeSet
import android.widget.TextView
import androidx.appcompat.widget.AppCompatButton
import androidx.constraintlayout.widget.ConstraintLayout
import bums.lunatic.launcher.R
open class SideButtonTextView : ConstraintLayout {
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)
var leftButtonTitle : String = ""
set(value) {
field = value
btn_decrement?.text = field
}
var rightButtonTitle : String = ""
set(value) {
field = value
btn_increment?.text = field
}
open var value : Int = 14
set(newValue) {
field = newValue
text_value?.text = displayFormat.format(field)
mValueChange?.invoke(field)
}
var displayFormat = "글자 크기 : %d"
set(newValue) {
field = newValue
try {
text_value?.text = displayFormat.format(value)
} catch (e : Exception) {
}
}
var mValueChange : ValueChange? = null
set(newValue) {
field = newValue
if (newValue != null) {
newValue(value)
}
}
var btn_decrement : AppCompatButton? = null
var btn_increment : AppCompatButton? = null
var text_value : TextView? = null
init {
inflate(context, R.layout.layout_steps_editor,this)
btn_increment = findViewById(R.id.btn_increment)
btn_decrement = findViewById(R.id.btn_decrement)
text_value = findViewById(R.id.text_value)
btn_decrement?.setOnClickListener { value = value.dec() }
btn_increment?.setOnClickListener { value = value.inc() }
}
}

View File

@ -0,0 +1,31 @@
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

@ -0,0 +1,226 @@
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

@ -0,0 +1,416 @@
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

@ -0,0 +1,5 @@
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

@ -0,0 +1,22 @@
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

@ -0,0 +1,20 @@
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

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

View File

@ -0,0 +1,16 @@
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

@ -0,0 +1,20 @@
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

@ -36,17 +36,27 @@ object Blog {
LOG(BLogType.E,DEFAULT_TAG,log)
}
private fun LOG(type : BLogType, tag : String, log : String) {
inline fun LOG(type : BLogType, tag : String, log : String) {
val stackTrace = Thread.currentThread().stackTrace
val blogIndex = stackTrace.indexOfLast { it.className.contains("Blog") }
val callerInfo = if (blogIndex != -1 && blogIndex + 1 < stackTrace.size)
stackTrace[blogIndex + 1]
else null
val fileName = callerInfo?.fileName ?: "Unknown"
val className = callerInfo?.className ?: "Unknown"
val methodName = callerInfo?.methodName ?: "Unknown"
val lineNumber = callerInfo?.lineNumber ?: -1
if (BuildConfig.DEBUG || BuildConfig.BUILD_TYPE.contains("debug")) {
when(type) {
BLogType.D -> {
Log.d(tag,log)
Log.d(tag, ("${fileName}\n${className}\n${methodName} : ${lineNumber}\n" + log))
}
BLogType.I -> {
Log.i(tag,log)
Log.i(tag, ("${fileName}\n${className}\n${methodName} : ${lineNumber}\n" + log))
}
BLogType.E -> {
Log.e(tag,log)
Log.e(tag, ("${fileName}\n${className}\n${methodName} : ${lineNumber}\n" + log))
}
else -> {}
}

View File

@ -1,20 +1,14 @@
package bums.lunatic.launcher.view
import android.content.Context
import android.content.Intent
import android.net.Uri
import android.os.Handler
import android.os.Looper
import android.provider.AlarmClock
import android.text.SpannableString
import android.text.SpannableStringBuilder
import android.text.Spanned
import android.text.TextPaint
import android.text.method.LinkMovementMethod
import android.text.style.AbsoluteSizeSpan
import android.text.style.ClickableSpan
import android.util.AttributeSet
import android.view.View
import androidx.appcompat.widget.AppCompatTextView
import bums.lunatic.launcher.R
import bums.lunatic.launcher.helpers.PrefString

View File

@ -3,7 +3,6 @@ package bums.lunatic.launcher.view
import android.content.Context
import android.util.AttributeSet
import android.view.View
import android.view.View.OnClickListener
import android.view.ViewGroup
import android.widget.RadioButton
import android.widget.TableLayout

View File

@ -8,7 +8,6 @@ import android.content.pm.ResolveInfo
import android.os.Build
import androidx.work.WorkerParameters
import bums.lunatic.launcher.BuildConfig
import bums.lunatic.launcher.LauncherActivity
import bums.lunatic.launcher.LauncherActivity.Companion.lActivity
import bums.lunatic.launcher.apps.AppDrawer.Companion.appNamesPrefs
import bums.lunatic.launcher.model.AppInfo

View File

@ -4,13 +4,10 @@ import android.annotation.SuppressLint
import android.content.Context
import androidx.core.net.toUri
import androidx.work.WorkerParameters
import bums.lunatic.launcher.helpers.PrefHelper
import bums.lunatic.launcher.model.DcInside
import bums.lunatic.launcher.model.RssData
import bums.lunatic.launcher.model.RssDataInterface
import bums.lunatic.launcher.model.RssDataType
import bums.lunatic.launcher.model.getRssData
import bums.lunatic.launcher.utils.Blog
import org.jsoup.Jsoup
import java.text.SimpleDateFormat

View File

@ -6,7 +6,6 @@ import androidx.work.WorkerParameters
import bums.lunatic.launcher.model.FmKorea
import bums.lunatic.launcher.model.RssDataType
import bums.lunatic.launcher.model.getRssData
import bums.lunatic.launcher.utils.Blog
import org.jsoup.Jsoup
import java.util.Date

View File

@ -4,10 +4,8 @@ import android.annotation.SuppressLint
import android.content.Context
import android.location.Location
import androidx.work.WorkerParameters
import bums.lunatic.launcher.LauncherActivity.Companion.runWeatherGetter
import bums.lunatic.launcher.common.letTrue
import bums.lunatic.launcher.helpers.PrefBoolean
import bums.lunatic.launcher.utils.Blog
import bums.lunatic.launcher.workers.LocationUpdateService.Companion.pushLocation
import com.google.android.gms.location.LocationServices
import com.google.android.gms.location.Priority
@ -33,7 +31,7 @@ class LocationGetter(context: Context, workerParams: WorkerParameters) : BaseGet
// Blog.LOGE("Location >>> (latitude)${it.longitude}/(longitude)${it.latitude}")
longitude = it.longitude
latitude = it.latitude
runWeatherGetter()
// runWeatherGetter()
PrefBoolean.location.get().letTrue {
pushLocation(this.applicationContext,it.latitude, it.longitude)
}

View File

@ -11,7 +11,6 @@ import android.location.LocationManager
import android.os.Build
import android.os.IBinder
import android.widget.Toast
import bums.lunatic.launcher.LauncherActivity.Companion.runWeatherGetter
import bums.lunatic.launcher.common.letTrue
import bums.lunatic.launcher.helpers.PrefBoolean
import bums.lunatic.launcher.helpers.PrefLong
@ -141,7 +140,7 @@ class LocationUpdateService : Service(), LocationListener {
PrefBoolean.location.get().letTrue {
longitude = p0.longitude
latitude = p0.latitude
runWeatherGetter()
// runWeatherGetter()
pushLocation(this.applicationContext, p0.latitude,p0.longitude)
}
}
@ -173,7 +172,7 @@ class LocationUpdateService : Service(), LocationListener {
).show()
longitude = location.longitude
latitude = location.latitude
runWeatherGetter()
// runWeatherGetter()
pushLocation(this.applicationContext, location.latitude, location.longitude)
}
}

View File

@ -7,7 +7,6 @@ import androidx.work.WorkerParameters
import bums.lunatic.launcher.model.RssDataType
import bums.lunatic.launcher.model.RuliWeb
import bums.lunatic.launcher.model.getRssData
import bums.lunatic.launcher.utils.Blog
import org.jsoup.Jsoup
class RuliWebGetter : BaseGetter {

View File

@ -2,6 +2,11 @@ package bums.lunatic.launcher.workers
import bums.lunatic.launcher.BuildConfig
import bums.lunatic.launcher.apps.SimpleContact
import bums.lunatic.launcher.tokiz.data.model.BookPageInfo
import bums.lunatic.launcher.tokiz.data.model.BookPageInfos
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.common.letTrue
import bums.lunatic.launcher.model.AppInfo
import bums.lunatic.launcher.model.Astro
@ -18,13 +23,11 @@ import bums.lunatic.launcher.model.LocationLog
import bums.lunatic.launcher.model.NotificationItem
import bums.lunatic.launcher.model.RssData
import bums.lunatic.launcher.model.RssDataInterface
import bums.lunatic.launcher.model.RssDataType
import bums.lunatic.launcher.model.TelegramBotUpdate
import bums.lunatic.launcher.model.TelegramChat
import bums.lunatic.launcher.model.TelegramData
import bums.lunatic.launcher.model.TelegramFrom
import bums.lunatic.launcher.model.TelegramMessage
import bums.lunatic.launcher.model.UserActionModel
import bums.lunatic.launcher.model.WeatherForcast
import bums.lunatic.launcher.utils.Blog
import bums.lunatic.launcher.utils.JamoUtils
@ -63,11 +66,11 @@ object WorkersDb {
// this.query<UserActionModel>().query("weekOfYear == $0 OR weekOfMonth == $1 OR dayOfWeek == $2").limit()
}
}
val clazz : Set<KClass<out BaseRealmObject>> = setOf(RssData::class, NotificationItem::class, AppInfo::class,SimpleContact::class, RecentCall::class, RecentSms::class, CurrentPlayItem::class,
TelegramBotUpdate::class, TelegramData::class, TelegramMessage::class, TelegramChat::class, BotCommandEentitie::class, TelegramFrom::class,
WeatherForcast::class, Location::class, Current::class, Forecast::class, Condition::class, Forecastday::class, Day::class, Astro::class, Hour::class,
LocationLog::class
LocationLog::class,
LastInfo::class, HistoryItem::class, ReaderConfig::class, BookPageInfos::class, BookPageInfo::class
)
//,UserActionModel::class

View File

@ -0,0 +1,5 @@
<?xml version="1.0" encoding="utf-8"?>
<selector xmlns:android="http://schemas.android.com/apk/res/android">
<item android:color="@color/finestSilver" android:state_checked="true"></item>
<item android:color="@color/black" ></item>
</selector>

View File

@ -0,0 +1,9 @@
<vector xmlns:android="http://schemas.android.com/apk/res/android"
android:width="512dp"
android:height="512dp"
android:viewportWidth="24"
android:viewportHeight="24">
<path
android:fillColor="#FFFFFFFF"
android:pathData="M17.921,1.505a1.5,1.5 0,0 1,-0.44 1.06L9.809,10.237a2.5,2.5 0,0 0,0 3.536l7.662,7.662a1.5,1.5 0,0 1,-2.121 2.121L7.688,15.9a5.506,5.506 0,0 1,0 -7.779L15.36,0.444a1.5,1.5 0,0 1,2.561 1.061Z"/>
</vector>

View File

@ -0,0 +1,9 @@
<vector xmlns:android="http://schemas.android.com/apk/res/android"
android:width="512dp"
android:height="512dp"
android:viewportWidth="24"
android:viewportHeight="24">
<path
android:fillColor="#FFFFFFFF"
android:pathData="M6.079,22.5a1.5,1.5 0,0 1,0.44 -1.06l7.672,-7.672a2.5,2.5 0,0 0,0 -3.536L6.529,2.565A1.5,1.5 0,0 1,8.65 0.444l7.662,7.661a5.506,5.506 0,0 1,0 7.779L8.64,23.556A1.5,1.5 0,0 1,6.079 22.5Z"/>
</vector>

View File

@ -0,0 +1,9 @@
<vector xmlns:android="http://schemas.android.com/apk/res/android"
android:width="512dp"
android:height="512dp"
android:viewportWidth="24"
android:viewportHeight="24">
<path
android:fillColor="#FFFFFFFF"
android:pathData="M2.849,23.55a2.954,2.954 0,0 0,3.266 -0.644L12,17.053l5.885,5.853a2.956,2.956 0,0 0,2.1 0.881,3.05 3.05,0 0,0 1.17,-0.237A2.953,2.953 0,0 0,23 20.779V5a5.006,5.006 0,0 0,-5 -5H6A5.006,5.006 0,0 0,1 5V20.779A2.953,2.953 0,0 0,2.849 23.55Z"/>
</vector>

View File

@ -0,0 +1,27 @@
<?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:innerRadiusRatio="2.71"
android:thicknessRatio="7.6"
android:shape="ring"
android:useLevel="false"
android:type="sweep">
<solid android:color="#9E9E9E" />
</shape>
</item>
<item android:id="@android:id/progress">
<rotate
android:fromDegrees="270"
android:toDegrees="270">
<shape
android:innerRadiusRatio="2.71"
android:thicknessRatio="7.6"
android:shape="ring"
android:angle="0"
android:type="sweep">
</shape>
</rotate>
</item>
</layer-list>

Binary file not shown.

After

Width:  |  Height:  |  Size: 13 KiB

View File

@ -0,0 +1,15 @@
<vector xmlns:android="http://schemas.android.com/apk/res/android"
android:width="512dp"
android:height="512dp"
android:viewportWidth="512"
android:viewportHeight="512">
<path
android:fillColor="#FFFFFFFF"
android:pathData="M256,319.84c-35.35,0 -64,28.65 -64,64v128h128v-128C320,348.49 291.35,319.84 256,319.84z"/>
<path
android:fillColor="#FFFFFFFF"
android:pathData="M362.67,383.84v128H448c35.35,0 64,-28.65 64,-64V253.26c0,-11.08 -4.3,-21.73 -12.01,-29.7l-181.29,-195.99c-31.99,-34.61 -85.98,-36.74 -120.59,-4.75c-1.64,1.52 -3.23,3.1 -4.75,4.75L12.4,223.5C4.45,231.5 -0,242.31 0,253.58v194.26c0,35.35 28.65,64 64,64h85.33v-128c0.4,-58.17 47.37,-105.68 104.07,-107.04C312.01,275.38 362.22,323.7 362.67,383.84z"/>
<path
android:fillColor="#FFFFFFFF"
android:pathData="M256,319.84c-35.35,0 -64,28.65 -64,64v128h128v-128C320,348.49 291.35,319.84 256,319.84z"/>
</vector>

Binary file not shown.

After

Width:  |  Height:  |  Size: 7.5 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 7.5 KiB

View File

@ -0,0 +1,15 @@
<vector xmlns:android="http://schemas.android.com/apk/res/android"
android:width="512dp"
android:height="512dp"
android:viewportWidth="24"
android:viewportHeight="24">
<path
android:fillColor="#FFFFFFFF"
android:pathData="M22.713,4.077A2.993,2.993 0,0 0,20.41 3H4.242L4.2,2.649A3,3 0,0 0,1.222 0H1A1,1 0,0 0,1 2h0.222a1,1 0,0 1,0.993 0.883l1.376,11.7A5,5 0,0 0,8.557 19H19a1,1 0,0 0,0 -2H8.557a3,3 0,0 1,-2.82 -2h11.92a5,5 0,0 0,4.921 -4.113l0.785,-4.354A2.994,2.994 0,0 0,22.713 4.077Z"/>
<path
android:fillColor="#FFFFFFFF"
android:pathData="M7,22m-2,0a2,2 0,1 1,4 0a2,2 0,1 1,-4 0"/>
<path
android:fillColor="#FFFFFFFF"
android:pathData="M17,22m-2,0a2,2 0,1 1,4 0a2,2 0,1 1,-4 0"/>
</vector>

View File

@ -0,0 +1,9 @@
<vector xmlns:android="http://schemas.android.com/apk/res/android"
android:width="512dp"
android:height="512dp"
android:viewportWidth="512"
android:viewportHeight="512">
<path
android:fillColor="#FFFFFFFF"
android:pathData="M34.28,384c17.65,30.63 56.78,41.15 87.4,23.5c0.02,-0.01 0.04,-0.02 0.06,-0.04l9.49,-5.48c17.92,15.33 38.52,27.22 60.76,35.07V448c0,35.35 28.65,64 64,64s64,-28.65 64,-64v-10.94c22.24,-7.86 42.84,-19.77 60.76,-35.12l9.54,5.5c30.63,17.67 69.79,7.17 87.47,-23.47c17.67,-30.63 7.17,-69.79 -23.47,-87.47l0,0l-9.47,-5.46c4.26,-23.2 4.26,-46.99 0,-70.19l9.47,-5.46c30.63,-17.67 41.14,-56.83 23.47,-87.47c-17.67,-30.63 -56.83,-41.14 -87.47,-23.47l-9.49,5.48C362.86,94.64 342.25,82.77 320,74.94V64c0,-35.35 -28.65,-64 -64,-64s-64,28.65 -64,64v10.94c-22.24,7.86 -42.84,19.77 -60.76,35.12l-9.54,-5.53C91.07,86.86 51.91,97.37 34.24,128s-7.17,69.79 23.47,87.47l0,0l9.47,5.46c-4.26,23.2 -4.26,46.99 0,70.19l-9.47,5.46C27.16,314.3 16.69,353.38 34.28,384zM256,170.67c47.13,0 85.33,38.21 85.33,85.33S303.13,341.33 256,341.33S170.67,303.13 170.67,256S208.87,170.67 256,170.67z"/>
</vector>

View File

@ -0,0 +1,6 @@
<?xml version="1.0" encoding="utf-8"?>
<shape xmlns:android="http://schemas.android.com/apk/res/android" android:shape="rectangle">
<corners android:radius="10dp"/>
<solid android:color="#44ffffff"/>
<stroke android:color="@color/white" android:width="1dp"/>
</shape>

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Some files were not shown because too many files have changed in this diff Show More