This commit is contained in:
lunaticbum 2026-01-12 13:58:11 +09:00
parent f21f96f8a3
commit 6e7e9685ab
46 changed files with 3154 additions and 2775 deletions

View File

@ -92,9 +92,29 @@
tools:ignore="HardcodedDebugMode">
<activity
android:name=".home.NeoRssActivity"
android:theme="@style/Theme.LunarLauncher.Starting"
android:launchMode="singleInstance"
android:screenOrientation="userPortrait"
android:configChanges="orientation|keyboardHidden|keyboard|screenSize|smallestScreenSize|screenLayout|layoutDirection|navigation"
android:windowSoftInputMode="adjustResize"
android:exported="false">
<intent-filter>
<action android:name="android.intent.action.WEB_SEARCH"/>
<category android:name="android.intent.category.DEFAULT" />
</intent-filter>
<meta-data
android:name="android.app.searchable"
android:resource="@xml/searchable" />
<intent-filter>
<action android:name="android.intent.action.SEND" />
<category android:name="android.intent.category.DEFAULT" />
<data android:mimeType="*/*"/>
</intent-filter>
</activity>
<!-- android:excludeFromRecents="true"-->
<!-- portrait|reversePortrait|userPortrait|sensorPortrait-->
<activity
android:name=".LauncherActivity"
android:theme="@style/Theme.LunarLauncher.Starting"
@ -108,18 +128,7 @@
<category android:name="android.intent.category.HOME" />
<category android:name="android.intent.category.DEFAULT" />
</intent-filter>
<intent-filter>
<action android:name="android.intent.action.WEB_SEARCH"/>
<category android:name="android.intent.category.DEFAULT" />
</intent-filter>
<meta-data
android:name="android.app.searchable"
android:resource="@xml/searchable" />
<intent-filter>
<action android:name="android.intent.action.SEND" />
<category android:name="android.intent.category.DEFAULT" />
<data android:mimeType="*/*"/>
</intent-filter>
<intent-filter>
<action android:name="android.intent.action.MAIN"/>
<category android:name="android.intent.category.LAUNCHER" />
@ -172,7 +181,7 @@
<!-- </activity>-->
<activity
android:name=".tokiz.Settings"
android:name=".home.tokiz.Settings"
android:label="@string/lunar_settings"
android:launchMode="singleInstance"
android:excludeFromRecents="true"

View File

@ -42,7 +42,6 @@ import androidx.core.view.WindowCompat
import androidx.core.view.WindowInsetsCompat
import androidx.core.view.isVisible
import androidx.core.view.updatePadding
import bums.lunatic.launcher.LauncherActivity.Companion.lActivity
import bums.lunatic.launcher.apps.AppDrawerBottomSheet
import bums.lunatic.launcher.common.CommonActivity
import bums.lunatic.launcher.databinding.LauncherActivityBinding
@ -50,20 +49,10 @@ import bums.lunatic.launcher.feeds.WidgetHost
import bums.lunatic.launcher.helpers.ForeGroundService
import bums.lunatic.launcher.helpers.HeadsetActionButtonReceiver
import bums.lunatic.launcher.home.GeckoWeb
import bums.lunatic.launcher.home.NeoRssActivity
import bums.lunatic.launcher.home.RssHome
import bums.lunatic.launcher.home.adapters.BookmarkDetailFragment
import bums.lunatic.launcher.home.adapters.BookmarkPagerFragment
import bums.lunatic.launcher.model.RssData
import bums.lunatic.launcher.model.RssDataType
import bums.lunatic.launcher.model.WidgetData
import bums.lunatic.launcher.receiver.NLService
import bums.lunatic.launcher.settings.SettingsActivity
import bums.lunatic.launcher.tokiz.Comics
import bums.lunatic.launcher.tokiz.Magnet
import bums.lunatic.launcher.tokiz.Novels
import bums.lunatic.launcher.tokiz.Perplexity
import bums.lunatic.launcher.tokiz.Webtoons
import bums.lunatic.launcher.tokiz.YouTube
import bums.lunatic.launcher.utils.Blog
import bums.lunatic.launcher.workers.WorkersDb
import bums.lunatic.launcher.workers.WorkersDb.syncSystemUsageStats
@ -195,23 +184,16 @@ open class LauncherActivity : CommonActivity() {
}
fun onSwipeRight() {
showContents(R.id.feeds)
startActivity(Intent(this, NeoRssActivity::class.java))
}
private lateinit var binding: LauncherActivityBinding
companion object {
private var sRuntime: GeckoRuntime? = null
fun getRuntime() : GeckoRuntime? {
lActivity?.initGeckoRuntime()
return sRuntime
}
var sActivity : Activity? = null
var isOpendFold = false
val qDayPeriod = 60L * 8L
@JvmStatic var lActivity: LauncherActivity? = null
}
var hiddenLoader : HashMap<String,GeckoWeb> = hashMapOf()
@ -245,188 +227,7 @@ open class LauncherActivity : CommonActivity() {
var actionButtonPressY = 0f
var onExit = false
var lastAction = MotionEvent.ACTION_HOVER_EXIT
override fun dispatchKeyEvent(ev: KeyEvent): Boolean {
val currentFragment = supportFragmentManager.findFragmentById(R.id.fragment_container)
Blog.LOGE("dispatch ev?.device?.name >>> ${ev?.device?.name} , keyCode >> ${ev?.keyCode}")
if (ev?.device?.name?.contains("SM-031N Mouse") == true) {
when(ev.action) {
ACTION_UP -> {
Blog.LOGE("dispatch dispatchKeyEvent>>> ${ev}")
when(ev.keyCode) {
KEYCODE_BUTTON_Y->{
}
KEYCODE_BUTTON_X->{
}
KEYCODE_BUTTON_A->{
WorkersDb.getRealm().apply {
writeBlocking {
}
}
}
KEYCODE_BUTTON_B->{
}
KEYCODE_DPAD_DOWN->{
}
KEYCODE_DPAD_UP->{
}
KEYCODE_BUTTON_START->{
onClickCenterButton()
}
KEYCODE_BUTTON_SELECT->{
WorkersDb.getRealm().apply {
writeBlocking {
}
}
}
else -> {}
}
}
else->{}
}
return true
}
else {
val currentFragment = supportFragmentManager.findFragmentById(R.id.fragment_container)
when(currentFragment) {
is Novels -> {
if(MotionEvent.ACTION_UP.equals(ev?.action ?: MotionEvent.ACTION_CANCEL) == true) {
return when (ev.keyCode) {
KeyEvent.KEYCODE_VOLUME_DOWN -> {
if(currentFragment is Novels){ currentFragment.actionNextEvent() }
true
}
KeyEvent.KEYCODE_VOLUME_UP -> {
if(currentFragment is Novels){ currentFragment.actionPrevEvent() }
true
}
else -> false
}
} else {
return when (ev.keyCode) {
KeyEvent.KEYCODE_VOLUME_DOWN -> {
true
}
KeyEvent.KEYCODE_VOLUME_UP -> {
true
}
else -> false
}
}
}
else -> return super.dispatchKeyEvent(ev)
}
}
return super.dispatchKeyEvent(ev)
}
override fun dispatchTrackballEvent(event: MotionEvent?): Boolean {
Blog.LOGE("event >>> ${event?.device}")
return super.dispatchTrackballEvent(event)
}
@SuppressLint("RestrictedApi")
override fun dispatchKeyShortcutEvent(event: KeyEvent): Boolean {
Blog.LOGE("event >>> ${event.device}")
return super.dispatchKeyShortcutEvent(event)
}
fun onClickCenterButton() {
WorkersDb.getRealm().apply {
writeBlocking {
delete(
query<RssData>()
.query("pubDate < $0",
bums.lunatic.launcher.utils.beforeDay(28)
)
.query("vote != $0", true).apply {
Blog.LOGE("onClickCenterButton DELETE >> ${this.description()}")
}.find()
)
var ddd = copyFromRealm(WorkersDb.getRssQuery("", RssDataType.getExcAdt(),false).limit(100).query("read == $0", 0).query("vote != $0", true).apply {
Blog.LOGE("onClickCenterButton SELECT >> ${this.description()}")
}.find()).map { it.originPage() }
var origin = ddd.first()
var jjjj = hashSetOf<String>()
jjjj.addAll(ddd)
}
}
}
override fun dispatchGenericMotionEvent(ev: MotionEvent?): Boolean {
if (ev?.device?.name?.contains("BLE-M3") == true) {
Blog.LOGE("keyEvent >>>>> dispatchGenericMotionEvent ${ev}")
ev?.action?.let { action ->
when(action) {
MotionEvent.ACTION_HOVER_ENTER -> {
return false
}
MotionEvent.ACTION_HOVER_MOVE ->{
if(lastAction == MotionEvent.ACTION_HOVER_MOVE) {
Blog.LOGE("ACTION_HOVER_MOVE Click")
}
return false
}
MotionEvent.ACTION_BUTTON_PRESS ->{
if (actionButtonPressX * actionButtonPressY == 0f) {
actionButtonPressX = ev.x ?: 0f
actionButtonPressY = ev.y ?: 0f
}
// if (onExit) return true
return false
}
MotionEvent.ACTION_BUTTON_RELEASE -> {
if (actionButtonPressX == ev.x && actionButtonPressY == ev.y) {
// Blog.LOGE("DisplayUtil.width >>> ${DisplayUtil.width} ${actionButtonPressX}")
// Blog.LOGE("DisplayUtil.width >>> ${DisplayUtil.height} ${actionButtonPressY}")
if(actionButtonPressX.toInt() == 480 && actionButtonPressY < 2000) {
Blog.LOGE("Arrow Center Click")
onClickCenterButton()
} else if(ev.y > 2000) {
}
} else if (actionButtonPressY == ev.y) {
if (actionButtonPressX.minus(ev.x ?: 0f) > 0f) {
Blog.LOGE("Arrow Right Click")
} else {
Blog.LOGE("Arrow Left Click")
}
} else {
if (actionButtonPressY.minus(ev.y ?: 0f) > 0f) {
Blog.LOGE("Arrow Down Click")
} else {
Blog.LOGE("Arrow Up Click")
}
}
// if (onExit) return true
return false
}
MotionEvent.ACTION_HOVER_EXIT -> {
actionButtonPressX = 0f
actionButtonPressY = 0f
onExit = true
return false
}
else -> {return false}
}.apply {
lastAction = action
}
}
}
return super.dispatchGenericMotionEvent(ev)
}
fun floatClick(v : View) {
Blog.LOGE("v >>> ${v}")
showContents(v.id)
}
override fun onNewIntent(intent: Intent) {
Blog.LOGE("onNewIntent intent >> ${intent}")
@ -568,7 +369,7 @@ open class LauncherActivity : CommonActivity() {
val intent = Intent(this, ForeGroundService::class.java)
this.startForegroundService(intent)
// 1. 시스템 바 공간을 앱이 차지하도록 설정 (상태바 뒤로 레이아웃 확장)
WindowCompat.setDecorFitsSystemWindows(window, false)
// 2. 상태바 색상을 투명하게 변경 (필요한 경우)
@ -580,10 +381,10 @@ open class LauncherActivity : CommonActivity() {
this.startService(nlService)
getWindow().addFlags(WindowManager.LayoutParams.FLAG_SECURE);
lActivity = this
DynamicColors.applyToActivityIfAvailable(this)
binding = LauncherActivityBinding.inflate(layoutInflater)
setContentView(binding.root)
sActivity = this
homeGestureDetector = androidx.core.view.GestureDetectorCompat(this, HomeGestureListener())
binding.widgetContainer.setOnTouchListener { view, event ->
// 위젯 드래그 중이 아닐 때만 제스처 처리
@ -607,36 +408,13 @@ open class LauncherActivity : CommonActivity() {
updateLocationService()
// showContents(binding.feeds.id)
binding.floatingActionMenu.setOnTouchListener { v: View, e: MotionEvent ->
if (binding.floatingActionMenu.isOpened) {
binding.floatingActionMenu.close(true)
return@setOnTouchListener true
}
return@setOnTouchListener false
}
binding.floatingActionMenu.setOnMenuButtonClickListener { v->
Blog.LOGE("v >> ${v}")
showContents(v.id)
}
if (intent?.action == Intent.ACTION_WEB_SEARCH) {
openWithIntent(intent)
}
val nullCursor = PointerIcon.getSystemIcon(this, PointerIcon.TYPE_NULL)
binding.root.setPointerIcon(nullCursor)
binding.share.setOnClickListener {
if (binding.currentAddress.text.length > 5) {
val sendIntent: Intent = Intent().apply {
action = Intent.ACTION_SEND
(binding.currentAddress.tag as? String)?.let{putExtra(Intent.EXTRA_TITLE, it)}
putExtra(Intent.EXTRA_TEXT, binding.currentAddress.text)
type = "text/plain"
}
val shareIntent = Intent.createChooser(sendIntent, "링크 공유하기")
startActivity(shareIntent)
}
}
appWidgetManager = AppWidgetManager.getInstance(this)
appWidgetHost = WidgetHost(applicationContext, APPWIDGET_HOST_ID)
@ -675,6 +453,10 @@ open class LauncherActivity : CommonActivity() {
})
}
override fun onPause() {
super.onPause()
}
// 위젯 선택기 실행
fun selectWidget() {
val appWidgetId = appWidgetHost?.allocateAppWidgetId()
@ -897,83 +679,7 @@ open class LauncherActivity : CommonActivity() {
}
}
fun showContents(id : Int) {
binding.fragmentLayer.visibility = View.VISIBLE
binding.fragmentContainer.visibility = View.VISIBLE
binding.controllPanel.visibility = View.VISIBLE
binding.floatingActionMenu.visibility = View.VISIBLE
when(id) {
R.id.feeds -> {
supportFragmentManager.beginTransaction()
.replace(R.id.fragment_container, RssHome())
.commit()
}
R.id.books ->{
supportFragmentManager.beginTransaction()
.replace(R.id.fragment_container, Novels())
.commit()
}
R.id.webtoons ->{
supportFragmentManager.beginTransaction()
.replace(R.id.fragment_container, Webtoons())
.commit()
}
R.id.comics ->{
supportFragmentManager.beginTransaction()
.replace(R.id.fragment_container, Comics())
.commit()
}
R.id.youtube ->{
supportFragmentManager.beginTransaction()
.replace(R.id.fragment_container, YouTube())
.commit()
}
R.id.perplexity ->{
supportFragmentManager.beginTransaction()
.replace(R.id.fragment_container, Perplexity())
.commit()
}
R.id.zota ->{
supportFragmentManager.beginTransaction()
.replace(R.id.fragment_container, BookmarkPagerFragment())
.commit()
}
R.id.setting ->{
startActivity(Intent(this, SettingsActivity::class.java))
}
R.id.close ->{
supportFragmentManager.findFragmentById(R.id.fragment_container)?.let {
supportFragmentManager.beginTransaction()
.remove(it)
.commit()
binding.fragmentLayer.visibility = View.GONE
binding.fragmentContainer.visibility = View.GONE
binding.controllPanel.visibility = View.GONE
binding.floatingActionMenu.visibility = View.GONE
}
}
else -> {}
}
binding.floatingActionMenu.close(false)
}
private fun initGeckoRuntime() {
if (sRuntime == null) {
try {
sRuntime = GeckoRuntime.create(this, GeckoRuntimeSettings.Builder()
.extensionsProcessEnabled(true)
.extensionsWebAPIEnabled(true)
.experimentDelegate(experimentDelegate)
.debugLogging(false)
.remoteDebuggingEnabled(true).build())
} catch (e : Exception) {
e.printStackTrace()
}
}
}
override fun onTouchEvent(event: MotionEvent?): Boolean {
Blog.LOGE("event >>> ${event}")
@ -991,12 +697,7 @@ open class LauncherActivity : CommonActivity() {
}
override fun onDestroy() {
try {
sRuntime?.shutdown()
sRuntime = null
} catch (e: Exception) { e.printStackTrace() }
// appWidgetHost?.stopListening() // 이 줄은 제거하고 onStop으로 이동
super.onDestroy()
}
@ -1046,26 +747,7 @@ open class LauncherActivity : CommonActivity() {
private fun handleBackPress() {
onBackPressedDispatcher.addCallback(this, object : OnBackPressedCallback(true) {
override fun handleOnBackPressed() {
val currentFragment = supportFragmentManager.findFragmentById(R.id.fragment_container)
if (currentFragment == null) showContents(R.id.close)
when(currentFragment) {
is RssHome ->{
if (currentFragment.binding.layoutRssSummary.root.isVisible) {
currentFragment.openGecko(rssData = currentFragment.randomOrNull())
} else {
currentFragment.doNextPage()
}
}
is YouTube -> {
currentFragment.back()
}
is Novels -> {
currentFragment.actionNextEvent(false)
}
else -> {
showContents(R.id.close)
}
}
}
})
}

View File

@ -1,506 +1,421 @@
/*
* Lunar Launcher
* Copyright (C) 2022 Md Rasel Hossain
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package bums.lunatic.launcher.apps
import android.content.Context
import android.content.Intent
import android.content.SharedPreferences
import android.content.pm.PackageManager
import android.net.Uri
import android.os.Bundle
import android.os.Handler
import android.os.Looper
import android.view.KeyEvent
import android.view.View.GONE
import android.view.View.VISIBLE
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.Companion.lActivity
import bums.lunatic.launcher.common.CommonActivity
import bums.lunatic.launcher.common.letTrue
import bums.lunatic.launcher.databinding.AppDrawerBinding
import bums.lunatic.launcher.helpers.Constants.Companion.KEY_APPS_COUNT
import bums.lunatic.launcher.helpers.Constants.Companion.KEY_APPS_LAYOUT
import bums.lunatic.launcher.helpers.Constants.Companion.PREFS_APP_NAMES
import bums.lunatic.launcher.helpers.Constants.Companion.PREFS_SETTINGS
import bums.lunatic.launcher.helpers.PrefBoolean
import bums.lunatic.launcher.helpers.PrefLong
import bums.lunatic.launcher.helpers.PrefString
import bums.lunatic.launcher.model.AppInfo
import bums.lunatic.launcher.model.SimpleContact
import bums.lunatic.launcher.utils.Blog
import bums.lunatic.launcher.utils.JamoUtils
import bums.lunatic.launcher.workers.UsageLogType
import bums.lunatic.launcher.workers.UsageUpdateType
import bums.lunatic.launcher.workers.WorkersDb
import io.realm.kotlin.ext.query
import io.realm.kotlin.query.RealmResults
import io.realm.kotlin.query.Sort
import java.net.URLEncoder
import java.util.concurrent.Executors
import java.util.concurrent.TimeUnit
import java.util.regex.Pattern
class AppDrawer : CommonActivity() {
private lateinit var binding: AppDrawerBinding
private var layoutType: Int = 0
// private var isSearchShown: Boolean = false
private var isKeyboardShowing: Boolean = false
companion object {
private var appsAdapter: AppsAdapter? = null
private var contactAdapter : ContactAdapter? = null
private var packageList = mutableListOf<AppInfo>()
@JvmStatic var settingsPrefs: SharedPreferences? = null
@JvmStatic var appNamesPrefs: SharedPreferences? = null
}
fun getInputText() = binding.searchInput.text.toString()
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
// setStyle(STYLE_NO_TITLE, R.style.FilterFullScreenDialog)
// packageManager
///*
// * Lunar Launcher
// * Copyright (C) 2022 Md Rasel Hossain
// *
// * This program is free software: you can redistribute it and/or modify
// * it under the terms of the GNU General Public License as published by
// * the Free Software Foundation, either version 3 of the License, or
// * (at your option) any later version.
// *
// * This program is distributed in the hope that it will be useful,
// * but WITHOUT ANY WARRANTY; without even the implied warranty of
// * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// * GNU General Public License for more details.
// *
// * You should have received a copy of the GNU General Public License
// * along with this program. If not, see <http://www.gnu.org/licenses/>.
// */
//
//package bums.lunatic.launcher.apps
//
//import android.content.Context
//import android.content.Intent
//import android.content.SharedPreferences
//import android.content.pm.PackageManager
//import android.net.Uri
//import android.os.Bundle
//import android.os.Handler
//import android.os.Looper
//import android.view.KeyEvent
//import android.view.View.GONE
//import android.view.View.VISIBLE
//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.Companion.sActivity
//import bums.lunatic.launcher.common.CommonActivity
//import bums.lunatic.launcher.common.letTrue
//import bums.lunatic.launcher.databinding.AppDrawerBinding
//import bums.lunatic.launcher.helpers.Constants.Companion.KEY_APPS_COUNT
//import bums.lunatic.launcher.helpers.Constants.Companion.KEY_APPS_LAYOUT
//import bums.lunatic.launcher.helpers.Constants.Companion.PREFS_APP_NAMES
//import bums.lunatic.launcher.helpers.Constants.Companion.PREFS_SETTINGS
//import bums.lunatic.launcher.helpers.PrefBoolean
//import bums.lunatic.launcher.helpers.PrefLong
//import bums.lunatic.launcher.helpers.PrefString
//import bums.lunatic.launcher.model.AppInfo
//import bums.lunatic.launcher.model.SimpleContact
//import bums.lunatic.launcher.utils.Blog
//import bums.lunatic.launcher.utils.JamoUtils
//import bums.lunatic.launcher.workers.UsageLogType
//import bums.lunatic.launcher.workers.UsageUpdateType
//import bums.lunatic.launcher.workers.WorkersDb
//import io.realm.kotlin.ext.query
//import io.realm.kotlin.query.RealmResults
//import io.realm.kotlin.query.Sort
//import java.net.URLEncoder
//import java.util.concurrent.Executors
//import java.util.concurrent.TimeUnit
//import java.util.regex.Pattern
//
//
//class AppDrawer : CommonActivity() {
//
// private lateinit var binding: AppDrawerBinding
// private var layoutType: Int = 0
// // private var isSearchShown: Boolean = false
// private var isKeyboardShowing: Boolean = false
//
// companion object {
//
// private var appsAdapter: AppsAdapter? = null
// private var contactAdapter : ContactAdapter? = null
// private var packageList = mutableListOf<AppInfo>()
// @JvmStatic var settingsPrefs: SharedPreferences? = null
// @JvmStatic var appNamesPrefs: SharedPreferences? = null
//
//
//
//
// }
// override fun onAttach(context: Context) {
// super.onAttach(context)
// fun getInputText() = binding.searchInput.text.toString()
// override fun onCreate(savedInstanceState: Bundle?) {
// super.onCreate(savedInstanceState)
//// setStyle(STYLE_NO_TITLE, R.style.FilterFullScreenDialog)
//// packageManager
//// }
//
//// override fun onAttach(context: Context) {
//// super.onAttach(context)
////// }
////
////
////
//// override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View {
//
// binding = AppDrawerBinding.inflate(layoutInflater)
// setContentView(binding.root)
// settingsPrefs = this.getSharedPreferences(PREFS_SETTINGS, 0)
// appNamesPrefs = this.getSharedPreferences(PREFS_APP_NAMES, 0)
// layoutType = settingsPrefs!!.getInt(KEY_APPS_LAYOUT, 0)
//
// override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View {
binding = AppDrawerBinding.inflate(layoutInflater)
setContentView(binding.root)
settingsPrefs = this.getSharedPreferences(PREFS_SETTINGS, 0)
appNamesPrefs = this.getSharedPreferences(PREFS_APP_NAMES, 0)
layoutType = settingsPrefs!!.getInt(KEY_APPS_LAYOUT, 0)
appsAdapter = AppsAdapter(packageManager!!, supportFragmentManager, binding.appsCount)
contactAdapter = ContactAdapter(applicationContext, supportFragmentManager)
binding.appsCount.visibility = if (settingsPrefs!!.getBoolean(KEY_APPS_COUNT, true)) VISIBLE else GONE
binding.searchNmap.setOnClickListener {
openSearchApps("nmap://search?query=${getInputText()}&appname=${BuildConfig.APPLICATION_ID}","com.nhn.android.nmap")
}
binding.searchYoutube.setOnClickListener {
openSearchApps("https://www.youtube.com/results?search_query=${getInputText()}","com.google.android.youtube")
}
binding.searchGoogleMap.setOnClickListener {
openSearchApps("geo:0,0?q=${getInputText()}","com.google.android.apps.maps")
}
binding.searchGoogle.setOnClickListener {
openSearchApps("https://www.google.com/search?q=${getInputText()}","com.android.chrome")
}
binding.searchTmap.setOnClickListener {
openSearchApps("tmap://search?name=${getInputText()}","com.skt.tmap.ku")
}
binding.searchNaver.setOnClickListener {
openSearchApps("https://search.naver.com/search.naver?where=nexearch&query=${getInputText()}", "com.nhn.android.search")
}
binding.searchDuckduckgo.setOnClickListener {
openSearchApps("https://duckduckgo.com/?t=h_&q=${getInputText()}","com.duckduckgo.mobile.android")
}
binding.searchNamuwiki.setOnClickListener {
openSearchApps("https://namu.wiki/Search?q=${getInputText()}")
}
binding.searchTranslate.setOnClickListener {
openSearchApps("https://translate.google.com/?hl=ko&sl=ko&tl=en&text=${getInputText()}&op=translate","com.android.chrome")
}
binding.searchStore.setOnClickListener {
openSearchApps("market://search?q=${getInputText()}")
}
binding.runSend.setOnClickListener {
sendMsg()
}
binding.runTelegram.setOnClickListener {
sendMsg("tg://msg?text=${getInputText()}&to=${PrefString.telegramSendTarget.get()}","org.telegram.messenger")
}
binding.runKatalk.setOnClickListener {
sendMsg(pkg = "com.kakao.talk")
}
binding.runKatalkT.setOnClickListener{
openSearchApps("kakaot://taxi?dest_lat=${URLEncoder.encode("37.467696")}&dest_lng=${URLEncoder.encode("127.101063")}","com.kakao.taxi")
// openSearchApps("kakaot://taxi?${URLEncoder.encode("세곡동 557")}","com.kakao.taxi")
// openSearchApps("kakaot://taxi?dest_addr=${URLEncoder.encode("세곡동 557")}","com.kakao.taxi")
}
setLayout()
binding.searchInput.setOnKeyListener { v, keyCode, event ->
//contactList.size < 1 && packageList.size < 1 &&
if(PrefBoolean.useQuickLaunch.get(false) && keyCode == 66 && event.action == KeyEvent.ACTION_UP) {
checkResult(binding.searchInput.text.toString())
true
}else {
false
}
}
var packageManager = lActivity?.packageManager
binding.searchInput.setOnLongClickListener {
WorkersDb.getRealm().apply {
var newQ = query<AppInfo>()
appQuery = newQ.sort(Pair("clickCount", Sort.DESCENDING),Pair("lastUseDate",Sort.DESCENDING)).find()
appQuery?.let {
if(it.size > 0) {
WorkersDb.getRealm().apply {
packageList.clear()
writeBlocking {
it.filter {
var installed = isPackageInstalled(it.pkgName ?: "fffffffail", packageManager!!)
// it.isInstalled = installed
installed
}.let { result ->
packageList.addAll(copyFromRealm(result))
binding.appsList.post { if (result.size > 0) {
appsAdapter?.updateData(packageList)
}}
}
}
}
}
}
}
WorkersDb.getRealm().apply {
var newQ = query<SimpleContact>()
contactQuery = newQ.sort(Pair("touchCount", Sort.DESCENDING),Pair("lastedTouchDateTime",Sort.DESCENDING)).find()
contactQuery?.let {
if (it.size > 0) {
contactList.clear()
contactList.addAll(copyFromRealm(it).toList())
binding.contactList.post {
if (contactList.size > 0) {
contactAdapter?.updateData(contactList)
}
}
}
}
}
true
}
binding.searchInput.doOnTextChanged{ inputText, _, _, _ ->
binding.searchInput.text?.let { binding.searchInput.setSelection(it.length) }
filterAppsList(inputText.toString())
}
// return binding.root
}
fun isPackageInstalled( packageName : String, packageManager : PackageManager?) : Boolean{
try {
packageManager!!.getPackageInfo(packageName, 0)
return true;
} catch ( e : Exception) {
return false;
}
}
fun sendMsg(scheme : String? = null , pkg : String? = null) {
var postIntent : Intent? = null
if (scheme != null && scheme.length > 1) {
postIntent = Intent(Intent.ACTION_VIEW,Uri.parse(scheme))
} else {
postIntent = Intent(Intent.ACTION_SEND)
postIntent.type = "text/plain"
postIntent.putExtra(Intent.EXTRA_TEXT, "${getInputText()}")
}
if (pkg != null && pkg.length > 1) {
postIntent?.setPackage(pkg)
startActivity(postIntent)
} else {
val chooserTitle = "바로 보냄"
startActivity(Intent.createChooser(postIntent, chooserTitle))
}
}
val appNames = hashSetOf<AppInfo>()
val contactList = arrayListOf<SimpleContact>()
fun openSearchApps(schemeString : String, pakage : String? = null) {
val gmmIntentUri = Uri.parse(schemeString)
val mapIntent = Intent(Intent.ACTION_VIEW, gmmIntentUri)
pakage?.let {
mapIntent.setPackage(pakage)
WorkersDb.logAppUsage(pakage, UsageLogType.APP, UsageUpdateType.DATETIME)
}
startActivity(mapIntent)
}
fun checkResult(keyword: String) {
openSearchMenus(keyword) {
registCancelSearch()
}
}
fun runonUi(invoke : () -> Unit) {
Handler(Looper.getMainLooper()).run {
try {
invoke.invoke()
}catch (e : Exception) {
e.printStackTrace()
}
}
}
override fun onResume() {
super.onResume()
Blog.LOGE("onResume")
fetchApps()
binding.appsCount.visibility = if (PrefBoolean.showAppResultCount.get(false)) VISIBLE else GONE
PrefBoolean.openWithKayboard.get().letTrue { openSearch() }
registCancelSearch()
}
val chechHandler = Handler(Looper.getMainLooper())
val cancelSearch = Runnable {
finish()
}
fun registCancelSearch() {
chechHandler.removeCallbacks(cancelSearch)
chechHandler.postDelayed(cancelSearch, 15000L)
}
fun clearCancelSearch() {
chechHandler.removeCallbacks(cancelSearch)
}
override fun onPause() {
super.onPause()
closeSearch()
}
private fun setLayout() {
binding.appsList.layoutManager = GridLayoutManager(this, 2, GridLayoutManager.HORIZONTAL,false)
binding.contactList.layoutManager = GridLayoutManager(this, 2, GridLayoutManager.HORIZONTAL,false)
/* initialize apps list adapter */
binding.appsList.adapter = appsAdapter
binding.contactList.adapter = contactAdapter
}
var appQuery : RealmResults<AppInfo>? = null
fun fetchApps(keyword : String? = null) {
WorkersDb.getRealm().apply {
var newQ = query<AppInfo>()
if (keyword != null && keyword.length > 0) {
if (JamoUtils.CHOSUNG.contains(keyword.split("")[0])) {
newQ = newQ.query("appName CONTAINS $0 OR appNameChosung CONTAINS $0 OR koreanName CONTAINS $0 OR alphaCho CONTAINS $0 OR category CONTAINS $0", keyword)
} else if(Pattern.matches("^[가-힣]*\$", keyword)){
newQ = newQ.query("appName CONTAINS $0 OR koreanName CONTAINS $0 OR category CONTAINS $0", keyword)
}else {
keyword.split("").forEach {
if (it.length > 0) {
newQ = newQ.query(
"appName CONTAINS $0 OR category CONTAINS $0 OR pkgName CONTAINS $0 OR appName CONTAINS $1 OR category CONTAINS $1 OR pkgName CONTAINS $1",
keyword.lowercase(),
keyword.uppercase()
)
}
}
}
}
appQuery = newQ.sort(Pair("clickCount", Sort.DESCENDING),Pair("lastUseDate",Sort.DESCENDING))
.limit(PrefLong.maxQueryCount.get(18L).toInt()).find()
appQuery?.let {
if(it.size > 0) {
WorkersDb.getRealm().apply {
packageList.clear()
writeBlocking {
it.filter {
var installed = isPackageInstalled(it.pkgName ?: "fffffffail", packageManager!!)
// it.isInstalled = installed
installed
}.let { result ->
packageList.addAll(copyFromRealm(result))
binding.appsList.post { if (result.size > 0) {
appsAdapter?.updateData(packageList)
}}
}
}
}
}
}
}
fetcContact(keyword)
}
var contactQuery : RealmResults<SimpleContact>? = null
fun fetcContact(keyword : String? = null) {
WorkersDb.getRealm().apply {
var newQ = query<SimpleContact>()
if (keyword != null && keyword.length > 0) {
if(Pattern.matches("^[0-9]*\$", keyword)){
keyword.split("").forEach { if (it.length > 0) newQ = newQ.query("phoneNumber CONTAINS $0", keyword) }
} else {
newQ = newQ.query("name CONTAINS $0 OR chosung CONTAINS $0", keyword)
}
}
contactQuery = newQ.sort(Pair("touchCount", Sort.DESCENDING),Pair("lastedTouchDateTime",Sort.DESCENDING))
.limit(PrefLong.maxQueryCount.get(18L).toInt()).find()
contactQuery?.let {
if (it.size > 0)
WorkersDb.getRealm().apply {
contactList.clear()
contactList.addAll(copyFromRealm(it).toList())
binding.contactList.post { if (contactList.size > 0) {
contactAdapter?.updateData(contactList)
} }
}
}
}
}
fun getHangule() {
Blog.LOGE("on getHangule")
Executors.newSingleThreadScheduledExecutor().schedule({
if (appNames.size > 0) {
val info = appNames.first()
appNames.remove(info)
if (info.koreanName?.length ?: 0 > 0 || info.appNameChosung?.length ?: 0 > 0) {
getHangule()
} else {
Blog.LOGE("on getHangule ${info.appName}")
if (Pattern.matches("^[a-zA-Z]*$", info.appName)) {
// Jsoup.connect("https://translate.google.com/?hl=ko&sl=en&tl=ko&text=${info.appName}&op=translate").get().let { trans ->
// BLog.LOGE("on getHangule ${trans.title()}")
// trans.getElementsByTag("span").forEach {
// BLog.LOGE("on getHangule ${it.text()}")
// if(it.hasAttr("jsaction") &&
// it.attr("jsaction").contains("mouseout") &&
// it.attr("jsaction").contains("contextmenu") &&
// it.attr("jsaction").contains("mouseover")
// ) {
// BLog.LOGE("on getHangule $it")
// appsAdapter = AppsAdapter(packageManager!!, supportFragmentManager, binding.appsCount)
// contactAdapter = ContactAdapter(applicationContext, supportFragmentManager)
//
// binding.appsCount.visibility = if (settingsPrefs!!.getBoolean(KEY_APPS_COUNT, true)) VISIBLE else GONE
// binding.searchNmap.setOnClickListener {
// openSearchApps("nmap://search?query=${getInputText()}&appname=${BuildConfig.APPLICATION_ID}","com.nhn.android.nmap")
// }
// binding.searchYoutube.setOnClickListener {
// openSearchApps("https://www.youtube.com/results?search_query=${getInputText()}","com.google.android.youtube")
// }
// binding.searchGoogleMap.setOnClickListener {
// openSearchApps("geo:0,0?q=${getInputText()}","com.google.android.apps.maps")
// }
// binding.searchGoogle.setOnClickListener {
// openSearchApps("https://www.google.com/search?q=${getInputText()}","com.android.chrome")
// }
// binding.searchTmap.setOnClickListener {
// openSearchApps("tmap://search?name=${getInputText()}","com.skt.tmap.ku")
//
// }
// binding.searchNaver.setOnClickListener {
// openSearchApps("https://search.naver.com/search.naver?where=nexearch&query=${getInputText()}", "com.nhn.android.search")
// }
// binding.searchDuckduckgo.setOnClickListener {
// openSearchApps("https://duckduckgo.com/?t=h_&q=${getInputText()}","com.duckduckgo.mobile.android")
// }
// binding.searchNamuwiki.setOnClickListener {
// openSearchApps("https://namu.wiki/Search?q=${getInputText()}")
// }
//
// binding.searchTranslate.setOnClickListener {
// openSearchApps("https://translate.google.com/?hl=ko&sl=ko&tl=en&text=${getInputText()}&op=translate","com.android.chrome")
// }
// binding.searchStore.setOnClickListener {
// openSearchApps("market://search?q=${getInputText()}")
// }
// binding.runSend.setOnClickListener {
// sendMsg()
// }
// binding.runTelegram.setOnClickListener {
// sendMsg("tg://msg?text=${getInputText()}&to=${PrefString.telegramSendTarget.get()}","org.telegram.messenger")
// }
// binding.runKatalk.setOnClickListener {
// sendMsg(pkg = "com.kakao.talk")
// }
//
// binding.runKatalkT.setOnClickListener{
// openSearchApps("kakaot://taxi?dest_lat=${URLEncoder.encode("37.467696")}&dest_lng=${URLEncoder.encode("127.101063")}","com.kakao.taxi")
//// openSearchApps("kakaot://taxi?${URLEncoder.encode("세곡동 557")}","com.kakao.taxi")
//// openSearchApps("kakaot://taxi?dest_addr=${URLEncoder.encode("세곡동 557")}","com.kakao.taxi")
// }
// setLayout()
// binding.searchInput.setOnKeyListener { v, keyCode, event ->
// //contactList.size < 1 && packageList.size < 1 &&
// if(PrefBoolean.useQuickLaunch.get(false) && keyCode == 66 && event.action == KeyEvent.ACTION_UP) {
// checkResult(binding.searchInput.text.toString())
// true
// }else {
// false
// }
// }
// var packageManager = sActivity?.packageManager
//
// binding.searchInput.setOnLongClickListener {
// WorkersDb.getRealm().apply {
// var newQ = query<AppInfo>()
// appQuery = newQ.sort(Pair("clickCount", Sort.DESCENDING),Pair("lastUseDate",Sort.DESCENDING)).find()
// appQuery?.let {
// if(it.size > 0) {
// WorkersDb.getRealm().apply {
// packageList.clear()
// writeBlocking {
// it.filter {
// var installed = isPackageInstalled(it.pkgName ?: "fffffffail", packageManager!!)
//// it.isInstalled = installed
// installed
// }.let { result ->
// packageList.addAll(copyFromRealm(result))
// binding.appsList.post { if (result.size > 0) {
// appsAdapter?.updateData(packageList)
// }}
// }
// }
//
// }.apply {
// getHangule()
// }
// Handler(Looper.getMainLooper()).post {
// LauncherActivity.Companion.lActivity?.doWebParseStart(
// "https://translate.google.com/?hl=ko&sl=en&tl=ko&text=${info.appName}&op=translate",
// object : CommadCallabck {
// override fun onConsoleLog(log: String) {
// if (log.contains("result::")) {
// val appHangulName = log.split("result::")[1]
// if(appHangulName?.length ?: 0 > 0) {
// info.appNameChosung = JamoUtils.split(appHangulName).joinToString("")
// info.koreanName = appHangulName
//// BLog.LOGE("appHangulName >>> $appHangulName")
//// BLog.LOGE("appHangulName >>> ${info.appNameChosung}")
// WorkersDb.update(info)
// getHangule()
// }
// }
// }
//
// override fun collectComplete() {
// getHangule()
// }
// })
// }
} else {
info.appNameChosung = JamoUtils.split(info.appName).joinToString("")
info.koreanName = info.appName
WorkersDb.update(info)
getHangule()
Blog.LOGE("on getHangule to next")
}
}
}
},5,TimeUnit.SECONDS)
}
private fun getAlphabetItems() {
// settingsPrefs!!.getInt(KEY_SCROLLBAR_HEIGHT, DEFAULT_SCROLLBAR_HEIGHT).let { height: Int ->
// if (height == 0) { binding.alphabets.visibility = GONE }
// else {
// binding.alphabets.apply {
// if (visibility == GONE) visibility = VISIBLE
// updateLayoutParams { this.height = height }
// }
// alphabetList.clear()
// for (mPackage in packageList) {
// mPackage.appName.first().uppercase().let { firstLetter: String ->
// when {
// numberPattern.matcher(firstLetter).matches() -> alphabetList.add(0, "#")
// alphabetPattern.matcher(firstLetter).matches() -> alphabetList.add(firstLetter)
// !numberPattern.matcher(firstLetter).matches() &&
// !alphabetPattern.matcher(firstLetter).matches() -> alphabetList.add(alphabetList.size,"⠶")
// else -> {}
// }
// }
// }
// binding.alphabets.invalidate()
// }
// WorkersDb.getRealm().apply {
// var newQ = query<SimpleContact>()
// contactQuery = newQ.sort(Pair("touchCount", Sort.DESCENDING),Pair("lastedTouchDateTime",Sort.DESCENDING)).find()
// contactQuery?.let {
// if (it.size > 0) {
// contactList.clear()
// contactList.addAll(copyFromRealm(it).toList())
// binding.contactList.post {
// if (contactList.size > 0) {
// contactAdapter?.updateData(contactList)
// }
// }
// }
// }
//
// }
// true
// }
// binding.searchInput.doOnTextChanged{ inputText, _, _, _ ->
// binding.searchInput.text?.let { binding.searchInput.setSelection(it.length) }
// filterAppsList(inputText.toString())
// }
//// return binding.root
// }
// fun isPackageInstalled( packageName : String, packageManager : PackageManager?) : Boolean{
// try {
// packageManager!!.getPackageInfo(packageName, 0)
// return true;
// } catch ( e : Exception) {
// return false;
// }
// }
//
// fun sendMsg(scheme : String? = null , pkg : String? = null) {
// var postIntent : Intent? = null
// if (scheme != null && scheme.length > 1) {
// postIntent = Intent(Intent.ACTION_VIEW,Uri.parse(scheme))
// } else {
// postIntent = Intent(Intent.ACTION_SEND)
// postIntent.type = "text/plain"
// postIntent.putExtra(Intent.EXTRA_TEXT, "${getInputText()}")
// }
// if (pkg != null && pkg.length > 1) {
// postIntent?.setPackage(pkg)
// startActivity(postIntent)
// } else {
// val chooserTitle = "바로 보냄"
// startActivity(Intent.createChooser(postIntent, chooserTitle))
// }
// }
//
// val appNames = hashSetOf<AppInfo>()
// val contactList = arrayListOf<SimpleContact>()
//
// fun openSearchApps(schemeString : String, pakage : String? = null) {
// val gmmIntentUri = Uri.parse(schemeString)
// val mapIntent = Intent(Intent.ACTION_VIEW, gmmIntentUri)
// pakage?.let {
// mapIntent.setPackage(pakage)
// WorkersDb.logAppUsage(pakage, UsageLogType.APP, UsageUpdateType.DATETIME)
// }
// startActivity(mapIntent)
// }
//
//
// fun checkResult(keyword: String) {
// openSearchMenus(keyword) {
// registCancelSearch()
// }
// }
//
//
//
// fun runonUi(invoke : () -> Unit) {
// Handler(Looper.getMainLooper()).run {
// try {
// invoke.invoke()
// }catch (e : Exception) {
// e.printStackTrace()
// }
// }
}
private fun filterAppsList(searchString: String) {
fetchApps(searchString)
registCancelSearch()
}
fun openSearch() {
try {
binding.searchInput.apply {
visibility = VISIBLE
requestFocus()
let {
(getSystemService(Context.INPUT_METHOD_SERVICE) as? InputMethodManager)?.showSoftInput(
it,
InputMethodManager.SHOW_IMPLICIT
)
}
}
} catch (e : UninitializedPropertyAccessException) {
}
}
/* clear search string, hide keyboard and search box */
private fun closeSearch() {
binding.searchInput.apply {
let {
text?.clear()
(getSystemService(Context.INPUT_METHOD_SERVICE) as? InputMethodManager)?.hideSoftInputFromWindow(it.windowToken, 0)
}
}
}
}
// }
//
//
// override fun onResume() {
// super.onResume()
// Blog.LOGE("onResume")
// fetchApps()
//
// binding.appsCount.visibility = if (PrefBoolean.showAppResultCount.get(false)) VISIBLE else GONE
//
// PrefBoolean.openWithKayboard.get().letTrue { openSearch() }
// registCancelSearch()
// }
//
// val chechHandler = Handler(Looper.getMainLooper())
//
// val cancelSearch = Runnable {
// finish()
// }
//
// fun registCancelSearch() {
// chechHandler.removeCallbacks(cancelSearch)
// chechHandler.postDelayed(cancelSearch, 15000L)
// }
//
// fun clearCancelSearch() {
// chechHandler.removeCallbacks(cancelSearch)
// }
//
// override fun onPause() {
// super.onPause()
// closeSearch()
// }
//
// private fun setLayout() {
// binding.appsList.layoutManager = GridLayoutManager(this, 2, GridLayoutManager.HORIZONTAL,false)
// binding.contactList.layoutManager = GridLayoutManager(this, 2, GridLayoutManager.HORIZONTAL,false)
// /* initialize apps list adapter */
// binding.appsList.adapter = appsAdapter
// binding.contactList.adapter = contactAdapter
// }
// var appQuery : RealmResults<AppInfo>? = null
// fun fetchApps(keyword : String? = null) {
// WorkersDb.getRealm().apply {
// var newQ = query<AppInfo>()
// if (keyword != null && keyword.length > 0) {
// if (JamoUtils.CHOSUNG.contains(keyword.split("")[0])) {
// newQ = newQ.query("appName CONTAINS $0 OR appNameChosung CONTAINS $0 OR koreanName CONTAINS $0 OR alphaCho CONTAINS $0 OR category CONTAINS $0", keyword)
// } else if(Pattern.matches("^[가-힣]*\$", keyword)){
// newQ = newQ.query("appName CONTAINS $0 OR koreanName CONTAINS $0 OR category CONTAINS $0", keyword)
// }else {
// keyword.split("").forEach {
// if (it.length > 0) {
// newQ = newQ.query(
// "appName CONTAINS $0 OR category CONTAINS $0 OR pkgName CONTAINS $0 OR appName CONTAINS $1 OR category CONTAINS $1 OR pkgName CONTAINS $1",
// keyword.lowercase(),
// keyword.uppercase()
// )
// }
// }
// }
// }
// appQuery = newQ.sort(Pair("clickCount", Sort.DESCENDING),Pair("lastUseDate",Sort.DESCENDING))
// .limit(PrefLong.maxQueryCount.get(18L).toInt()).find()
// appQuery?.let {
// if(it.size > 0) {
// WorkersDb.getRealm().apply {
// packageList.clear()
// writeBlocking {
// it.filter {
// var installed = isPackageInstalled(it.pkgName ?: "fffffffail", packageManager!!)
//// it.isInstalled = installed
// installed
// }.let { result ->
// packageList.addAll(copyFromRealm(result))
// binding.appsList.post { if (result.size > 0) {
// appsAdapter?.updateData(packageList)
// }}
// }
// }
// }
// }
// }
// }
// fetcContact(keyword)
// }
//
//
// var contactQuery : RealmResults<SimpleContact>? = null
// fun fetcContact(keyword : String? = null) {
// WorkersDb.getRealm().apply {
// var newQ = query<SimpleContact>()
// if (keyword != null && keyword.length > 0) {
// if(Pattern.matches("^[0-9]*\$", keyword)){
// keyword.split("").forEach { if (it.length > 0) newQ = newQ.query("phoneNumber CONTAINS $0", keyword) }
// } else {
// newQ = newQ.query("name CONTAINS $0 OR chosung CONTAINS $0", keyword)
// }
// }
// contactQuery = newQ.sort(Pair("touchCount", Sort.DESCENDING),Pair("lastedTouchDateTime",Sort.DESCENDING))
// .limit(PrefLong.maxQueryCount.get(18L).toInt()).find()
// contactQuery?.let {
// if (it.size > 0)
// WorkersDb.getRealm().apply {
// contactList.clear()
// contactList.addAll(copyFromRealm(it).toList())
// binding.contactList.post { if (contactList.size > 0) {
// contactAdapter?.updateData(contactList)
// } }
// }
// }
// }
// }
//
//
//
//
// private fun filterAppsList(searchString: String) {
// fetchApps(searchString)
// registCancelSearch()
// }
//
// fun openSearch() {
// try {
// binding.searchInput.apply {
// visibility = VISIBLE
// requestFocus()
// let {
// (getSystemService(Context.INPUT_METHOD_SERVICE) as? InputMethodManager)?.showSoftInput(
// it,
// InputMethodManager.SHOW_IMPLICIT
// )
// }
// }
// } catch (e : UninitializedPropertyAccessException) {
//
// }
// }
//
// /* clear search string, hide keyboard and search box */
// private fun closeSearch() {
// binding.searchInput.apply {
// let {
// text?.clear()
// (getSystemService(Context.INPUT_METHOD_SERVICE) as? InputMethodManager)?.hideSoftInputFromWindow(it.windowToken, 0)
// }
// }
// }
//
//}
//

View File

@ -37,6 +37,7 @@ import io.realm.kotlin.query.Sort
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.launch
import kotlinx.coroutines.withContext
import java.net.URLEncoder
class AppDrawerBottomSheet : BottomSheetDialogFragment() {
@ -176,29 +177,74 @@ class AppDrawerBottomSheet : BottomSheetDialogFragment() {
}
}
val keyword : String
get() {
return binding.searchInput.text.toString()
}
private fun setupSearchButtons() {
// 기존 AppDrawer의 버튼 연결
binding.searchNmap.setOnClickListener {
openSearchApps("nmap://search?query=${getInputText()}&appname=${BuildConfig.APPLICATION_ID}", "com.nhn.android.nmap")
openSearchApps("nmap://search?query=${keyword}&appname=${BuildConfig.APPLICATION_ID}", "com.nhn.android.nmap")
}
binding.searchYoutube.setOnClickListener {
openSearchApps("https://www.youtube.com/results?search_query=${getInputText()}", "com.google.android.youtube")
openSearchApps("https://www.youtube.com/results?search_query=${keyword}", "com.google.android.youtube")
}
binding.hidden.setOnClickListener {
binding.hidden.isSelected = !binding.hidden.isSelected
Blog.LOGE("binding.hidden.isSelected >>> ${binding.hidden.isSelected}")
filterAppsList(keyword)
}
binding.searchTaxi.setOnClickListener {
openSearchApps("kakaot://taxi?goalx=${URLEncoder.encode("37.467696")}&goaly=${URLEncoder.encode("127.101063")}","com.kakao.taxi")
}
binding.searchMusic.setOnClickListener {
try {
// 스포티파이는 별도의 URL 인코딩 없이도 잘 동작하지만, 안전하게 인코딩 추천
val encodedKeyword = URLEncoder.encode(keyword, "UTF-8")
val uri = Uri.parse("spotify:search:$encodedKeyword")
val intent = Intent(Intent.ACTION_VIEW, uri)
// 명시적으로 스포티파이 앱 지정 (웹 브라우저로 빠지는 것 방지)
intent.flags = Intent.FLAG_ACTIVITY_NEW_TASK or Intent.FLAG_ACTIVITY_CLEAR_TOP
requireContext().startActivity(intent)
} catch (e: Exception) {
// 앱이 없을 경우 플레이스토어로 이동
val marketIntent = Intent(Intent.ACTION_VIEW, Uri.parse("market://details?id=com.spotify.music"))
marketIntent.flags = Intent.FLAG_ACTIVITY_NEW_TASK
requireContext().startActivity(marketIntent)
}
}
binding.searchTmap.setOnClickListener {
try {
// 한글 검색어를 위해 URL 인코딩 필수
val encodedKeyword = URLEncoder.encode(keyword, "UTF-8")
val uri = Uri.parse("tmap://search?name=$encodedKeyword")
val intent = Intent(Intent.ACTION_VIEW, uri)
requireContext().startActivity(intent)
} catch (e: Exception) {
// 앱이 없을 경우 스토어로 이동
val marketIntent = Intent(Intent.ACTION_VIEW, Uri.parse("market://details?id=com.skt.tmap.ku"))
requireContext().startActivity(marketIntent)
}
}
binding.searchGoogle.setOnClickListener {
val intent = Intent(Intent.ACTION_WEB_SEARCH).apply {
putExtra(SearchManager.QUERY, getInputText()) // 질문 전달
putExtra(SearchManager.QUERY, keyword) // 질문 전달
}
if (intent.resolveActivity(requireContext().packageManager) != null) {
startActivity(intent)
}
}
binding.searchNaver.setOnClickListener {
openSearchApps("https://search.naver.com/search.naver?where=nexearch&query=${getInputText()}", "com.nhn.android.search")
openSearchApps("https://search.naver.com/search.naver?where=nexearch&query=${keyword}", "com.nhn.android.search")
}
// ... 나머지 버튼들도 동일하게 추가 ...
}
private fun getInputText() = binding.searchInput.text.toString()
private fun openSearchApps(schemeString: String, packageName: String? = null) {
try {
@ -294,7 +340,13 @@ class AppDrawerBottomSheet : BottomSheetDialogFragment() {
}
val mainAppList = allApps.filter { it.visibilityMode == 0}
val mainAppList = allApps.filter {
if (binding.hidden.isSelected) {
true
} else {
it.visibilityMode == 0
}
}
var contactQuery = realm.query<SimpleContact>()
@ -315,7 +367,13 @@ class AppDrawerBottomSheet : BottomSheetDialogFragment() {
contactQuery = contactQuery.sort("touchCount", Sort.DESCENDING).limit(10)
val contactsResult = contactQuery.find()
val contactsList = contactsResult.map { realm.copyFromRealm(it) }
val contactsList = contactsResult.map { realm.copyFromRealm(it) }.filter {
if (binding.hidden.isSelected) {
true
} else {
it.visibilityMode == 0
}
}
Blog.LOGE("unifiedList >>> ${unifiedList.size}")

View File

@ -24,6 +24,7 @@ import android.content.ActivityNotFoundException
import android.content.ComponentName
import android.content.Context
import android.content.Intent
import android.content.SharedPreferences
import android.content.pm.ApplicationInfo
import android.content.pm.PackageManager
import android.graphics.Rect
@ -43,15 +44,14 @@ import android.widget.Toast
import androidx.core.content.FileProvider
import androidx.core.content.pm.PackageInfoCompat
import androidx.core.widget.doOnTextChanged
import bums.lunatic.launcher.LauncherActivity.Companion.lActivity
import bums.lunatic.launcher.R
import bums.lunatic.launcher.apps.AppDrawer.Companion.appNamesPrefs
import bums.lunatic.launcher.databinding.ActivityBrowserDialogBinding
import bums.lunatic.launcher.databinding.AppInfoDialogBinding
import bums.lunatic.launcher.databinding.AppMenuBinding
import bums.lunatic.launcher.helpers.UniUtils.Companion.copyToClipboard
import bums.lunatic.launcher.helpers.UniUtils.Companion.screenHeight
import bums.lunatic.launcher.helpers.UniUtils.Companion.screenWidth
import bums.lunatic.launcher.home.NeoRssActivity.Companion.lActivity
import bums.lunatic.launcher.model.AppInfo
import bums.lunatic.launcher.utils.JamoUtils
import bums.lunatic.launcher.workers.UsageLogType
@ -78,7 +78,10 @@ internal class AppMenu : BottomSheetDialogFragment() {
override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View {
binding = AppMenuBinding.inflate(inflater, container, false)
// @JvmStatic
var settingsPrefs: SharedPreferences? = null
// @JvmStatic
var appNamesPrefs: SharedPreferences? = null
/* get package name from fragment's tag */
packageName = tag.toString()
packageManager = requireContext().packageManager
@ -130,39 +133,40 @@ internal class AppMenu : BottomSheetDialogFragment() {
binding.alterName.setText(app.koreanName)
binding.recommend.isChecked = app.blockRecommend
binding.listVisible.isChecked = app.visibilityMode == 1
binding.totalTouch.setOnClickListener {
WorkersDb.logAppUsage(packageName, UsageLogType.APP,UsageUpdateType.COUNT)
}
binding.lastTouchDate.setOnClickListener {
WorkersDb.logAppUsage(packageName, UsageLogType.APP,UsageUpdateType.DATETIME)
}
binding.alterName.doOnTextChanged { text, start, before, count ->
WorkersDb.getRealm().apply {
writeBlocking {
var result = query<AppInfo>("pkgName == $0",packageName).find()
if(result.size > 0) {
val app = result.first()
app.koreanName = text.toString()
app.appNameChosung = JamoUtils.split(app.koreanName).joinToString("")
}
}
}
}
/* set application name and package name */
binding.appName.apply {
setText(app.appName)
hint = defAppName
}
binding.appPackage.text = packageName
}
}
}
}
binding.totalTouch.setOnClickListener {
WorkersDb.logAppUsage(packageName, UsageLogType.APP,UsageUpdateType.COUNT)
}
binding.lastTouchDate.setOnClickListener {
WorkersDb.logAppUsage(packageName, UsageLogType.APP,UsageUpdateType.DATETIME)
}
binding.alterName.doOnTextChanged { text, start, before, count ->
WorkersDb.getRealm().apply {
writeBlocking {
var result = query<AppInfo>("pkgName == $0",packageName).find()
if(result.size > 0) {
val app = result.first()
app.koreanName = text.toString()
app.appNameChosung = JamoUtils.split(app.koreanName).joinToString("")
}
}
}
}
/* set application name and package name */
binding.appName.apply {
setText(appNamesPrefs?.getString(packageName, defAppName))
hint = defAppName
}
binding.appPackage.text = packageName
return binding.root
}
@ -219,10 +223,10 @@ internal class AppMenu : BottomSheetDialogFragment() {
if (text!!.isBlank()) setText(defAppName)
else setText(text!!.trim())
if (text.toString() == defAppName) appNamesPrefs?.edit()!!.remove(packageName).apply()
else appNamesPrefs?.edit()!!.putString(packageName, text.toString()).apply()
(requireParentFragment() as AppDrawer).fetchApps()
// if (text.toString() == defAppName) appNamesPrefs?.edit()!!.remove(packageName).apply()
// else appNamesPrefs?.edit()!!.putString(packageName, text.toString()).apply()
//
// (requireParentFragment() as AppDrawer).fetchApps()
}
}
}

View File

@ -28,7 +28,7 @@ import android.widget.TextView
import androidx.fragment.app.FragmentManager
import androidx.recyclerview.widget.DiffUtil
import androidx.recyclerview.widget.RecyclerView
import bums.lunatic.launcher.LauncherActivity.Companion.lActivity
import bums.lunatic.launcher.LauncherActivity.Companion.sActivity
import bums.lunatic.launcher.R
import bums.lunatic.launcher.databinding.AppsChildBinding
import bums.lunatic.launcher.model.AppInfo
@ -50,7 +50,7 @@ class AppsViewHolder(var view: AppsChildBinding) : RecyclerView.ViewHolder(view.
loadIconAsync(appIconTwo, appinfo.pkgName)
childTextview.apply {
gravity = Gravity.CENTER
setTextSize(TypedValue.COMPLEX_UNIT_PX, lActivity!!.resources.getDimension(R.dimen.twelve))
setTextSize(TypedValue.COMPLEX_UNIT_PX, sActivity!!.resources.getDimension(R.dimen.twelve))
}
}

View File

@ -25,7 +25,7 @@ import android.provider.ContactsContract
import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
import bums.lunatic.launcher.LauncherActivity.Companion.lActivity
import bums.lunatic.launcher.LauncherActivity.Companion.sActivity
import bums.lunatic.launcher.databinding.ContactMenuBinding
import bums.lunatic.launcher.model.SimpleContact
import bums.lunatic.launcher.utils.Blog
@ -73,7 +73,7 @@ internal class ContactMenu : BottomSheetDialogFragment() {
WorkersDb.logAppUsage(contactId, UsageLogType.CONTACT,UsageUpdateType.DATETIME)
}
val resolver = lActivity!!.contentResolver
val resolver = sActivity!!.contentResolver
val phoneUri = ContactsContract.CommonDataKinds.Phone.CONTENT_URI
val projection = arrayOf(
ContactsContract.CommonDataKinds.Phone.DISPLAY_NAME,

View File

@ -6,7 +6,7 @@ import android.os.Bundle
import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
import bums.lunatic.launcher.LauncherActivity.Companion.lActivity
import bums.lunatic.launcher.LauncherActivity.Companion.sActivity
import bums.lunatic.launcher.databinding.ContactMenuBinding
import com.google.android.material.bottomsheet.BottomSheetDialog
import com.google.android.material.bottomsheet.BottomSheetDialogFragment
@ -25,7 +25,7 @@ class SmmsMenu: BottomSheetDialogFragment() {
/* get package name from fragment's tag */
msgId = tag.toString()
val resolver = lActivity!!.contentResolver
val resolver = sActivity!!.contentResolver
return binding.root

View File

@ -32,7 +32,7 @@ import android.view.LayoutInflater
import android.view.View
import androidx.appcompat.widget.LinearLayoutCompat
import androidx.core.content.ContextCompat
import bums.lunatic.launcher.LauncherActivity.Companion.lActivity
import bums.lunatic.launcher.LauncherActivity.Companion.sActivity
import bums.lunatic.launcher.R
import bums.lunatic.launcher.databinding.ChildSysInfoBinding
import bums.lunatic.launcher.helpers.Constants.Companion.KEY_TEMP_UNIT
@ -53,8 +53,8 @@ import kotlin.math.roundToInt
internal class SystemStats {
private val toGb = 1.07374182E9f
private fun string(id: Int) : String { return lActivity!!.getString(id) }
private val inflater : LayoutInflater get() { return lActivity!!.layoutInflater }
private fun string(id: Int) : String { return sActivity!!.getString(id) }
private val inflater : LayoutInflater get() { return sActivity!!.layoutInflater }
/* ram info */
fun ram(ramParent: LinearLayoutCompat) {
@ -137,7 +137,7 @@ internal class SystemStats {
/* external storage */
fun extStorage(extParent: LinearLayoutCompat) {
val extStorages = ContextCompat.getExternalFilesDirs(lActivity!!, null)
val extStorages = ContextCompat.getExternalFilesDirs(sActivity!!, null)
/* sd card is available */
if (extStorages.size > 1) {
extParent.removeAllViews()
@ -175,7 +175,7 @@ internal class SystemStats {
val totalRootStorage = StatFs(Environment.getRootDirectory().path).blockCountLong *
StatFs(Environment.getRootDirectory().path).blockSizeLong / toGb
val batteryIntent = lActivity!!.registerReceiver(null, IntentFilter(Intent.ACTION_BATTERY_CHANGED))
val batteryIntent = sActivity!!.registerReceiver(null, IntentFilter(Intent.ACTION_BATTERY_CHANGED))
val batteryTemp = batteryIntent!!.getIntExtra(BatteryManager.EXTRA_TEMPERATURE, 0).toFloat() / 10
val voltage = batteryIntent.getIntExtra(BatteryManager.EXTRA_VOLTAGE, 0).toFloat() / 1000
@ -199,13 +199,13 @@ internal class SystemStats {
private val memoryInfo: ActivityManager.MemoryInfo get() {
val memoryInfo = ActivityManager.MemoryInfo()
val activityManager = lActivity!!.getSystemService(Context.ACTIVITY_SERVICE) as ActivityManager
val activityManager = sActivity!!.getSystemService(Context.ACTIVITY_SERVICE) as ActivityManager
activityManager.getMemoryInfo(memoryInfo)
return memoryInfo
}
private val tempUnit: Int get() =
lActivity!!.getSharedPreferences(PREFS_SETTINGS, 0).getInt(KEY_TEMP_UNIT, 0)
sActivity!!.getSharedPreferences(PREFS_SETTINGS, 0).getInt(KEY_TEMP_UNIT, 0)
private fun longToString(long: Long) : String {
var seconds = (long.toDouble() / 1000).roundToInt()

View File

@ -28,7 +28,6 @@ import android.view.View
import android.view.ViewGroup
import androidx.recyclerview.widget.DiffUtil
import androidx.recyclerview.widget.RecyclerView
import bums.lunatic.launcher.LauncherActivity.Companion.lActivity
import bums.lunatic.launcher.databinding.ListItemWithBinding
import bums.lunatic.launcher.home.adapters.RssItemDiffUtil
import bums.lunatic.launcher.model.RssDataInterface
@ -105,7 +104,7 @@ internal class RssAdapter<T : RssDataInterface>(private val context: Context) :
val mapIntent = Intent(Intent.ACTION_VIEW, gmmIntentUri)
mapIntent.addFlags(Intent.FLAG_ACTIVITY_EXCLUDE_FROM_RECENTS)
mapIntent.setPackage("com.opera.browser")
lActivity?.startActivity(mapIntent)
context.startActivity(mapIntent)
}
fun updateData(newList: List<RssDataInterface>) {

View File

@ -29,7 +29,6 @@ import androidx.work.PeriodicWorkRequestBuilder
import androidx.work.WorkManager
import androidx.work.WorkerParameters
import bums.lunatic.launcher.LauncherActivity
import bums.lunatic.launcher.LauncherActivity.Companion.lActivity
import bums.lunatic.launcher.R
import bums.lunatic.launcher.utils.Blog
import bums.lunatic.launcher.workers.TaskAggregator
@ -252,8 +251,8 @@ class ForeGroundService : Service() {
fun workmanager() : WorkManager? {
if (mWorkManager == null && lActivity != null) {
mWorkManager = WorkManager.getInstance(lActivity!!)
if (mWorkManager == null && applicationContext != null) {
mWorkManager = WorkManager.getInstance(applicationContext)
}
return mWorkManager
}

View File

@ -37,7 +37,7 @@ import androidx.appcompat.widget.LinearLayoutCompat
import androidx.biometric.BiometricManager
import androidx.biometric.BiometricManager.BIOMETRIC_SUCCESS
import androidx.biometric.BiometricPrompt
import bums.lunatic.launcher.LauncherActivity.Companion.lActivity
import bums.lunatic.launcher.LauncherActivity.Companion.sActivity
import bums.lunatic.launcher.R
import bums.lunatic.launcher.helpers.Constants.Companion.ACCESSIBILITY_SERVICE_LOCK_SCREEN
import bums.lunatic.launcher.helpers.Constants.Companion.AUTHENTICATOR_TYPE
@ -51,13 +51,13 @@ internal class UniUtils {
/* get display width */
val screenWidth: Int get() {
return if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.R) {
val windowMetrics = lActivity!!.windowManager.currentWindowMetrics
val windowMetrics = sActivity!!.windowManager.currentWindowMetrics
val insets = windowMetrics.windowInsets
.getInsetsIgnoringVisibility(WindowInsets.Type.systemBars())
windowMetrics.bounds.width() - insets.left - insets.right
} else {
val displayMetrics = DisplayMetrics()
@Suppress("DEPRECATION") lActivity!!.windowManager.defaultDisplay.getMetrics(displayMetrics)
@Suppress("DEPRECATION") sActivity!!.windowManager.defaultDisplay.getMetrics(displayMetrics)
displayMetrics.widthPixels
}
}
@ -65,13 +65,13 @@ internal class UniUtils {
/* get display height */
val screenHeight: Int get() {
return if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.R) {
val windowMetrics = lActivity!!.windowManager.currentWindowMetrics
val windowMetrics = sActivity!!.windowManager.currentWindowMetrics
val insets = windowMetrics.windowInsets
.getInsetsIgnoringVisibility(WindowInsets.Type.systemBars())
windowMetrics.bounds.height() - insets.top - insets.bottom
} else {
val displayMetrics = DisplayMetrics()
@Suppress("DEPRECATION") lActivity!!.windowManager.defaultDisplay.getMetrics(displayMetrics)
@Suppress("DEPRECATION") sActivity!!.windowManager.defaultDisplay.getMetrics(displayMetrics)
displayMetrics.heightPixels
}
}
@ -79,7 +79,7 @@ internal class UniUtils {
/* copy texts to clipboard */
fun copyToClipboard(context: Context, copiedString: String?) {
val clipBoard =
lActivity!!.getSystemService(Context.CLIPBOARD_SERVICE) as ClipboardManager
context.getSystemService(Context.CLIPBOARD_SERVICE) as ClipboardManager
clipBoard.setPrimaryClip(ClipData.newPlainText("", copiedString))
Toast.makeText(context, context.getString(R.string.copied_message), Toast.LENGTH_SHORT).show()
}
@ -129,7 +129,7 @@ internal class UniUtils {
/* check if the device is connected to the internet */
val isNetworkAvailable: Boolean get() {
val connectivityManager =
lActivity!!.getSystemService(Context.CONNECTIVITY_SERVICE) as ConnectivityManager
sActivity!!.getSystemService(Context.CONNECTIVITY_SERVICE) as ConnectivityManager
@Suppress("DEPRECATION") val activeNetworkInfo = connectivityManager.activeNetworkInfo
@Suppress("DEPRECATION") return activeNetworkInfo != null && activeNetworkInfo.isConnectedOrConnecting
}
@ -144,7 +144,7 @@ internal class UniUtils {
fun biometricPromptInfo(title: String): BiometricPrompt.PromptInfo {
return BiometricPrompt.PromptInfo.Builder()
.setTitle(title)
.setSubtitle(lActivity!!.getString(R.string.authentication_subtitle))
.setSubtitle(sActivity!!.getString(R.string.authentication_subtitle))
.setConfirmationRequired(true)
.setAllowedAuthenticators(AUTHENTICATOR_TYPE)
.build()
@ -170,7 +170,7 @@ internal class UniUtils {
policy.lockNow()
} catch (exception: SecurityException) {
/* open device admin manager screen */
lActivity!!.startActivity(
sActivity!!.startActivity(
Intent().setComponent(
ComponentName(
"com.android.settings",
@ -226,10 +226,10 @@ internal class UniUtils {
/* lock screen using accessibility service */
private fun lockAccessibility() {
if (LockService().isAccessibilityServiceEnabled(lActivity!!.applicationContext)) {
if (LockService().isAccessibilityServiceEnabled(sActivity!!.applicationContext)) {
try {
lActivity!!.startService(
Intent(lActivity!!.applicationContext, LockService::class.java)
sActivity!!.startService(
Intent(sActivity!!.applicationContext, LockService::class.java)
.setAction(ACCESSIBILITY_SERVICE_LOCK_SCREEN)
)
} catch (exception: Exception) {
@ -237,7 +237,7 @@ internal class UniUtils {
}
} else {
/* open accessibility service screen */
lActivity!!.startActivity(Intent(Settings.ACTION_ACCESSIBILITY_SETTINGS))
sActivity!!.startActivity(Intent(Settings.ACTION_ACCESSIBILITY_SETTINGS))
}
}

View File

@ -2,8 +2,6 @@ package bums.lunatic.launcher.home
import CustomVideoNodeRenderer
import android.app.Dialog
import android.content.ClipData
import android.content.ClipboardManager
import android.content.Context
import android.content.DialogInterface
import android.content.Intent
@ -37,17 +35,16 @@ import android.widget.RadioGroup
import android.widget.TextView
import android.widget.Toast
import androidx.appcompat.app.AlertDialog
import androidx.core.content.ContextCompat.getSystemService
import androidx.core.net.toUri
import androidx.core.view.isVisible
import bums.lunatic.launcher.BookmarkUploader
import bums.lunatic.launcher.LauncherActivity.Companion.getRuntime
import bums.lunatic.launcher.R
import bums.lunatic.launcher.home.NeoRssActivity.Companion.getRuntime
import bums.lunatic.launcher.model.Dotax
import bums.lunatic.launcher.model.DotaxArticles
import bums.lunatic.launcher.model.getRssData
import bums.lunatic.launcher.tokiz.PortMessage
import bums.lunatic.launcher.tokiz.view.BWebview
import bums.lunatic.launcher.home.tokiz.PortMessage
import bums.lunatic.launcher.home.tokiz.view.BWebview
import bums.lunatic.launcher.utils.Blog
import bums.lunatic.launcher.utils.CommonUtils
import bums.lunatic.launcher.workers.WorkersDb

View File

@ -0,0 +1,654 @@
package bums.lunatic.launcher.home
import android.annotation.SuppressLint
import android.app.SearchManager
import android.content.Intent
import android.content.res.Configuration
import android.graphics.Color
import android.os.Build
import android.os.Bundle
import android.os.Handler
import android.os.Looper
import android.view.KeyEvent
import android.view.KeyEvent.ACTION_UP
import android.view.KeyEvent.KEYCODE_BUTTON_A
import android.view.KeyEvent.KEYCODE_BUTTON_B
import android.view.KeyEvent.KEYCODE_BUTTON_SELECT
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_UP
import android.view.MotionEvent
import android.view.PointerIcon
import android.view.View
import android.view.WindowManager
import androidx.activity.OnBackPressedCallback
import androidx.annotation.RequiresApi
import androidx.core.net.toUri
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 bums.lunatic.launcher.LunaticLauncher
import bums.lunatic.launcher.R
import bums.lunatic.launcher.common.CommonActivity
import bums.lunatic.launcher.databinding.RssActivityBinding
import bums.lunatic.launcher.helpers.ForeGroundService
import bums.lunatic.launcher.helpers.HeadsetActionButtonReceiver
import bums.lunatic.launcher.home.adapters.BookmarkPagerFragment
import bums.lunatic.launcher.model.RssData
import bums.lunatic.launcher.model.RssDataType
import bums.lunatic.launcher.settings.SettingsActivity
import bums.lunatic.launcher.home.tokiz.Comics
import bums.lunatic.launcher.home.tokiz.Novels
import bums.lunatic.launcher.home.tokiz.Perplexity
import bums.lunatic.launcher.home.tokiz.Webtoons
import bums.lunatic.launcher.home.tokiz.YouTube
import bums.lunatic.launcher.utils.Blog
import bums.lunatic.launcher.utils.beforeDay
import bums.lunatic.launcher.workers.WorkersDb
import com.google.android.material.color.DynamicColors
import com.yausername.ffmpeg.FFmpeg
import com.yausername.youtubedl_android.YoutubeDL
import com.yausername.youtubedl_android.YoutubeDLException
import io.realm.kotlin.ext.query
import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.launch
import org.json.JSONObject
import org.mozilla.geckoview.ExperimentDelegate
import org.mozilla.geckoview.GeckoResult
import org.mozilla.geckoview.GeckoRuntime
import org.mozilla.geckoview.GeckoRuntimeSettings
open class NeoRssActivity : CommonActivity() {
private lateinit var binding: RssActivityBinding
companion object {
private var sRuntime: GeckoRuntime? = null
fun getRuntime() : GeckoRuntime? {
lActivity?.initGeckoRuntime()
return sRuntime
}
var isOpendFold = false
val qDayPeriod = 60L * 8L
@JvmStatic var lActivity: NeoRssActivity? = null
}
var hiddenLoader : HashMap<String,GeckoWeb> = hashMapOf()
fun contentsLoad(url : String){
if (isDestroyed == false && isFinishing == false) {
url.toUri()?.host?.let { host ->
if (!hiddenLoader.contains(host)) {
GeckoWeb(this).apply {
LunaticLauncher.Companion.mHourlyLogWriter?.writeLog("contentsLoad FIRST_LOAD$host")
hiddenLoader.put(host,this)
loadUrl(url)
}
} else {
hiddenLoader.get(host)?.loadUrl(url)
LunaticLauncher.Companion.mHourlyLogWriter?.writeLog("contentsLoad RELOAD$host")
}
}
}
}
@SuppressLint("MissingSuperCall")
override fun onConfigurationChanged(newConfig: Configuration) {
super.onConfigurationChanged(newConfig)
isOpendFold = (newConfig.screenWidthDp * 1.1f) > newConfig.screenHeightDp
val nullCursor = PointerIcon.getSystemIcon(this, PointerIcon.TYPE_NULL)
binding.root.setPointerIcon(nullCursor)
}
var actionButtonPressX = 0f
var actionButtonPressY = 0f
var onExit = false
var lastAction = MotionEvent.ACTION_HOVER_EXIT
override fun dispatchKeyEvent(ev: KeyEvent): Boolean {
val currentFragment = supportFragmentManager.findFragmentById(R.id.fragment_container)
Blog.LOGE("dispatch ev?.device?.name >>> ${ev?.device?.name} , keyCode >> ${ev?.keyCode}")
if (ev?.device?.name?.contains("SM-031N Mouse") == true) {
when(ev.action) {
ACTION_UP -> {
Blog.LOGE("dispatch dispatchKeyEvent>>> ${ev}")
when(ev.keyCode) {
KEYCODE_BUTTON_Y->{
}
KEYCODE_BUTTON_X->{
}
KEYCODE_BUTTON_A->{
WorkersDb.getRealm().apply {
writeBlocking {
}
}
}
KEYCODE_BUTTON_B->{
}
KEYCODE_DPAD_DOWN->{
}
KEYCODE_DPAD_UP->{
}
KEYCODE_BUTTON_START->{
onClickCenterButton()
}
KEYCODE_BUTTON_SELECT->{
WorkersDb.getRealm().apply {
writeBlocking {
}
}
}
else -> {}
}
}
else->{}
}
return true
}
else {
val currentFragment = supportFragmentManager.findFragmentById(R.id.fragment_container)
when(currentFragment) {
is Novels -> {
if(MotionEvent.ACTION_UP.equals(ev?.action ?: MotionEvent.ACTION_CANCEL) == true) {
return when (ev.keyCode) {
KeyEvent.KEYCODE_VOLUME_DOWN -> {
if(currentFragment is Novels){ currentFragment.actionNextEvent() }
true
}
KeyEvent.KEYCODE_VOLUME_UP -> {
if(currentFragment is Novels){ currentFragment.actionPrevEvent() }
true
}
else -> false
}
} else {
return when (ev.keyCode) {
KeyEvent.KEYCODE_VOLUME_DOWN -> {
true
}
KeyEvent.KEYCODE_VOLUME_UP -> {
true
}
else -> false
}
}
}
else -> return super.dispatchKeyEvent(ev)
}
}
return super.dispatchKeyEvent(ev)
}
override fun dispatchTrackballEvent(event: MotionEvent?): Boolean {
Blog.LOGE("event >>> ${event?.device}")
return super.dispatchTrackballEvent(event)
}
@SuppressLint("RestrictedApi")
override fun dispatchKeyShortcutEvent(event: KeyEvent): Boolean {
Blog.LOGE("event >>> ${event.device}")
return super.dispatchKeyShortcutEvent(event)
}
fun onClickCenterButton() {
WorkersDb.getRealm().apply {
writeBlocking {
delete(
query<RssData>()
.query("pubDate < $0",
beforeDay(28)
)
.query("vote != $0", true).apply {
Blog.LOGE("onClickCenterButton DELETE >> ${this.description()}")
}.find()
)
var ddd = copyFromRealm(WorkersDb.getRssQuery("", RssDataType.getExcAdt(),false).limit(100).query("read == $0", 0).query("vote != $0", true).apply {
Blog.LOGE("onClickCenterButton SELECT >> ${this.description()}")
}.find()).map { it.originPage() }
var origin = ddd.first()
var jjjj = hashSetOf<String>()
jjjj.addAll(ddd)
}
}
}
override fun dispatchGenericMotionEvent(ev: MotionEvent?): Boolean {
if (ev?.device?.name?.contains("BLE-M3") == true) {
Blog.LOGE("keyEvent >>>>> dispatchGenericMotionEvent ${ev}")
ev?.action?.let { action ->
when(action) {
MotionEvent.ACTION_HOVER_ENTER -> {
return false
}
MotionEvent.ACTION_HOVER_MOVE ->{
if(lastAction == MotionEvent.ACTION_HOVER_MOVE) {
Blog.LOGE("ACTION_HOVER_MOVE Click")
}
return false
}
MotionEvent.ACTION_BUTTON_PRESS ->{
if (actionButtonPressX * actionButtonPressY == 0f) {
actionButtonPressX = ev.x ?: 0f
actionButtonPressY = ev.y ?: 0f
}
// if (onExit) return true
return false
}
MotionEvent.ACTION_BUTTON_RELEASE -> {
if (actionButtonPressX == ev.x && actionButtonPressY == ev.y) {
// Blog.LOGE("DisplayUtil.width >>> ${DisplayUtil.width} ${actionButtonPressX}")
// Blog.LOGE("DisplayUtil.width >>> ${DisplayUtil.height} ${actionButtonPressY}")
if(actionButtonPressX.toInt() == 480 && actionButtonPressY < 2000) {
Blog.LOGE("Arrow Center Click")
onClickCenterButton()
} else if(ev.y > 2000) {
}
} else if (actionButtonPressY == ev.y) {
if (actionButtonPressX.minus(ev.x ?: 0f) > 0f) {
Blog.LOGE("Arrow Right Click")
} else {
Blog.LOGE("Arrow Left Click")
}
} else {
if (actionButtonPressY.minus(ev.y ?: 0f) > 0f) {
Blog.LOGE("Arrow Down Click")
} else {
Blog.LOGE("Arrow Up Click")
}
}
// if (onExit) return true
return false
}
MotionEvent.ACTION_HOVER_EXIT -> {
actionButtonPressX = 0f
actionButtonPressY = 0f
onExit = true
return false
}
else -> {return false}
}.apply {
lastAction = action
}
}
}
return super.dispatchGenericMotionEvent(ev)
}
fun floatClick(v : View) {
Blog.LOGE("v >>> ${v}")
showContents(v.id)
}
override fun onNewIntent(intent: Intent) {
Blog.LOGE("onNewIntent intent >> ${intent}")
if(intent?.action?.equals(Intent.ACTION_SEND) == true &&
intent?.hasExtra(Intent.EXTRA_TEXT) == true) {
intent?.getStringExtra(Intent.EXTRA_TEXT)?.let {
if(it.startsWith("http") == false) {
it.split("http").forEach { string ->
if(string.startsWith("http")) {
try {
string.toUri()?.let { uri ->
Blog.LOGE("onNewIntent string uri.lastPathSegment >>>>> ${uri.host}")
Blog.LOGE("onNewIntent string uri.lastPathSegment >>>>> ${uri.lastPathSegment}")
}
} catch (e: Exception) {
}
}
}
} else {
try {
it.toUri()?.let { uri ->
Blog.LOGE("onNewIntent it uri.lastPathSegment >>>>> ${uri.host}")
Blog.LOGE("onNewIntent it uri.lastPathSegment >>>>> ${uri.lastPathSegment}")
}
} catch (e: Exception) {
}
}
}
} else if (intent?.action == Intent.ACTION_WEB_SEARCH) {
openWithIntent(intent)
} else {
Blog.LOGE("onNewIntent intent?.hasExtra >> ${intent?.hasExtra(Intent.EXTRA_STREAM)}")
if (intent?.action?.equals(Intent.ACTION_MAIN) == true && intent.categories.contains(
Intent.CATEGORY_HOME
) && intent.hasExtra("android.intent.extra.EXTRA_START_REASON") && intent.getStringExtra(
"android.intent.extra.EXTRA_START_REASON"
).equals("startDockOrHome")
) {
} else {
intent?.extras?.keySet()?.forEach {
try {
Blog.LOGE(
"onNewIntent :: key >> ${it} :: value >> ${
intent?.extras?.getString(
it
)
}"
)
} catch (e: Exception) {
e.printStackTrace()
}
}
}
}
super.onNewIntent(intent)
}
private fun openWithIntent(intent: Intent){
Blog.LOGE("intent >> ${intent}")
intent.getStringExtra(SearchManager.QUERY)?.let { query->
Blog.LOGE("intent >> ${query}")
supportFragmentManager.beginTransaction()
.replace(R.id.fragment_container, RssHome().apply {
arguments = Bundle().apply {
putString(SearchManager.QUERY, query)
}
})
.commit()
}
}
@SuppressLint("NewApi", "MissingPermission", "ClickableViewAccessibility")
override fun onCreate(savedInstanceState: Bundle?) {
installSplashScreen()
super.onCreate(savedInstanceState)
try {
YoutubeDL.getInstance().init(this)
FFmpeg.getInstance().init(this);
CoroutineScope(Dispatchers.IO).launch {
YoutubeDL.getInstance().updateYoutubeDL(this@NeoRssActivity)
}
} catch (e: YoutubeDLException) {
Blog.LOGE("failed to initialize youtubedl-android", e)
}
val intent = Intent(this, ForeGroundService::class.java)
this.startForegroundService(intent)
// 1. 시스템 바 공간을 앱이 차지하도록 설정 (상태바 뒤로 레이아웃 확장)
WindowCompat.setDecorFitsSystemWindows(window, false)
// 2. 상태바 색상을 투명하게 변경 (필요한 경우)
window.statusBarColor = Color.TRANSPARENT
// (선택 사항) 내비게이션 바도 투명하게 하고 싶다면
window.navigationBarColor = Color.TRANSPARENT
getWindow().addFlags(WindowManager.LayoutParams.FLAG_SECURE);
lActivity = this
DynamicColors.applyToActivityIfAvailable(this)
binding = RssActivityBinding.inflate(layoutInflater)
setContentView(binding.root)
HeadsetActionButtonReceiver.register(this)
ViewCompat.setOnApplyWindowInsetsListener(binding.root) { view, windowInsets ->
val insets = windowInsets.getInsets(WindowInsetsCompat.Type.systemBars())
view.setPadding(insets.left, insets.top, insets.right, insets.bottom)
WindowInsetsCompat.CONSUMED
}
handleBackPress()
updateLocationService()
// showContents(binding.feeds.id)
binding.floatingActionMenu.setOnTouchListener { v: View, e: MotionEvent ->
if (binding.floatingActionMenu.isOpened) {
binding.floatingActionMenu.close(true)
return@setOnTouchListener true
}
return@setOnTouchListener false
}
binding.floatingActionMenu.setOnMenuButtonClickListener { v->
Blog.LOGE("v >> ${v}")
showContents(v.id)
}
if (intent?.action == Intent.ACTION_WEB_SEARCH) {
openWithIntent(intent)
}
val nullCursor = PointerIcon.getSystemIcon(this, PointerIcon.TYPE_NULL)
binding.root.setPointerIcon(nullCursor)
binding.share.setOnClickListener {
if (binding.currentAddress.text.length > 5) {
val sendIntent: Intent = Intent().apply {
setAction(Intent.ACTION_SEND)
(binding.currentAddress.tag as? String)?.let{putExtra(Intent.EXTRA_TITLE, it)}
putExtra(Intent.EXTRA_TEXT, binding.currentAddress.text)
setType("text/plain")
}
val shareIntent = Intent.createChooser(sendIntent, "링크 공유하기")
startActivity(shareIntent)
}
}
showContents(R.id.feeds)
}
override fun onPause() {
super.onPause()
}
// LauncherActivity 클래스 멤버 변수 추가
private var isDraggingWidget = false
private var currentDragView: View? = null
private var lastTouchX = 0f
private var lastTouchY = 0f
fun showContents(id : Int) {
binding.fragmentLayer.visibility = View.VISIBLE
binding.fragmentContainer.visibility = View.VISIBLE
binding.controllPanel.visibility = View.VISIBLE
binding.floatingActionMenu.visibility = View.VISIBLE
when(id) {
R.id.feeds -> {
supportFragmentManager.beginTransaction()
.replace(R.id.fragment_container, RssHome())
.commit()
}
R.id.books ->{
supportFragmentManager.beginTransaction()
.replace(R.id.fragment_container, Novels())
.commit()
}
R.id.webtoons ->{
supportFragmentManager.beginTransaction()
.replace(R.id.fragment_container, Webtoons())
.commit()
}
R.id.comics ->{
supportFragmentManager.beginTransaction()
.replace(R.id.fragment_container, Comics())
.commit()
}
R.id.youtube ->{
supportFragmentManager.beginTransaction()
.replace(R.id.fragment_container, YouTube())
.commit()
}
R.id.perplexity ->{
supportFragmentManager.beginTransaction()
.replace(R.id.fragment_container, Perplexity())
.commit()
}
R.id.zota ->{
supportFragmentManager.beginTransaction()
.replace(R.id.fragment_container, BookmarkPagerFragment())
.commit()
}
R.id.setting ->{
startActivity(Intent(this, SettingsActivity::class.java))
}
R.id.close ->{
supportFragmentManager.findFragmentById(R.id.fragment_container)?.let {
supportFragmentManager.beginTransaction()
.remove(it)
.commit()
binding.fragmentLayer.visibility = View.GONE
binding.fragmentContainer.visibility = View.GONE
binding.controllPanel.visibility = View.GONE
binding.floatingActionMenu.visibility = View.GONE
}
}
else -> {}
}
binding.floatingActionMenu.close(false)
}
private fun initGeckoRuntime() {
if (sRuntime == null) {
try {
sRuntime = GeckoRuntime.create(this, GeckoRuntimeSettings.Builder()
.extensionsProcessEnabled(true)
.extensionsWebAPIEnabled(true)
.experimentDelegate(experimentDelegate)
.debugLogging(false)
.remoteDebuggingEnabled(true).build())
} catch (e : Exception) {
e.printStackTrace()
}
}
}
override fun onTouchEvent(event: MotionEvent?): Boolean {
Blog.LOGE("event >>> ${event}")
return super.onTouchEvent(event)
}
override fun onStart() {
super.onStart()
}
override fun onStop() {
super.onStop()
}
override fun onDestroy() {
try {
sRuntime?.shutdown()
sRuntime = null
} catch (e: Exception) { e.printStackTrace() }
// appWidgetHost?.stopListening() // 이 줄은 제거하고 onStop으로 이동
super.onDestroy()
}
@RequiresApi(Build.VERSION_CODES.O_MR1)
override fun onResume() {
super.onResume()
Blog.LOGE("LauncherActivity onResume")
}
private fun openSearch() {
val searchManager = getSystemService(SEARCH_SERVICE) as SearchManager
val searchableInfo = searchManager.getSearchableInfo(componentName)
if (searchableInfo != null) {
val intent = Intent(Intent.ACTION_SEARCH).apply {
// setSearchableInfo(searchableInfo)
setFlags(Intent.FLAG_ACTIVITY_NEW_TASK)
}
startActivity(intent)
} else {
// 검색 가능한 앱이 없을 경우 처리
}
}
/* alternative of deprecated onBackPressed method */
private fun handleBackPress() {
onBackPressedDispatcher.addCallback(this, object : OnBackPressedCallback(true) {
override fun handleOnBackPressed() {
val currentFragment = supportFragmentManager.findFragmentById(R.id.fragment_container)
if (currentFragment == null) showContents(R.id.close)
when(currentFragment) {
is RssHome ->{
if (currentFragment.binding.layoutRssSummary.root.isVisible) {
currentFragment.openGecko(rssData = currentFragment.randomOrNull())
} else {
currentFragment.doNextPage()
}
}
is YouTube -> {
currentFragment.back()
}
is Novels -> {
currentFragment.actionNextEvent(false)
}
else -> {
showContents(R.id.close)
}
}
}
})
}
val experimentDelegate = object : ExperimentDelegate {
override fun onGetExperimentFeature(feature: String): GeckoResult<JSONObject?> {
Blog.LOGE("onGetExperimentFeature $feature")
return super.onGetExperimentFeature(feature)
}
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)
}
}
val callBackHandler = Handler(Looper.getMainLooper())
}

View File

@ -43,26 +43,24 @@ import androidx.fragment.app.FragmentManager
import androidx.recyclerview.widget.DividerItemDecoration
import androidx.recyclerview.widget.ItemTouchHelper
import androidx.recyclerview.widget.RecyclerView
import bums.lunatic.launcher.LauncherActivity
import bums.lunatic.launcher.LauncherActivity.Companion.lActivity
import bums.lunatic.launcher.R
import bums.lunatic.launcher.common.letTrue
import bums.lunatic.launcher.databinding.LauncherHomeBinding
import bums.lunatic.launcher.helpers.Constants.Companion.PREFS_SETTINGS
import bums.lunatic.launcher.home.NeoRssActivity.Companion.lActivity
import bums.lunatic.launcher.home.SearchBottomSheet.OnSearchListener
import bums.lunatic.launcher.home.adapters.RssItemAdapter
import bums.lunatic.launcher.home.adapters.SwipeToDeleteCallback
import bums.lunatic.launcher.model.RssData
import bums.lunatic.launcher.model.RssDataType
import bums.lunatic.launcher.model.WeatherForcast
import bums.lunatic.launcher.tokiz.view.JxEvent
import bums.lunatic.launcher.home.tokiz.view.JxEvent
import bums.lunatic.launcher.utils.Blog
import bums.lunatic.launcher.utils.SimpleFingerGestures
import bums.lunatic.launcher.utils.beforeDay
import bums.lunatic.launcher.utils.beforeOneDay
import bums.lunatic.launcher.workers.WorkersDb
import bums.lunatic.launcher.workers.WorkersDb.getRealm
import com.google.android.material.imageview.ShapeableImageView
import com.squareup.picasso.Picasso
import io.realm.kotlin.UpdatePolicy
import io.realm.kotlin.ext.query
@ -577,7 +575,7 @@ internal class RssHome : Fragment() {
binding.geckoWeb.decoViews.add(binding.hide)
binding.geckoWeb.decoViews.add(binding.vote)
binding.geckoWeb.decoViews.add(binding.progressBar)
(activity as? LauncherActivity)?.let { activity ->
(activity as? NeoRssActivity)?.let { activity ->
binding.geckoWeb.decoViews.add(activity.findViewById<TextView>(R.id.current_address))
binding.geckoWeb.decoViews.add(activity.findViewById<ImageButton>(R.id.back))
binding.geckoWeb.decoViews.add(activity.findViewById<ImageButton>(R.id.reload))

View File

@ -1,114 +1,114 @@
/*
* Lunar Launcher
* Copyright (C) 2022 Md Rasel Hossain
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package bums.lunatic.launcher.home
import android.content.pm.PackageManager
import android.os.Bundle
import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
import android.webkit.WebView
import androidx.fragment.app.DialogFragment
import bums.lunatic.launcher.R
import bums.lunatic.launcher.databinding.RssViewerBinding
internal class RssViewer : DialogFragment() {
private lateinit var binding: RssViewerBinding
private lateinit var packageName: String
private lateinit var packageManager: PackageManager
private lateinit var defAppName: String
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setStyle(STYLE_NO_TITLE, R.style.FilterFullScreenDialog)
}
override fun onStart() {
super.onStart()
if (dialog != null) {
// val metrics = resources.displayMetrics
// val screenHeight = metrics.heightPixels
// val bottomSheet =
// dialog!!.findViewById<View>(com.google.android.material.R.id.design_bottom_sheet)
// bottomSheet.layoutParams.height = (screenHeight * 0.95).toInt()
// val behavior = BottomSheetBehavior.from(bottomSheet)
// behavior.state = BottomSheetBehavior.STATE_EXPANDED
// behavior.skipCollapsed = true
}
}
override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View {
binding = RssViewerBinding.inflate(inflater, container, false)
binding.webview.loadUrl(tag!!)
binding.webview.setDesktopMode(false)
var mWebView = WebView(requireContext())
mWebView.requestFocus()
mWebView.evaluateJavascript("try {document.querySelector('.my-point-box').focus()}catch(err){}") { }
// binding.pdfPrint.setOnClickListener { pdfPring() }
return binding.root
}
// fun pdfPring() {
// val fileName = tag?.toUri()?.path?.replace("/","_")?.replace(".","_")
// val path = File(Environment.getExternalStorageDirectory(),"bums")
// if (path.exists() == false) {
// path.mkdirs()
// }
// val file = File(path, fileName.plus(".pdf"))
///*
// * Lunar Launcher
// * Copyright (C) 2022 Md Rasel Hossain
// *
// * This program is free software: you can redistribute it and/or modify
// * it under the terms of the GNU General Public License as published by
// * the Free Software Foundation, either version 3 of the License, or
// * (at your option) any later version.
// *
// * This program is distributed in the hope that it will be useful,
// * but WITHOUT ANY WARRANTY; without even the implied warranty of
// * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// * GNU General Public License for more details.
// *
// * You should have received a copy of the GNU General Public License
// * along with this program. If not, see <http://www.gnu.org/licenses/>.
// */
//
// BLog.LOGE("file >>> ${file.absolutePath}")
// try {
// PDFPrint.generatePDFFromWebView(file,binding.webview, object : PDFPrint.OnPDFPrintListener {
// override fun onSuccess(file: File?) {
// BLog.LOGE("file >>>> ${file!!.absolutePath}")
// val shareIntent: Intent = Intent().apply {
// action = Intent.ACTION_SEND
// this.`package` = "com.synology.dsdrive"
// val imageUri = FileProvider.getUriForFile(
// lActivity!!,
// "bums.lunatic.launcher.fileprovider", //(use your app signature + ".provider" )
// file
// )
// putExtra(Intent.EXTRA_STREAM, imageUri)
// type = "pdf"
// }
// lActivity!!.startActivity(shareIntent)
// }
//package bums.lunatic.launcher.home
//
// override fun onError(exception: java.lang.Exception?) {
// Toast.makeText(lActivity!!,
// "Pdf Save Failk ${exception?.localizedMessage}", Toast.LENGTH_LONG).show()
// exception?.printStackTrace()
// }
// } )
// } catch (e: IOException) {
// e.printStackTrace()
//import android.content.pm.PackageManager
//import android.os.Bundle
//import android.view.LayoutInflater
//import android.view.View
//import android.view.ViewGroup
//import android.webkit.WebView
//import androidx.fragment.app.DialogFragment
//import bums.lunatic.launcher.R
//import bums.lunatic.launcher.databinding.RssViewerBinding
//
//
//internal class RssViewer : DialogFragment() {
//
// private lateinit var binding: RssViewerBinding
// private lateinit var packageName: String
// private lateinit var packageManager: PackageManager
// private lateinit var defAppName: String
//
// override fun onCreate(savedInstanceState: Bundle?) {
// super.onCreate(savedInstanceState)
// setStyle(STYLE_NO_TITLE, R.style.FilterFullScreenDialog)
// }
//
// override fun onStart() {
// super.onStart()
// if (dialog != null) {
//// val metrics = resources.displayMetrics
//// val screenHeight = metrics.heightPixels
//// val bottomSheet =
//// dialog!!.findViewById<View>(com.google.android.material.R.id.design_bottom_sheet)
//// bottomSheet.layoutParams.height = (screenHeight * 0.95).toInt()
//// val behavior = BottomSheetBehavior.from(bottomSheet)
//// behavior.state = BottomSheetBehavior.STATE_EXPANDED
//// behavior.skipCollapsed = true
// }
// }
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
super.onViewCreated(view, savedInstanceState)
// (requireDialog() as BottomSheetDialog).dismissWithAnimation = true
}
}
//
// override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View {
// binding = RssViewerBinding.inflate(inflater, container, false)
// binding.webview.loadUrl(tag!!)
// binding.webview.setDesktopMode(false)
//
// var mWebView = WebView(requireContext())
// mWebView.requestFocus()
// mWebView.evaluateJavascript("try {document.querySelector('.my-point-box').focus()}catch(err){}") { }
//
//// binding.pdfPrint.setOnClickListener { pdfPring() }
// return binding.root
// }
//
//// fun pdfPring() {
//// val fileName = tag?.toUri()?.path?.replace("/","_")?.replace(".","_")
//// val path = File(Environment.getExternalStorageDirectory(),"bums")
//// if (path.exists() == false) {
//// path.mkdirs()
//// }
//// val file = File(path, fileName.plus(".pdf"))
////
//// BLog.LOGE("file >>> ${file.absolutePath}")
//// try {
//// PDFPrint.generatePDFFromWebView(file,binding.webview, object : PDFPrint.OnPDFPrintListener {
//// override fun onSuccess(file: File?) {
//// BLog.LOGE("file >>>> ${file!!.absolutePath}")
//// val shareIntent: Intent = Intent().apply {
//// action = Intent.ACTION_SEND
//// this.`package` = "com.synology.dsdrive"
//// val imageUri = FileProvider.getUriForFile(
//// lActivity!!,
//// "bums.lunatic.launcher.fileprovider", //(use your app signature + ".provider" )
//// file
//// )
//// putExtra(Intent.EXTRA_STREAM, imageUri)
//// type = "pdf"
//// }
//// lActivity!!.startActivity(shareIntent)
//// }
////
//// override fun onError(exception: java.lang.Exception?) {
//// Toast.makeText(lActivity!!,
//// "Pdf Save Failk ${exception?.localizedMessage}", Toast.LENGTH_LONG).show()
//// exception?.printStackTrace()
//// }
//// } )
//// } catch (e: IOException) {
//// e.printStackTrace()
//// }
//// }
//
// override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
// super.onViewCreated(view, savedInstanceState)
//// (requireDialog() as BottomSheetDialog).dismissWithAnimation = true
//
// }
//}

View File

@ -1,112 +1,112 @@
/*
* Lunar Launcher
* Copyright (C) 2022 Md Rasel Hossain
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package bums.lunatic.launcher.home.adapters
import android.annotation.SuppressLint
import android.content.Context
import android.content.pm.PackageManager
import android.graphics.drawable.Drawable
import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
import androidx.constraintlayout.widget.ConstraintLayout
import androidx.recyclerview.widget.DiffUtil
import androidx.recyclerview.widget.RecyclerView
import bums.lunatic.launcher.LauncherActivity.Companion.lActivity
import bums.lunatic.launcher.databinding.ListItemWithBinding
import bums.lunatic.launcher.model.NotificationItem
import bums.lunatic.launcher.workers.WorkersDb
import java.text.SimpleDateFormat
import java.util.Date
internal class NotificationItemAdapter (
private val context: Context) : RecyclerView.Adapter<NotiHolder>() {
private var notiItems: ArrayList<NotificationItem> = arrayListOf()
override fun onCreateViewHolder(viewGroup: ViewGroup, i: Int): NotiHolder {
val binding = ListItemWithBinding.inflate(LayoutInflater.from(viewGroup.context), viewGroup, false)
return NotiHolder(binding)
}
override fun getItemCount(): Int {
return notiItems.size
}
val dateFormat = SimpleDateFormat("hh:mm / yy - MM - dd")
@SuppressLint("SetTextI18n")
override fun onBindViewHolder(holder: NotiHolder, position: Int) {
val appInfo = notiItems[position]
try {
holder.view.circlePreview.visibility = View.VISIBLE
var param = holder.view.circlePreview.layoutParams
holder.view.circlePreview.layoutParams = ConstraintLayout.LayoutParams(120,param.height)
val d: Drawable = context.packageManager.getApplicationIcon(appInfo.pkgName!!)
holder.view.circlePreview.setImageDrawable(d)
holder.view.title.text = appInfo.tikerMsg ?: "${appInfo.selfDisplayName} ${appInfo.subtext}"
holder.view.desc.text = "${appInfo.pkgName} ${appInfo.title}"
holder.view.date.text = dateFormat.format(Date(appInfo.postTime))
holder.view.circlePreview.setOnLongClickListener {
WorkersDb.getRealm().writeBlocking {
delete(query<NotificationItem>(NotificationItem::class).query("pkgName == $0",appInfo.pkgName).find())
}
lActivity?.packageManager?.apply {
context.startActivity(getLaunchIntentForPackage(appInfo.pkgName!!))
}
true
}
} catch (e: PackageManager.NameNotFoundException) {
return
}
}
fun updateData(newList: List<NotificationItem>) {
try {
DiffUtil.calculateDiff(NotiItemDiffUtil(notiItems, newList)).apply {
}.dispatchUpdatesTo(this).apply {
// notifyItemRangeChanged(0,10)
}
notiItems.clear()
notiItems.addAll(newList)
}catch ( e : Exception) {
e.printStackTrace()
}
}
}
internal class NotiHolder(var view: ListItemWithBinding) : RecyclerView.ViewHolder(view.root)
internal class NotiItemDiffUtil(
var oldList: List<NotificationItem>, var newList: List<NotificationItem>
) : DiffUtil.Callback() {
override fun getOldListSize(): Int = oldList.size
override fun getNewListSize(): Int = newList.size
override fun areItemsTheSame(oldItemPosition: Int, newItemPosition: Int): Boolean =
oldList[oldItemPosition].uniq_id == if (newList.size > newItemPosition) newList[newItemPosition].uniq_id else ""
override fun areContentsTheSame(oldItemPosition: Int, newItemPosition: Int): Boolean =
oldList[oldItemPosition].uniq_id == if (newList.size > newItemPosition) newList[newItemPosition].uniq_id else ""
}
///*
// * Lunar Launcher
// * Copyright (C) 2022 Md Rasel Hossain
// *
// * This program is free software: you can redistribute it and/or modify
// * it under the terms of the GNU General Public License as published by
// * the Free Software Foundation, either version 3 of the License, or
// * (at your option) any later version.
// *
// * This program is distributed in the hope that it will be useful,
// * but WITHOUT ANY WARRANTY; without even the implied warranty of
// * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// * GNU General Public License for more details.
// *
// * You should have received a copy of the GNU General Public License
// * along with this program. If not, see <http://www.gnu.org/licenses/>.
// */
//
//package bums.lunatic.launcher.home.adapters
//
//import android.annotation.SuppressLint
//import android.content.Context
//import android.content.pm.PackageManager
//import android.graphics.drawable.Drawable
//import android.view.LayoutInflater
//import android.view.View
//import android.view.ViewGroup
//import androidx.constraintlayout.widget.ConstraintLayout
//import androidx.recyclerview.widget.DiffUtil
//import androidx.recyclerview.widget.RecyclerView
//import bums.lunatic.launcher.databinding.ListItemWithBinding
//import bums.lunatic.launcher.home.NeoRssActivity.Companion.lActivity
//import bums.lunatic.launcher.model.NotificationItem
//import bums.lunatic.launcher.workers.WorkersDb
//import java.text.SimpleDateFormat
//import java.util.Date
//
//
//internal class NotificationItemAdapter (
// private val context: Context) : RecyclerView.Adapter<NotiHolder>() {
// private var notiItems: ArrayList<NotificationItem> = arrayListOf()
// override fun onCreateViewHolder(viewGroup: ViewGroup, i: Int): NotiHolder {
// val binding = ListItemWithBinding.inflate(LayoutInflater.from(viewGroup.context), viewGroup, false)
// return NotiHolder(binding)
// }
//
// override fun getItemCount(): Int {
// return notiItems.size
// }
//
// val dateFormat = SimpleDateFormat("hh:mm / yy - MM - dd")
//
// @SuppressLint("SetTextI18n")
// override fun onBindViewHolder(holder: NotiHolder, position: Int) {
// val appInfo = notiItems[position]
// try {
// holder.view.circlePreview.visibility = View.VISIBLE
// var param = holder.view.circlePreview.layoutParams
// holder.view.circlePreview.layoutParams = ConstraintLayout.LayoutParams(120,param.height)
// val d: Drawable = context.packageManager.getApplicationIcon(appInfo.pkgName!!)
// holder.view.circlePreview.setImageDrawable(d)
// holder.view.title.text = appInfo.tikerMsg ?: "${appInfo.selfDisplayName} ${appInfo.subtext}"
// holder.view.desc.text = "${appInfo.pkgName} ${appInfo.title}"
// holder.view.date.text = dateFormat.format(Date(appInfo.postTime))
// holder.view.circlePreview.setOnLongClickListener {
// WorkersDb.getRealm().writeBlocking {
// delete(query<NotificationItem>(NotificationItem::class).query("pkgName == $0",appInfo.pkgName).find())
// }
// lActivity?.packageManager?.apply {
// context.startActivity(getLaunchIntentForPackage(appInfo.pkgName!!))
// }
// true
// }
//
//
// } catch (e: PackageManager.NameNotFoundException) {
// return
// }
//
// }
//
// fun updateData(newList: List<NotificationItem>) {
// try {
// DiffUtil.calculateDiff(NotiItemDiffUtil(notiItems, newList)).apply {
//
// }.dispatchUpdatesTo(this).apply {
//// notifyItemRangeChanged(0,10)
// }
// notiItems.clear()
// notiItems.addAll(newList)
// }catch ( e : Exception) {
// e.printStackTrace()
// }
// }
//
//
//}
//
//internal class NotiHolder(var view: ListItemWithBinding) : RecyclerView.ViewHolder(view.root)
//internal class NotiItemDiffUtil(
// var oldList: List<NotificationItem>, var newList: List<NotificationItem>
//) : DiffUtil.Callback() {
//
// override fun getOldListSize(): Int = oldList.size
// override fun getNewListSize(): Int = newList.size
//
// override fun areItemsTheSame(oldItemPosition: Int, newItemPosition: Int): Boolean =
// oldList[oldItemPosition].uniq_id == if (newList.size > newItemPosition) newList[newItemPosition].uniq_id else ""
//
// override fun areContentsTheSame(oldItemPosition: Int, newItemPosition: Int): Boolean =
// oldList[oldItemPosition].uniq_id == if (newList.size > newItemPosition) newList[newItemPosition].uniq_id else ""
//}

View File

@ -1,167 +1,167 @@
/*
* Lunar Launcher
* Copyright (C) 2022 Md Rasel Hossain
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package bums.lunatic.launcher.home.adapters
import android.annotation.SuppressLint
import android.content.Context
import android.content.Intent
import android.net.Uri
import android.provider.CallLog
import android.provider.ContactsContract
import android.view.LayoutInflater
import android.view.ViewGroup
import androidx.recyclerview.widget.DiffUtil
import androidx.recyclerview.widget.GridLayoutManager
import androidx.recyclerview.widget.RecyclerView
import bums.lunatic.launcher.LauncherActivity.Companion.lActivity
import bums.lunatic.launcher.R
import bums.lunatic.launcher.databinding.CalllogItemBinding
import bums.lunatic.launcher.utils.getContactId
import bums.lunatic.launcher.workers.RecentCall
internal class RecentCallsAdapter(
private val callList: ArrayList<RecentCall>,
private val context: Context) : RecyclerView.Adapter<RecentCallsAdapter.RecentCallsHolder>() {
private val currentFragment = lActivity!!.supportFragmentManager.findFragmentById(R.id.mainFragmentsContainer)
override fun onCreateViewHolder(viewGroup: ViewGroup, i: Int): RecentCallsHolder {
val binding = CalllogItemBinding.inflate(LayoutInflater.from(viewGroup.context), viewGroup, false)
return RecentCallsHolder(binding)
}
override fun getItemCount(): Int {
// BLog.LOGE("callList.size >>> ${callList.size}")
return callList.size
}
@SuppressLint("SetTextI18n")
override fun onBindViewHolder(holder: RecentCallsHolder, position: Int) {
val todo = callList[position]
holder.view.name.text = if(todo.name.equals("unknown")) todo.number else { todo.name}
when (todo.type) {
// CallLog.Calls.INCOMING_TYPE -> { dir = "INCOMING_TYPE" }
// CallLog.Calls.OUTGOING_TYPE -> { dir = "OUTGOING_TYPE" }
CallLog.Calls.MISSED_TYPE -> { holder.view.root.isSelected = true }
// CallLog.Calls.VOICEMAIL_TYPE -> { dir = "VOICEMAIL_TYPE" }
// CallLog.Calls.REJECTED_TYPE -> { dir = "REJECTED_TYPE" }
// CallLog.Calls.BLOCKED_TYPE -> { dir = "BLOCKED_TYPE" }
// CallLog.Calls.ANSWERED_EXTERNALLY_TYPE -> { dir = "ANSWERED_EXTERNALLY_TYPE" }
else -> { holder.view.root.isSelected = false }
}
// "\u25CF ${} , ${todo.typeString} : ${todo.count} : ${todo.date}"
holder.view.type.text = todo.typeString
/* multiline texts are enabled for TodoManager */
holder.view.date.text = todo.date
/* launch edit or update dialog on item click */
holder.view.root.setOnClickListener { updateDialog(position) }
/* copy texts on long click */
holder.view.root.setOnLongClickListener {
// copyToClipboard(context, todo.name)
var cId = getContactId(lActivity!!.contentResolver, todo.number)
if (cId != null && cId.length > 0) {
var intent = Intent(Intent.ACTION_VIEW);
intent.setData(Uri.parse(ContactsContract.Contacts.CONTENT_URI.toString() + "/" + cId));
lActivity?.startActivity(intent);
} else {
lActivity?.startActivity(Intent(Intent.ACTION_DIAL, Uri.parse("tel:${todo.number}")))
}
true
}
}
inner class RecentCallsHolder(var view: CalllogItemBinding) : RecyclerView.ViewHolder(view.root)
/* update dialog */
private fun updateDialog(position: Int) {
// val bottomSheetDialog = BottomSheetDialog(lActivity!!, R.style.BottomSheetDialog)
// val dialogBinding = TodoDialogBinding.inflate(LayoutInflater.from(context))
// bottomSheetDialog.setContentView(dialogBinding.root)
// bottomSheetDialog.show()
// bottomSheetDialog.dismissWithAnimation = true
///*
// * Lunar Launcher
// * Copyright (C) 2022 Md Rasel Hossain
// *
// * This program is free software: you can redistribute it and/or modify
// * it under the terms of the GNU General Public License as published by
// * the Free Software Foundation, either version 3 of the License, or
// * (at your option) any later version.
// *
// * This program is distributed in the hope that it will be useful,
// * but WITHOUT ANY WARRANTY; without even the implied warranty of
// * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// * GNU General Public License for more details.
// *
// * You should have received a copy of the GNU General Public License
// * along with this program. If not, see <http://www.gnu.org/licenses/>.
// */
//
// val databaseHandler = DatabaseHandler(context)
// val todo = databaseHandler.todos[position]
//package bums.lunatic.launcher.home.adapters
//
// dialogBinding.apply {
// deleteAllConfirmation.visibility = View.GONE
// todoInput.setText(todo.name)
// todoCancel.text = context.getString(R.string.delete)
// todoCancel.setTextColor(ContextCompat.getColor(context, android.R.color.holo_red_light))
// todoOk.text = context.getString(R.string.update)
//import android.annotation.SuppressLint
//import android.content.Context
//import android.content.Intent
//import android.net.Uri
//import android.provider.CallLog
//import android.provider.ContactsContract
//import android.view.LayoutInflater
//import android.view.ViewGroup
//import androidx.recyclerview.widget.DiffUtil
//import androidx.recyclerview.widget.GridLayoutManager
//import androidx.recyclerview.widget.RecyclerView
//import bums.lunatic.launcher.R
//import bums.lunatic.launcher.databinding.CalllogItemBinding
//import bums.lunatic.launcher.home.NeoRssActivity.Companion.lActivity
//import bums.lunatic.launcher.utils.getContactId
//import bums.lunatic.launcher.workers.RecentCall
//
//
//internal class RecentCallsAdapter(
// private val callList: ArrayList<RecentCall>,
// private val context: Context) : RecyclerView.Adapter<RecentCallsAdapter.RecentCallsHolder>() {
//
// private val currentFragment = lActivity!!.supportFragmentManager.findFragmentById(R.id.mainFragmentsContainer)
//
// override fun onCreateViewHolder(viewGroup: ViewGroup, i: Int): RecentCallsHolder {
// val binding = CalllogItemBinding.inflate(LayoutInflater.from(viewGroup.context), viewGroup, false)
// return RecentCallsHolder(binding)
// }
//
// override fun getItemCount(): Int {
//// BLog.LOGE("callList.size >>> ${callList.size}")
// return callList.size
// }
//
// @SuppressLint("SetTextI18n")
// override fun onBindViewHolder(holder: RecentCallsHolder, position: Int) {
// val todo = callList[position]
// holder.view.name.text = if(todo.name.equals("unknown")) todo.number else { todo.name}
//
// when (todo.type) {
//// CallLog.Calls.INCOMING_TYPE -> { dir = "INCOMING_TYPE" }
//// CallLog.Calls.OUTGOING_TYPE -> { dir = "OUTGOING_TYPE" }
// CallLog.Calls.MISSED_TYPE -> { holder.view.root.isSelected = true }
//// CallLog.Calls.VOICEMAIL_TYPE -> { dir = "VOICEMAIL_TYPE" }
//// CallLog.Calls.REJECTED_TYPE -> { dir = "REJECTED_TYPE" }
//// CallLog.Calls.BLOCKED_TYPE -> { dir = "BLOCKED_TYPE" }
//// CallLog.Calls.ANSWERED_EXTERNALLY_TYPE -> { dir = "ANSWERED_EXTERNALLY_TYPE" }
// else -> { holder.view.root.isSelected = false }
// }
//// "\u25CF ${} , ${todo.typeString} : ${todo.count} : ${todo.date}"
// holder.view.type.text = todo.typeString
// /* multiline texts are enabled for TodoManager */
// holder.view.date.text = todo.date
// /* launch edit or update dialog on item click */
// holder.view.root.setOnClickListener { updateDialog(position) }
// /* copy texts on long click */
// holder.view.root.setOnLongClickListener {
//
// /* delete the item */
// dialogBinding.todoCancel.setOnClickListener {
//
// }
//
// /* update the item */
// dialogBinding.todoOk.setOnClickListener {
// val updatedTodoString = Objects.requireNonNull(dialogBinding.todoInput.text).toString().trim { it <= ' ' }
// if (updatedTodoString.isNotEmpty()) {
// todo.name = updatedTodoString
// databaseHandler.updateTodo(todo)
// bottomSheetDialog.dismiss()
//// copyToClipboard(context, todo.name)
// var cId = getContactId(lActivity!!.contentResolver, todo.number)
// if (cId != null && cId.length > 0) {
// var intent = Intent(Intent.ACTION_VIEW);
// intent.setData(Uri.parse(ContactsContract.Contacts.CONTENT_URI.toString() + "/" + cId));
// lActivity?.startActivity(intent);
// } else {
// dialogBinding.todoInput.error = context.getString(R.string.empty_text_field)
// lActivity?.startActivity(Intent(Intent.ACTION_DIAL, Uri.parse("tel:${todo.number}")))
// }
//
// true
// }
//
// }
//
// inner class RecentCallsHolder(var view: CalllogItemBinding) : RecyclerView.ViewHolder(view.root)
//
// /* update dialog */
// private fun updateDialog(position: Int) {
//// val bottomSheetDialog = BottomSheetDialog(lActivity!!, R.style.BottomSheetDialog)
//// val dialogBinding = TodoDialogBinding.inflate(LayoutInflater.from(context))
//// bottomSheetDialog.setContentView(dialogBinding.root)
//// bottomSheetDialog.show()
//// bottomSheetDialog.dismissWithAnimation = true
////
//// val databaseHandler = DatabaseHandler(context)
//// val todo = databaseHandler.todos[position]
////
//// dialogBinding.apply {
//// deleteAllConfirmation.visibility = View.GONE
//// todoInput.setText(todo.name)
//// todoCancel.text = context.getString(R.string.delete)
//// todoCancel.setTextColor(ContextCompat.getColor(context, android.R.color.holo_red_light))
//// todoOk.text = context.getString(R.string.update)
//// }
////
//// /* delete the item */
//// dialogBinding.todoCancel.setOnClickListener {
////
//// }
////
//// /* update the item */
//// dialogBinding.todoOk.setOnClickListener {
//// val updatedTodoString = Objects.requireNonNull(dialogBinding.todoInput.text).toString().trim { it <= ' ' }
//// if (updatedTodoString.isNotEmpty()) {
//// todo.name = updatedTodoString
//// databaseHandler.updateTodo(todo)
//// bottomSheetDialog.dismiss()
//// } else {
//// dialogBinding.todoInput.error = context.getString(R.string.empty_text_field)
//// }
//// }
// }
// var layoutManager : GridLayoutManager? = null
// var recyclerView: RecyclerView? = null
// override fun onAttachedToRecyclerView(recyclerView: RecyclerView) {
// layoutManager = recyclerView.layoutManager as? GridLayoutManager
// this.recyclerView = recyclerView
// }
//
// fun updateData(newList: Collection<RecentCall>) {
// val diffUtilResult = DiffUtil.calculateDiff(RecentCallDiffUtil(callList, newList.toList()))
// diffUtilResult.dispatchUpdatesTo(this).apply {
// val visibleItemCount = (layoutManager?.findLastVisibleItemPosition() ?: 0) - (layoutManager?.findFirstVisibleItemPosition() ?: 0)
// if (visibleItemCount > 0) {
// this@RecentCallsAdapter.notifyItemRangeChanged(0, visibleItemCount)
// recyclerView?.scrollToPosition(0)
// }
// }
}
var layoutManager : GridLayoutManager? = null
var recyclerView: RecyclerView? = null
override fun onAttachedToRecyclerView(recyclerView: RecyclerView) {
layoutManager = recyclerView.layoutManager as? GridLayoutManager
this.recyclerView = recyclerView
}
fun updateData(newList: Collection<RecentCall>) {
val diffUtilResult = DiffUtil.calculateDiff(RecentCallDiffUtil(callList, newList.toList()))
diffUtilResult.dispatchUpdatesTo(this).apply {
val visibleItemCount = (layoutManager?.findLastVisibleItemPosition() ?: 0) - (layoutManager?.findFirstVisibleItemPosition() ?: 0)
if (visibleItemCount > 0) {
this@RecentCallsAdapter.notifyItemRangeChanged(0, visibleItemCount)
recyclerView?.scrollToPosition(0)
}
}
callList.clear()
callList.addAll(newList)
}
}
internal class RecentCallDiffUtil(
private val oldList: List<RecentCall>, private val newList: List<RecentCall>
) : DiffUtil.Callback() {
override fun getOldListSize(): Int = oldList.size
override fun getNewListSize(): Int = newList.size
override fun areItemsTheSame(oldItemPosition: Int, newItemPosition: Int): Boolean =
oldList[oldItemPosition].date == newList[newItemPosition].date
override fun areContentsTheSame(oldItemPosition: Int, newItemPosition: Int): Boolean =
oldList[oldItemPosition] == newList[newItemPosition]
}
// callList.clear()
// callList.addAll(newList)
// }
//
//}
//
//internal class RecentCallDiffUtil(
// private val oldList: List<RecentCall>, private val newList: List<RecentCall>
//) : DiffUtil.Callback() {
//
// override fun getOldListSize(): Int = oldList.size
// override fun getNewListSize(): Int = newList.size
//
// override fun areItemsTheSame(oldItemPosition: Int, newItemPosition: Int): Boolean =
// oldList[oldItemPosition].date == newList[newItemPosition].date
//
// override fun areContentsTheSame(oldItemPosition: Int, newItemPosition: Int): Boolean =
// oldList[oldItemPosition] == newList[newItemPosition]
//}
//

View File

@ -1,169 +1,168 @@
/*
* Lunar Launcher
* Copyright (C) 2022 Md Rasel Hossain
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package bums.lunatic.launcher.home.adapters
import android.annotation.SuppressLint
import android.content.Context
import android.content.Intent
import android.net.Uri
import android.view.LayoutInflater
import android.view.ViewGroup
import androidx.recyclerview.widget.DiffUtil
import androidx.recyclerview.widget.RecyclerView
import bums.lunatic.launcher.LauncherActivity.Companion.lActivity
import bums.lunatic.launcher.R
import bums.lunatic.launcher.databinding.SmsItemBinding
import bums.lunatic.launcher.utils.getContactName
import bums.lunatic.launcher.workers.RecentSms
import java.text.SimpleDateFormat
import java.util.Date
internal class SmsLogsAdapter(
private val smsList: ArrayList<RecentSms>,
private val context: Context) : RecyclerView.Adapter<SmsLogHolder>() {
private val currentFragment = lActivity!!.supportFragmentManager.findFragmentById(R.id.mainFragmentsContainer)
override fun onCreateViewHolder(viewGroup: ViewGroup, i: Int): SmsLogHolder {
val binding = SmsItemBinding.inflate(LayoutInflater.from(viewGroup.context), viewGroup, false)
return SmsLogHolder(binding)
}
override fun getItemCount(): Int {
return smsList.size
}
@SuppressLint("SetTextI18n")
override fun onBindViewHolder(holder: SmsLogHolder, position: Int) {
val todo = smsList[position]
var name = getContactName(lActivity!!.contentResolver,todo.person)
if (name == null) {
getContactName(lActivity!!.contentResolver,todo.addr)
}
if(todo.isMms) {
var body = todo.texts?.joinToString("\n")?.replace("\n"," ")
body = if (body?.length ?: 0 > 60) body?.substring(0,60).plus("...") else body
holder.view.itemText.text = "\u25CF ${if(name != null && name.length > 0) name else if(todo.person != null && todo.person.length > 0){todo.person} else todo.addr} : ${
SimpleDateFormat("yyyy/MM/dd HH:mm:ss").format(
Date(
Math.max(
todo.pstDate.toLong(),
todo.rcvDate.toLong()
)
)
)
} : ${todo.type}"
holder.view.contents.text = "${body}"
} else {
holder.view.itemText.text = "\u25CF ${if(name != null && name.length > 0) name else if(todo.person != null && todo.person.length > 0){todo.person} else todo.addr} : ${
SimpleDateFormat("yyyy/MM/dd HH:mm:ss").format(
Date(
Math.max(
todo.pstDate.toLong(),
todo.rcvDate.toLong()
)
)
)
} : ${todo.type}"
holder.view.contents.text = "${todo.body}"
}
/* multiline texts are enabled for TodoManager */
// holder.view.itemText.isSingleLine = false
/* launch edit or update dialog on item click */
// holder.view.itemText.setOnClickListener { updateDialog(position) }
/* copy texts on long click */
holder.view.itemText.setOnLongClickListener {
var intent = Intent(Intent.ACTION_SENDTO);
intent.setData(Uri.parse("smsto:" + Uri.encode(todo.addr)));
lActivity?.startActivity(intent);
true
}
holder.view.root.isActivated = if(holder.view.itemText.text.contains("#CMAS#")) true else false
}
fun updateData(newList: List<RecentSms>) {
val diffUtilResult = DiffUtil.calculateDiff(SmsDiffUtil(smsList, newList))
diffUtilResult.dispatchUpdatesTo(this)
smsList.clear()
smsList.addAll(newList)
}
/* update dialog */
private fun updateDialog(position: Int) {
// val bottomSheetDialog = BottomSheetDialog(lActivity!!, R.style.BottomSheetDialog)
// val dialogBinding = TodoDialogBinding.inflate(LayoutInflater.from(context))
// bottomSheetDialog.setContentView(dialogBinding.root)
// bottomSheetDialog.show()
// bottomSheetDialog.dismissWithAnimation = true
///*
// * Lunar Launcher
// * Copyright (C) 2022 Md Rasel Hossain
// *
// * This program is free software: you can redistribute it and/or modify
// * it under the terms of the GNU General Public License as published by
// * the Free Software Foundation, either version 3 of the License, or
// * (at your option) any later version.
// *
// * This program is distributed in the hope that it will be useful,
// * but WITHOUT ANY WARRANTY; without even the implied warranty of
// * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// * GNU General Public License for more details.
// *
// * You should have received a copy of the GNU General Public License
// * along with this program. If not, see <http://www.gnu.org/licenses/>.
// */
//
// val databaseHandler = DatabaseHandler(context)
// val todo = databaseHandler.todos[position]
//package bums.lunatic.launcher.home.adapters
//
// dialogBinding.apply {
// deleteAllConfirmation.visibility = View.GONE
// todoInput.setText(todo.name)
// todoCancel.text = context.getString(R.string.delete)
// todoCancel.setTextColor(ContextCompat.getColor(context, android.R.color.holo_red_light))
// todoOk.text = context.getString(R.string.update)
//import android.annotation.SuppressLint
//import android.content.Context
//import android.content.Intent
//import android.net.Uri
//import android.view.LayoutInflater
//import android.view.ViewGroup
//import androidx.recyclerview.widget.DiffUtil
//import androidx.recyclerview.widget.RecyclerView
//import bums.lunatic.launcher.R
//import bums.lunatic.launcher.databinding.SmsItemBinding
//import bums.lunatic.launcher.utils.getContactName
//import bums.lunatic.launcher.workers.RecentSms
//import java.text.SimpleDateFormat
//import java.util.Date
//
//
//internal class SmsLogsAdapter(
// private val smsList: ArrayList<RecentSms>,
// private val context: Context) : RecyclerView.Adapter<SmsLogHolder>() {
//
// private val currentFragment = lActivity!!.supportFragmentManager.findFragmentById(R.id.mainFragmentsContainer)
//
// override fun onCreateViewHolder(viewGroup: ViewGroup, i: Int): SmsLogHolder {
// val binding = SmsItemBinding.inflate(LayoutInflater.from(viewGroup.context), viewGroup, false)
// return SmsLogHolder(binding)
// }
//
// override fun getItemCount(): Int {
// return smsList.size
// }
//
// @SuppressLint("SetTextI18n")
// override fun onBindViewHolder(holder: SmsLogHolder, position: Int) {
// val todo = smsList[position]
// var name = getContactName(lActivity!!.contentResolver,todo.person)
// if (name == null) {
// getContactName(lActivity!!.contentResolver,todo.addr)
// }
// if(todo.isMms) {
// var body = todo.texts?.joinToString("\n")?.replace("\n"," ")
// body = if (body?.length ?: 0 > 60) body?.substring(0,60).plus("...") else body
// holder.view.itemText.text = "\u25CF ${if(name != null && name.length > 0) name else if(todo.person != null && todo.person.length > 0){todo.person} else todo.addr} : ${
// SimpleDateFormat("yyyy/MM/dd HH:mm:ss").format(
// Date(
// Math.max(
// todo.pstDate.toLong(),
// todo.rcvDate.toLong()
// )
// )
// )
// } : ${todo.type}"
// holder.view.contents.text = "${body}"
// } else {
// holder.view.itemText.text = "\u25CF ${if(name != null && name.length > 0) name else if(todo.person != null && todo.person.length > 0){todo.person} else todo.addr} : ${
// SimpleDateFormat("yyyy/MM/dd HH:mm:ss").format(
// Date(
// Math.max(
// todo.pstDate.toLong(),
// todo.rcvDate.toLong()
// )
// )
// )
// } : ${todo.type}"
//
//
//
//
// holder.view.contents.text = "${todo.body}"
// }
//
// /* delete the item */
// dialogBinding.todoCancel.setOnClickListener {
//
//
// /* multiline texts are enabled for TodoManager */
//// holder.view.itemText.isSingleLine = false
// /* launch edit or update dialog on item click */
//// holder.view.itemText.setOnClickListener { updateDialog(position) }
// /* copy texts on long click */
// holder.view.itemText.setOnLongClickListener {
// var intent = Intent(Intent.ACTION_SENDTO);
// intent.setData(Uri.parse("smsto:" + Uri.encode(todo.addr)));
// lActivity?.startActivity(intent);
// true
// }
//
// /* update the item */
// dialogBinding.todoOk.setOnClickListener {
// val updatedTodoString = Objects.requireNonNull(dialogBinding.todoInput.text).toString().trim { it <= ' ' }
// if (updatedTodoString.isNotEmpty()) {
// todo.name = updatedTodoString
// databaseHandler.updateTodo(todo)
// bottomSheetDialog.dismiss()
// } else {
// dialogBinding.todoInput.error = context.getString(R.string.empty_text_field)
// }
// }
}
}
class SmsLogHolder(var view: SmsItemBinding) : RecyclerView.ViewHolder(view.root)
internal class SmsDiffUtil(
private val oldList: List<RecentSms>, private val newList: List<RecentSms>
) : DiffUtil.Callback() {
override fun getOldListSize(): Int = oldList.size
override fun getNewListSize(): Int = newList.size
override fun areItemsTheSame(oldItemPosition: Int, newItemPosition: Int): Boolean =
oldList[oldItemPosition].rcvDate == newList[newItemPosition].rcvDate
override fun areContentsTheSame(oldItemPosition: Int, newItemPosition: Int): Boolean =
oldList[oldItemPosition].rcvDate == newList[newItemPosition].rcvDate
}
// holder.view.root.isActivated = if(holder.view.itemText.text.contains("#CMAS#")) true else false
// }
//
//
//
// fun updateData(newList: List<RecentSms>) {
// val diffUtilResult = DiffUtil.calculateDiff(SmsDiffUtil(smsList, newList))
// diffUtilResult.dispatchUpdatesTo(this)
// smsList.clear()
// smsList.addAll(newList)
// }
//
// /* update dialog */
// private fun updateDialog(position: Int) {
//// val bottomSheetDialog = BottomSheetDialog(lActivity!!, R.style.BottomSheetDialog)
//// val dialogBinding = TodoDialogBinding.inflate(LayoutInflater.from(context))
//// bottomSheetDialog.setContentView(dialogBinding.root)
//// bottomSheetDialog.show()
//// bottomSheetDialog.dismissWithAnimation = true
////
//// val databaseHandler = DatabaseHandler(context)
//// val todo = databaseHandler.todos[position]
////
//// dialogBinding.apply {
//// deleteAllConfirmation.visibility = View.GONE
//// todoInput.setText(todo.name)
//// todoCancel.text = context.getString(R.string.delete)
//// todoCancel.setTextColor(ContextCompat.getColor(context, android.R.color.holo_red_light))
//// todoOk.text = context.getString(R.string.update)
//// }
////
//// /* delete the item */
//// dialogBinding.todoCancel.setOnClickListener {
////
//// }
////
//// /* update the item */
//// dialogBinding.todoOk.setOnClickListener {
//// val updatedTodoString = Objects.requireNonNull(dialogBinding.todoInput.text).toString().trim { it <= ' ' }
//// if (updatedTodoString.isNotEmpty()) {
//// todo.name = updatedTodoString
//// databaseHandler.updateTodo(todo)
//// bottomSheetDialog.dismiss()
//// } else {
//// dialogBinding.todoInput.error = context.getString(R.string.empty_text_field)
//// }
//// }
// }
//
//}
//class SmsLogHolder(var view: SmsItemBinding) : RecyclerView.ViewHolder(view.root)
//internal class SmsDiffUtil(
// private val oldList: List<RecentSms>, private val newList: List<RecentSms>
//) : DiffUtil.Callback() {
//
// override fun getOldListSize(): Int = oldList.size
// override fun getNewListSize(): Int = newList.size
//
// override fun areItemsTheSame(oldItemPosition: Int, newItemPosition: Int): Boolean =
// oldList[oldItemPosition].rcvDate == newList[newItemPosition].rcvDate
//
// override fun areContentsTheSame(oldItemPosition: Int, newItemPosition: Int): Boolean =
// oldList[oldItemPosition].rcvDate == newList[newItemPosition].rcvDate
//}

View File

@ -1,107 +1,107 @@
package bums.lunatic.launcher.home.adapters
import android.annotation.SuppressLint
import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
import androidx.recyclerview.widget.LinearLayoutManager
import androidx.recyclerview.widget.LinearSnapHelper
import androidx.recyclerview.widget.RecyclerView
import bums.lunatic.launcher.databinding.WeatherBookBinding
import bums.lunatic.launcher.utils.Blog
class WeatherAdapter(
private val pages: List<Int>,
private val adatpers: List<RecyclerView.Adapter<out RecyclerView.ViewHolder>?>,
private val weatherBook: WeatherBookBinding? = null)
: RecyclerView.Adapter<WeatherAdapter.PageViewHolder>() {
class PageViewHolder(val view: View): RecyclerView.ViewHolder(view)
var childs : ArrayList<RecyclerView> = arrayListOf<RecyclerView>()
@SuppressLint("ResourceType")
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): PageViewHolder {
val layoutInflater = LayoutInflater.from(parent.context).inflate(pages[viewType], parent, false)
// var first = layoutInflater.findViewById<RecyclerView>(R.id.recycler_hourly_weather)
// var second = layoutInflater.findViewById<RecyclerView>(R.id.weather_dress_recycller)
return PageViewHolder(layoutInflater)
}
fun syncScroll(newPosition: Int) {
childs[newPosition].let {recyclerView ->
Blog.LOGE("recyclerView >>> ${recyclerView} 1 ")
if (!isSyncingScroll) {
isSyncingScroll = true
Blog.LOGE("recyclerView >>> ${recyclerView} 2 ")
childs.forEach { c ->
// val visibleItemCount = (layoutManager?.findLastVisibleItemPosition() ?: 0) - (layoutManager?.findFirstVisibleItemPosition() ?: 0)
if (c != recyclerView) {
(c.layoutManager as LinearLayoutManager)?.let {
it.findFirstVisibleItemPosition()?.let {
(recyclerView?.layoutManager as? LinearLayoutManager)?.let { target ->
target.scrollToPositionWithOffset(it, 0)
}
// .scrollToPosition(it)
}
}
Blog.LOGE("recyclerView >>> ${recyclerView} 3 ")
}
}
isSyncingScroll = false
Blog.LOGE("recyclerView >>> ${recyclerView} 4 ")
}
}
}
val mOnScrollListener = object : RecyclerView.OnScrollListener() {
override fun onScrollStateChanged(recyclerView: RecyclerView, newState: Int) {
super.onScrollStateChanged(recyclerView, newState)
// recyclerView.postDelayed({syncScroll(recyclerView)},10L)
// recyclerView.post{syncScroll(recyclerView)}
}
override fun onScrolled(recyclerView: RecyclerView, dx: Int, dy: Int) {
super.onScrolled(recyclerView, dx, dy)
}
}
var isSyncingScroll = false
override fun onBindViewHolder(holder: PageViewHolder, position: Int) {
if (adatpers[position] != null) {
(holder.view as RecyclerView).apply {
this.adapter = adatpers[position]
this.layoutManager = LinearLayoutManager(this.context, LinearLayoutManager.HORIZONTAL, false)
if (!childs.contains(this)) {
childs.add(this)
this.addOnScrollListener(mOnScrollListener)
LinearSnapHelper().attachToRecyclerView(this)
}
}
// when (position) {
// 0 -> holder.view.findViewById<RecyclerView>(R.id.recycler_hourly_weather).apply {
// this.adapter = adatpers[position]
// this.layoutManager =
//package bums.lunatic.launcher.home.adapters
//
//import android.annotation.SuppressLint
//import android.view.LayoutInflater
//import android.view.View
//import android.view.ViewGroup
//import androidx.recyclerview.widget.LinearLayoutManager
//import androidx.recyclerview.widget.LinearSnapHelper
//import androidx.recyclerview.widget.RecyclerView
//import bums.lunatic.launcher.databinding.WeatherBookBinding
//import bums.lunatic.launcher.utils.Blog
//
//class WeatherAdapter(
// private val pages: List<Int>,
// private val adatpers: List<RecyclerView.Adapter<out RecyclerView.ViewHolder>?>,
// private val weatherBook: WeatherBookBinding? = null)
// : RecyclerView.Adapter<WeatherAdapter.PageViewHolder>() {
//
// class PageViewHolder(val view: View): RecyclerView.ViewHolder(view)
//
//
// var childs : ArrayList<RecyclerView> = arrayListOf<RecyclerView>()
//
//
// @SuppressLint("ResourceType")
// override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): PageViewHolder {
//
//
// val layoutInflater = LayoutInflater.from(parent.context).inflate(pages[viewType], parent, false)
//// var first = layoutInflater.findViewById<RecyclerView>(R.id.recycler_hourly_weather)
//// var second = layoutInflater.findViewById<RecyclerView>(R.id.weather_dress_recycller)
//
// return PageViewHolder(layoutInflater)
// }
//
//
// fun syncScroll(newPosition: Int) {
// childs[newPosition].let {recyclerView ->
// Blog.LOGE("recyclerView >>> ${recyclerView} 1 ")
// if (!isSyncingScroll) {
// isSyncingScroll = true
// Blog.LOGE("recyclerView >>> ${recyclerView} 2 ")
// childs.forEach { c ->
//// val visibleItemCount = (layoutManager?.findLastVisibleItemPosition() ?: 0) - (layoutManager?.findFirstVisibleItemPosition() ?: 0)
// if (c != recyclerView) {
// (c.layoutManager as LinearLayoutManager)?.let {
// it.findFirstVisibleItemPosition()?.let {
// (recyclerView?.layoutManager as? LinearLayoutManager)?.let { target ->
// target.scrollToPositionWithOffset(it, 0)
// }
//// .scrollToPosition(it)
// }
// }
// Blog.LOGE("recyclerView >>> ${recyclerView} 3 ")
// }
// }
// isSyncingScroll = false
// Blog.LOGE("recyclerView >>> ${recyclerView} 4 ")
// }
// }
//
// else -> holder.view.findViewById<RecyclerView>(R.id.weather_dress_recycller).apply {
// this.adapter = adatpers[position]
// this.layoutManager =
// LinearLayoutManager(this.context, LinearLayoutManager.HORIZONTAL, false)
// }
//
//
// val mOnScrollListener = object : RecyclerView.OnScrollListener() {
// override fun onScrollStateChanged(recyclerView: RecyclerView, newState: Int) {
// super.onScrollStateChanged(recyclerView, newState)
//// recyclerView.postDelayed({syncScroll(recyclerView)},10L)
//// recyclerView.post{syncScroll(recyclerView)}
// }
//
// override fun onScrolled(recyclerView: RecyclerView, dx: Int, dy: Int) {
// super.onScrolled(recyclerView, dx, dy)
// }
// }
// var isSyncingScroll = false
// override fun onBindViewHolder(holder: PageViewHolder, position: Int) {
// if (adatpers[position] != null) {
// (holder.view as RecyclerView).apply {
// this.adapter = adatpers[position]
// this.layoutManager = LinearLayoutManager(this.context, LinearLayoutManager.HORIZONTAL, false)
// if (!childs.contains(this)) {
// childs.add(this)
// this.addOnScrollListener(mOnScrollListener)
// LinearSnapHelper().attachToRecyclerView(this)
// }
// }
}
}
override fun getItemCount(): Int = pages.size
override fun getItemViewType(position: Int): Int = position
}
//// when (position) {
//// 0 -> holder.view.findViewById<RecyclerView>(R.id.recycler_hourly_weather).apply {
//// this.adapter = adatpers[position]
//// this.layoutManager =
////
//// }
////
//// else -> holder.view.findViewById<RecyclerView>(R.id.weather_dress_recycller).apply {
//// this.adapter = adatpers[position]
//// this.layoutManager =
//// LinearLayoutManager(this.context, LinearLayoutManager.HORIZONTAL, false)
//// }
//// }
// }
// }
//
// override fun getItemCount(): Int = pages.size
//
// override fun getItemViewType(position: Int): Int = position
//}

View File

@ -1,71 +1,71 @@
package bums.lunatic.launcher.home.adapters
import android.annotation.SuppressLint
import android.graphics.Color
import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
import androidx.recyclerview.widget.RecyclerView
import bums.lunatic.launcher.databinding.ItemRecHourlyDressBinding
import bums.lunatic.launcher.model.Hour
import bums.lunatic.launcher.model.WeatherInfoManager
import java.util.Calendar
class WeatherDressAdatper (private val dataSet: ArrayList<Hour>) : RecyclerView.Adapter<WeatherDressAdatper.ViewHolder>(){
var isChangedAmOrPm: Boolean = true
class ViewHolder(val viewItem: ItemRecHourlyDressBinding): RecyclerView.ViewHolder(viewItem.root)
// @SuppressLint("NotifyDataSetChanged")
fun update(li: Collection<Hour>) {
li.toList()
this.dataSet.clear()
this.dataSet.addAll(li)
// notifyDataSetChanged()
}
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): WeatherDressAdatper.ViewHolder {
// val view = LayoutInflater.from(parent.context)
// .inflate(R.layout.item_rec_hourly_dress, parent, false)
// val itemBinding: ItemRecHourlyDressBinding = DataBindingUtil.
val binding = ItemRecHourlyDressBinding.inflate(LayoutInflater.from(parent.context), parent, false)
return WeatherDressAdatper.ViewHolder(binding)
}
fun getToday() = Calendar.getInstance().get(Calendar.DAY_OF_YEAR)
@SuppressLint("SetTextI18n")
override fun onBindViewHolder(holder: WeatherDressAdatper.ViewHolder, position: Int) {
val data = dataSet[position] as? Hour
// BLog.LOGE("saved weatherForcast >>> asFlow ${dataSet.size}")
// val today = Calendar.getInstance()
// today.time = Date(data?.time_epoch?.toLong()?.times(1000L) ?: 0L)
// val dayOfItem = today.get(Calendar.DAY_OF_YEAR)
data?.let {
// total.loc = WorkersDb.getRealm().query<Location>().also {
// BLog.LOGE("re >>> ${it.description()}") // 쿼리 로그
// }.find().first()
WeatherInfoManager.getShowingInfo(it).apply {
// total.setInfo(this)
holder.viewItem.setInfo(this)
}
// BLog.LOGE("reeeeeeeeeee >>> ${holder.viewItem.hour.text}")
holder.viewItem.amOrPm.visibility =
if (arrayListOf(12, 0).contains(WeatherInfoManager.toZonedDateTime(it.time_epoch).hour) || position == 0) {
View.VISIBLE
} else View.INVISIBLE
holder.viewItem.hour.apply {
if (WeatherInfoManager.toZonedDateTime(it.time_epoch).hour == 0) {
this@apply.setTextColor(Color.BLACK)
this@apply.isSelected = true
} else {
this@apply.setTextColor(Color.WHITE)
this@apply.isSelected = false
}
}
holder.viewItem.imgWeather.setImageLevel(it.temp_c.toInt())
}
}
override fun getItemCount(): Int = dataSet.size
}
//package bums.lunatic.launcher.home.adapters
//
//import android.annotation.SuppressLint
//import android.graphics.Color
//import android.view.LayoutInflater
//import android.view.View
//import android.view.ViewGroup
//import androidx.recyclerview.widget.RecyclerView
//import bums.lunatic.launcher.databinding.ItemRecHourlyDressBinding
//import bums.lunatic.launcher.model.Hour
//import bums.lunatic.launcher.model.WeatherInfoManager
//import java.util.Calendar
//
//class WeatherDressAdatper (private val dataSet: ArrayList<Hour>) : RecyclerView.Adapter<WeatherDressAdatper.ViewHolder>(){
// var isChangedAmOrPm: Boolean = true
//
// class ViewHolder(val viewItem: ItemRecHourlyDressBinding): RecyclerView.ViewHolder(viewItem.root)
//
// // @SuppressLint("NotifyDataSetChanged")
// fun update(li: Collection<Hour>) {
// li.toList()
// this.dataSet.clear()
// this.dataSet.addAll(li)
//// notifyDataSetChanged()
// }
//
// override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): WeatherDressAdatper.ViewHolder {
//// val view = LayoutInflater.from(parent.context)
//// .inflate(R.layout.item_rec_hourly_dress, parent, false)
//// val itemBinding: ItemRecHourlyDressBinding = DataBindingUtil.
// val binding = ItemRecHourlyDressBinding.inflate(LayoutInflater.from(parent.context), parent, false)
// return WeatherDressAdatper.ViewHolder(binding)
// }
//
// fun getToday() = Calendar.getInstance().get(Calendar.DAY_OF_YEAR)
//
// @SuppressLint("SetTextI18n")
// override fun onBindViewHolder(holder: WeatherDressAdatper.ViewHolder, position: Int) {
// val data = dataSet[position] as? Hour
//// BLog.LOGE("saved weatherForcast >>> asFlow ${dataSet.size}")
//// val today = Calendar.getInstance()
//// today.time = Date(data?.time_epoch?.toLong()?.times(1000L) ?: 0L)
//// val dayOfItem = today.get(Calendar.DAY_OF_YEAR)
// data?.let {
//// total.loc = WorkersDb.getRealm().query<Location>().also {
//// BLog.LOGE("re >>> ${it.description()}") // 쿼리 로그
//// }.find().first()
// WeatherInfoManager.getShowingInfo(it).apply {
//// total.setInfo(this)
// holder.viewItem.setInfo(this)
// }
//// BLog.LOGE("reeeeeeeeeee >>> ${holder.viewItem.hour.text}")
// holder.viewItem.amOrPm.visibility =
// if (arrayListOf(12, 0).contains(WeatherInfoManager.toZonedDateTime(it.time_epoch).hour) || position == 0) {
// View.VISIBLE
// } else View.INVISIBLE
// holder.viewItem.hour.apply {
// if (WeatherInfoManager.toZonedDateTime(it.time_epoch).hour == 0) {
// this@apply.setTextColor(Color.BLACK)
// this@apply.isSelected = true
// } else {
// this@apply.setTextColor(Color.WHITE)
// this@apply.isSelected = false
// }
// }
// holder.viewItem.imgWeather.setImageLevel(it.temp_c.toInt())
// }
// }
//
// override fun getItemCount(): Int = dataSet.size
//}

View File

@ -1,54 +1,54 @@
package bums.lunatic.launcher.home.adapters
import android.graphics.Color
import android.view.LayoutInflater
import android.view.ViewGroup
import androidx.recyclerview.widget.RecyclerView
import bums.lunatic.launcher.databinding.ItemHourlyWeatherBinding
import bums.lunatic.launcher.model.Hour
import bums.lunatic.launcher.model.WeatherInfoManager
import com.squareup.picasso.Picasso
class WeatherHourlyAdapter(private val dataSet: ArrayList<Hour>): RecyclerView.Adapter<WeatherHourlyAdapter.ViewHolder>() {
class ViewHolder(val viewItem: ItemHourlyWeatherBinding): RecyclerView.ViewHolder(viewItem.root)
override fun onCreateViewHolder(parent: ViewGroup, type: Int): WeatherHourlyAdapter.ViewHolder {
val binding = ItemHourlyWeatherBinding.inflate(LayoutInflater.from(parent.context), parent, false)
return WeatherHourlyAdapter.ViewHolder(binding)
}
override fun onBindViewHolder(holder: ViewHolder, position: Int) {
val data = dataSet[position] as? Hour
// BLog.LOGE("saved weatherForcast >>> asFlow ${dataSet.size}")
data?.let {
WeatherInfoManager.getShowingInfo(it).apply {
holder.viewItem.setInfo(this)
Picasso.get()
.load(this.urlImgWeather)
.into(holder.viewItem.imgWeather)
}
// BLog.LOGE("reeeeeeeeeee >>> ${holder.viewItem.hour.text}")
// holder.viewItem.amOrPm.visibility =
// if (arrayListOf(12, 0).contains(WeatherInfoManager.toZonedDateTime(it.time_epoch).hour) || position == 0) {
// View.VISIBLE
// } else View.INVISIBLE
holder.viewItem.hour.apply {
if (WeatherInfoManager.toZonedDateTime(it.time_epoch).hour == 0) {
this@apply.setTextColor(Color.BLACK)
this@apply.isSelected = true
} else {
this@apply.setTextColor(Color.WHITE)
this@apply.isSelected = false
}
}
}
}
override fun getItemCount(): Int = dataSet.size
fun update(li: Collection<Hour>) {
li.toList()
this.dataSet.clear()
this.dataSet.addAll(li)
}
}
//package bums.lunatic.launcher.home.adapters
//
//import android.graphics.Color
//import android.view.LayoutInflater
//import android.view.ViewGroup
//import androidx.recyclerview.widget.RecyclerView
//import bums.lunatic.launcher.databinding.ItemHourlyWeatherBinding
//import bums.lunatic.launcher.model.Hour
//import bums.lunatic.launcher.model.WeatherInfoManager
//import com.squareup.picasso.Picasso
//
//class WeatherHourlyAdapter(private val dataSet: ArrayList<Hour>): RecyclerView.Adapter<WeatherHourlyAdapter.ViewHolder>() {
// class ViewHolder(val viewItem: ItemHourlyWeatherBinding): RecyclerView.ViewHolder(viewItem.root)
//
// override fun onCreateViewHolder(parent: ViewGroup, type: Int): WeatherHourlyAdapter.ViewHolder {
// val binding = ItemHourlyWeatherBinding.inflate(LayoutInflater.from(parent.context), parent, false)
// return WeatherHourlyAdapter.ViewHolder(binding)
// }
//
// override fun onBindViewHolder(holder: ViewHolder, position: Int) {
// val data = dataSet[position] as? Hour
//// BLog.LOGE("saved weatherForcast >>> asFlow ${dataSet.size}")
// data?.let {
// WeatherInfoManager.getShowingInfo(it).apply {
// holder.viewItem.setInfo(this)
// Picasso.get()
// .load(this.urlImgWeather)
// .into(holder.viewItem.imgWeather)
// }
//// BLog.LOGE("reeeeeeeeeee >>> ${holder.viewItem.hour.text}")
//// holder.viewItem.amOrPm.visibility =
//// if (arrayListOf(12, 0).contains(WeatherInfoManager.toZonedDateTime(it.time_epoch).hour) || position == 0) {
//// View.VISIBLE
//// } else View.INVISIBLE
// holder.viewItem.hour.apply {
// if (WeatherInfoManager.toZonedDateTime(it.time_epoch).hour == 0) {
// this@apply.setTextColor(Color.BLACK)
// this@apply.isSelected = true
// } else {
// this@apply.setTextColor(Color.WHITE)
// this@apply.isSelected = false
// }
// }
// }
// }
//
// override fun getItemCount(): Int = dataSet.size
//
// fun update(li: Collection<Hour>) {
// li.toList()
// this.dataSet.clear()
// this.dataSet.addAll(li)
// }
//}

View File

@ -1,9 +1,8 @@
package bums.lunatic.launcher.tokiz
package bums.lunatic.launcher.home.tokiz
import android.content.DialogInterface
import android.content.Intent
import android.content.res.Configuration
import android.graphics.Bitmap
import android.net.Uri
import android.os.Bundle
import android.os.Handler
@ -22,8 +21,6 @@ import android.view.View.OnTouchListener
import android.view.View.VISIBLE
import android.view.View.inflate
import android.view.ViewGroup
import android.webkit.WebView
import android.webkit.WebViewClient
import android.widget.ArrayAdapter
import android.widget.EditText
import android.widget.ImageButton
@ -33,15 +30,15 @@ import androidx.appcompat.app.AlertDialog
import androidx.core.net.toUri
import androidx.core.view.isVisible
import androidx.fragment.app.Fragment
import bums.lunatic.launcher.LauncherActivity
import bums.lunatic.launcher.LauncherActivity.Companion.getRuntime
import bums.lunatic.launcher.R
import bums.lunatic.launcher.databinding.BooktokiBinding
import bums.lunatic.launcher.home.NeoRssActivity
import bums.lunatic.launcher.home.NeoRssActivity.Companion.getRuntime
import bums.lunatic.launcher.home.toast
import bums.lunatic.launcher.tokiz.view.BWebview
import bums.lunatic.launcher.tokiz.view.JxEvent
import bums.lunatic.launcher.tokiz.view.PagedTextLayout
import bums.lunatic.launcher.tokiz.view.PagedTextViewInterface
import bums.lunatic.launcher.home.tokiz.view.BWebview
import bums.lunatic.launcher.home.tokiz.view.JxEvent
import bums.lunatic.launcher.home.tokiz.view.PagedTextLayout
import bums.lunatic.launcher.home.tokiz.view.PagedTextViewInterface
import bums.lunatic.launcher.utils.Blog
import bums.lunatic.launcher.workers.WorkersDb
import com.google.gson.Gson
@ -655,7 +652,7 @@ abstract class BaseToki : Fragment(), PagedTextViewInterface {
binding.menuWeb
(activity as? LauncherActivity)?.let { activity ->
(activity as? NeoRssActivity)?.let { activity ->
binding.menuWeb.decoViews.add(activity.findViewById<TextView>(R.id.current_address))
binding.menuWeb.decoViews.add(activity.findViewById<ImageButton>(R.id.back))
binding.menuWeb.decoViews.add(activity.findViewById<ImageButton>(R.id.reload))
@ -1197,7 +1194,7 @@ abstract class BaseToki : Fragment(), PagedTextViewInterface {
activity?.runOnUiThread {
view.text = contents
view.visibility = VISIBLE
binding.menuWeb.visibility = View.GONE
binding.menuWeb.visibility = GONE
}
view.forceUpdateUI()
lastedUrl?.let {
@ -1809,7 +1806,7 @@ class Novels : BaseToki(), PagedTextViewInterface {
if (binding.pagedLayer.isVisible) {
binding.pagedLayer.visibility = GONE
}
binding.menuWeb.visibility = View.VISIBLE
binding.menuWeb.visibility = VISIBLE
}
}

View File

@ -1,4 +1,4 @@
package bums.lunatic.launcher.tokiz
package bums.lunatic.launcher.home.tokiz
import android.R
import android.content.Context

View File

@ -1,4 +1,4 @@
package bums.lunatic.launcher.tokiz
package bums.lunatic.launcher.home.tokiz
import android.graphics.Color
import android.os.Build

View File

@ -1,4 +1,4 @@
package bums.lunatic.launcher.tokiz.view
package bums.lunatic.launcher.home.tokiz.view
import android.annotation.SuppressLint
import android.content.Context
@ -25,6 +25,7 @@ import org.mozilla.gecko.util.ThreadUtils.runOnUiThread
import org.mozilla.geckoview.GeckoView
import java.io.File
import java.util.Base64
import kotlin.collections.iterator
enum class JxEvent {
SCROLL_UP,
@ -93,7 +94,7 @@ open class BWebview : GeckoView {
runOnUiThread {
decoViews.filter { it.id == R.id.dl_video }.firstOrNull()?.let {
it.setOnClickListener {}
it.visibility = View.GONE
it.visibility = GONE
}}}
Blog.LOGE("checkIfDownloadable ${url}")
CoroutineScope(Dispatchers.IO).launch {
@ -131,7 +132,11 @@ open class BWebview : GeckoView {
it.setOnClickListener {
videoDlownLoad(url)
}
it.visibility = if (canVideoDown){View.VISIBLE} else{View.GONE}
it.visibility = if (canVideoDown){
VISIBLE
} else{
GONE
}
}
}
}
@ -143,7 +148,7 @@ open class BWebview : GeckoView {
runOnUiThread {
decoViews.filter { it.id == R.id.dl_video }.firstOrNull()?.let {
it.setOnClickListener {}
it.visibility = View.GONE
it.visibility = GONE
}}}
}
}
@ -261,7 +266,7 @@ open class BWebview : GeckoView {
nUrl = lastDomain
}
if (this.isVisible == false) {
this.visibility = View.VISIBLE
this.visibility = VISIBLE
}
Blog.LOGE("nUrl >>>> ${nUrl}")

View File

@ -1,4 +1,4 @@
package bums.lunatic.launcher.tokiz.view
package bums.lunatic.launcher.home.tokiz.view
import android.annotation.TargetApi
import android.content.Context
@ -12,12 +12,11 @@ import android.util.AttributeSet
import android.util.TypedValue
import android.view.View
import android.widget.TextView
import android.widget.TextView.BufferType
import androidx.appcompat.widget.AppCompatTextView
import androidx.constraintlayout.widget.ConstraintLayout
import androidx.constraintlayout.widget.Guideline
import bums.lunatic.launcher.R
import bums.lunatic.launcher.tokiz.TouchArea
import bums.lunatic.launcher.home.tokiz.TouchArea
import bums.lunatic.launcher.utils.Blog
import bums.lunatic.launcher.utils.SimpleFingerGestures
import kotlinx.coroutines.MainScope

View File

@ -1,4 +1,4 @@
package bums.lunatic.launcher.tokiz.view
package bums.lunatic.launcher.home.tokiz.view
import android.content.Context
import android.util.AttributeSet

View File

@ -17,6 +17,7 @@ class SimpleContact : RealmObject {
// [신규] true면 추천 리스트에 절대 안 뜸
var blockRecommend: Boolean = false
constructor(id: String, name: String, phoneNumber: String) {
this.id = id
this.name = name

View File

@ -1,432 +1,432 @@
/*
* Lunar Launcher
* Copyright (C) 2022 Md Rasel Hossain
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package bums.lunatic.launcher.qaccess
import android.Manifest
import android.app.AlertDialog
import android.content.Context
import android.content.Intent
import android.content.SharedPreferences
import android.content.pm.PackageManager
import android.graphics.BlendMode
import android.graphics.BlendModeColorFilter
import android.graphics.Color
import android.graphics.PorterDuff
import android.graphics.Typeface
import android.media.AudioManager
import android.net.Uri
import android.os.Build
import android.os.Bundle
import android.os.PowerManager
import android.provider.Settings
import android.text.InputType
import android.view.Gravity
import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
import android.widget.RelativeLayout
import androidx.appcompat.widget.LinearLayoutCompat
import androidx.core.content.ContextCompat
import bums.lunatic.launcher.LauncherActivity.Companion.lActivity
import bums.lunatic.launcher.R
import bums.lunatic.launcher.databinding.QuickAccessBinding
import bums.lunatic.launcher.databinding.ShortcutMakerBinding
import bums.lunatic.launcher.helpers.ColorPicker
import bums.lunatic.launcher.helpers.Constants.Companion.DEFAULT_ICON_SIZE
import bums.lunatic.launcher.helpers.Constants.Companion.KEY_ICON_SIZE
import bums.lunatic.launcher.helpers.Constants.Companion.KEY_SHORTCUT_COUNT
import bums.lunatic.launcher.helpers.Constants.Companion.KEY_SHORTCUT_NO_
import bums.lunatic.launcher.helpers.Constants.Companion.MAX_SHORTCUTS
import bums.lunatic.launcher.helpers.Constants.Companion.PREFS_SETTINGS
import bums.lunatic.launcher.helpers.Constants.Companion.PREFS_SHORTCUTS
import bums.lunatic.launcher.helpers.Constants.Companion.SEPARATOR
import bums.lunatic.launcher.helpers.Constants.Companion.SHORTCUT_TYPE_PHONE
import bums.lunatic.launcher.helpers.Constants.Companion.SHORTCUT_TYPE_URL
import bums.lunatic.launcher.model.AppInfo
import bums.lunatic.launcher.model.SimpleContact
import bums.lunatic.launcher.utils.Blog
import bums.lunatic.launcher.workers.WorkersDb
import com.google.android.material.bottomsheet.BottomSheetDialog
import com.google.android.material.bottomsheet.BottomSheetDialogFragment
import com.google.android.material.button.MaterialButtonToggleGroup
import com.google.android.material.dialog.MaterialAlertDialogBuilder
import com.google.android.material.slider.Slider
import com.google.android.material.textview.MaterialTextView
import io.realm.kotlin.ext.query
import io.realm.kotlin.query.RealmResults
import java.util.Objects
import kotlin.properties.Delegates
internal class QuickAccess : BottomSheetDialogFragment() {
private lateinit var binding: QuickAccessBinding
private lateinit var sharedPreferences: SharedPreferences
private var iconSize by Delegates.notNull<Int>()
override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View {
binding = QuickAccessBinding.inflate(inflater, container, false)
sharedPreferences = requireContext().getSharedPreferences(PREFS_SHORTCUTS, 0)
iconSize = requireContext().getSharedPreferences(PREFS_SETTINGS, 0).getInt(KEY_ICON_SIZE, DEFAULT_ICON_SIZE)
/* set up volume sliders, brightness slider and favorite apps */
volumeControllers()
controlBrightness()
return binding.root
}
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
super.onViewCreated(view, savedInstanceState)
/* enable dismiss animation */
(requireDialog() as BottomSheetDialog).dismissWithAnimation = true
}
override fun onResume() {
super.onResume()
/* repopulate shortcuts and apps */
shortcuts()
}
/* control the volumes */
private fun volumeControllers() {
val audioManager = lActivity!!.getSystemService(Context.AUDIO_SERVICE) as AudioManager
/* max value */
binding.notification.valueTo = audioManager.getStreamMaxVolume(AudioManager.STREAM_NOTIFICATION).toFloat()
binding.alarm.valueTo = audioManager.getStreamMaxVolume(AudioManager.STREAM_ALARM).toFloat()
binding.media.valueTo = audioManager.getStreamMaxVolume(AudioManager.STREAM_MUSIC).toFloat()
binding.voice.valueTo = audioManager.getStreamMaxVolume(AudioManager.STREAM_VOICE_CALL).toFloat()
binding.ring.valueTo = audioManager.getStreamMaxVolume(AudioManager.STREAM_RING).toFloat()
/* current value */
binding.notification.value = audioManager.getStreamVolume(AudioManager.STREAM_NOTIFICATION).toFloat()
binding.alarm.value = audioManager.getStreamVolume(AudioManager.STREAM_ALARM).toFloat()
binding.media.value = audioManager.getStreamVolume(AudioManager.STREAM_MUSIC).toFloat()
binding.voice.value = audioManager.getStreamVolume(AudioManager.STREAM_VOICE_CALL).toFloat()
binding.ring.value = audioManager.getStreamVolume(AudioManager.STREAM_RING).toFloat()
/* slider change listener for alarm volume */
binding.alarm.addOnChangeListener(Slider.OnChangeListener { _: Slider?, value: Float, _: Boolean ->
audioManager.setStreamVolume(AudioManager.STREAM_ALARM, value.toInt(), 0)
})
/* slider change listener for media volume */
binding.media.addOnChangeListener(Slider.OnChangeListener { _: Slider?, value: Float, _: Boolean ->
audioManager.setStreamVolume(AudioManager.STREAM_MUSIC, value.toInt(), 0)
})
/* slider change listener for voice call volume */
binding.voice.addOnChangeListener(Slider.OnChangeListener { _: Slider?, value: Float, _: Boolean ->
audioManager.setStreamVolume(AudioManager.STREAM_VOICE_CALL, value.toInt(), 0)
})
/* notify and ring volume sliders will work only if
the device isn't in dnd or silent mode */
if (Settings.Global.getInt(lActivity!!.contentResolver, "zen_mode") == 0 &&
audioManager.ringerMode != AudioManager.RINGER_MODE_SILENT) {
/* slider change listener for notify volume */
binding.notification.addOnChangeListener(Slider.OnChangeListener { _: Slider?, value: Float, _: Boolean ->
audioManager.setStreamVolume(AudioManager.STREAM_NOTIFICATION, value.toInt(), 0)
})
/* slider change listener for ring volume */
binding.ring.addOnChangeListener(Slider.OnChangeListener { _: Slider?, value: Float, _: Boolean ->
audioManager.setStreamVolume(AudioManager.STREAM_RING, value.toInt(), 0)
})
} else {
binding.notification.isEnabled = false
binding.ring.isEnabled = false
}
}
/* set up contact and url shortcuts */
private fun shortcuts() {
binding.shortcutsGroup.removeAllViews()
val shortcutCount =
requireContext().getSharedPreferences(PREFS_SETTINGS, 0).getInt(KEY_SHORTCUT_COUNT, MAX_SHORTCUTS)
if (shortcutCount == 0) binding.shortcutsGroup.visibility = View.GONE
for (position in 1..shortcutCount) {
val shortcutValue = sharedPreferences.getString(KEY_SHORTCUT_NO_ + position.toString(), "").toString()
val splitShortcutValue = shortcutValue.split(SEPARATOR).toTypedArray()
var shortcutType = ""
var intentString = ""
var thumbLetter = ""
var color = ""
try {
if (splitShortcutValue.size >= 4) {
shortcutType = splitShortcutValue[0]
intentString = splitShortcutValue[1]
thumbLetter = splitShortcutValue[2]
color = splitShortcutValue[3]
}
} catch (exception : Exception) {
exception.printStackTrace()
}
shortcutsUtil(textView, shortcutType, intentString, thumbLetter, color, position)
}
}
/* control the brightness */
private fun controlBrightness() {
val resolver = lActivity!!.contentResolver
/* set max value */
binding.brightness.valueTo = maxBrightness
/* set slider value to current brightness value */
try {
binding.brightness.value = Settings.System.getInt(resolver, Settings.System.SCREEN_BRIGHTNESS).toFloat()
} catch (settingNotFoundException: Settings.SettingNotFoundException) {
settingNotFoundException.printStackTrace()
}
/* listen slider value changes */
binding.brightness.addOnChangeListener(Slider.OnChangeListener { _: Slider?, value: Float, _: Boolean ->
/* if write settings permission is not allowed already,
again ask for it to be granted */
if (!Settings.System.canWrite(lActivity!!)) {
lActivity!!.startActivity(
Intent(Settings.ACTION_MANAGE_WRITE_SETTINGS)
.setData(Uri.parse("package:" + lActivity!!.packageName))
.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK)
)
/* set the brightness according to the slider value */
} else {
Settings.System.putInt(
resolver,
Settings.System.SCREEN_BRIGHTNESS_MODE,
Settings.System.SCREEN_BRIGHTNESS_MODE_MANUAL
)
Settings.System.putInt(resolver, Settings.System.SCREEN_BRIGHTNESS, value.toInt())
}
})
}
/* contact/url shortcuts */
private fun shortcutsUtil(textView: MaterialTextView, shortcutType: String, intentString: String,
thumbLetter: String, color: String, position: Int) {
/* show plus sign for empty positions and set click listener */
if (intentString.isEmpty()) {
textView.text = "+"
textView.setOnClickListener {
shortcutsSaverDialog(position, "00000000", "", "", "")
}
} else {
/* show thumbnail letter */
textView.text = thumbLetter
/* set background color */
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.Q) {
textView.background.colorFilter =
BlendModeColorFilter(Color.parseColor("#$color"), BlendMode.MULTIPLY)
} else {
@Suppress("DEPRECATION")
textView.background.setColorFilter(Color.parseColor("#$color"), PorterDuff.Mode.MULTIPLY)
}
/* on normal click */
textView.setOnClickListener {
/* type is url */
if (shortcutType == SHORTCUT_TYPE_URL) {
var url = intentString
Blog.LOGE("intentString >>>> ${intentString}")
/* add http before the url if it doesn't have http/https prefix */
if (!url.startsWith("http")) {
// url = "http://$intentString"
/* open the url */
WorkersDb.getRealm().apply {
var result = query<AppInfo>("appName CONTAINS $0 OR koreanName CONTAINS $0", url).find()
if (result.size == 1) {
result.first().pkgName?.let {
try {
context?.startActivity(context?.packageManager?.getLaunchIntentForPackage(it))
}catch (e : Exception) {}
}
} else {
lActivity!!.startActivity(
Intent(Intent.ACTION_VIEW, Uri.parse(url)).setFlags(Intent.FLAG_ACTIVITY_NEW_TASK)
)
}
}
} else {
lActivity!!.startActivity(
Intent(Intent.ACTION_VIEW, Uri.parse(url)).setFlags(Intent.FLAG_ACTIVITY_NEW_TASK)
)
}
/* type is contact */
} else if (shortcutType == SHORTCUT_TYPE_PHONE) {
/* if the necessary permission is not granted already,
ask for it again */
if (lActivity!!.checkSelfPermission(Manifest.permission.CALL_PHONE) != PackageManager.PERMISSION_GRANTED) {
lActivity!!.requestPermissions(arrayOf(Manifest.permission.CALL_PHONE), 1)
} else {
/* make phone call */
WorkersDb.getRealm().writeBlocking {
Blog.LOGE(">>>> ${query<SimpleContact>().query("phoneNumber CONTAINS $0", intentString).description()}")
var result : RealmResults<SimpleContact>? = null
if (intentString.startsWith("0")) {
result = query<SimpleContact>().query("phoneNumber CONTAINS $0 or phoneNumber CONTAINS $1", intentString, intentString.removeRange(0,1)).find()
} else {
result = query<SimpleContact>().query("phoneNumber CONTAINS $0", intentString).find()
}
Blog.LOGE(">>>> ${result.size}")
if(result.size > 0){
result.forEach {
it.touchCount = 1 + it.touchCount
it.lastedTouchDateTime = System.currentTimeMillis()
}
}
}
lActivity!!.startActivity(
Intent(Intent.ACTION_DIAL, Uri.parse("tel:$intentString"))
)
}
}
try {
this.dismissAllowingStateLoss()
} catch (e : Exception) {
}
}
/* reset the shortcut on long click */
textView.setOnLongClickListener {
shortcutsSaverDialog(position, color, thumbLetter, shortcutType, intentString)
true
}
}
}
/* dialog for creating shortcuts */
private fun shortcutsSaverDialog(
position: Int, color: String, thumbLetter: String, shortcutType: String, intentString: String) {
val dialogBinding = ShortcutMakerBinding.inflate(lActivity!!.layoutInflater)
val dialogBuilder = MaterialAlertDialogBuilder(lActivity!!)
.setView(dialogBinding.root)
.setNeutralButton(R.string.delete, null)
.setNegativeButton(android.R.string.cancel, null)
.setPositiveButton(android.R.string.ok, null)
.show()
dialogBinding.thumbField.setText(thumbLetter)
dialogBinding.inputField.setText(intentString)
when (shortcutType) {
SHORTCUT_TYPE_PHONE -> dialogBinding.shortcutType.check(dialogBinding.contact.id)
SHORTCUT_TYPE_URL -> dialogBinding.shortcutType.check(dialogBinding.url.id)
}
/* set up color picker section */
ColorPicker(color, dialogBinding.colorPicker.colorInput, dialogBinding.colorPicker.colorA,
dialogBinding.colorPicker.colorR, dialogBinding.colorPicker.colorG,
dialogBinding.colorPicker.colorB, dialogBinding.root).pickColor()
/* shortcut type chooser - contact/url */
var updatedShortcutType = shortcutType
dialogBinding.shortcutType.addOnButtonCheckedListener {
_: MaterialButtonToggleGroup?, checkedId: Int, isChecked: Boolean ->
if (isChecked) {
when (checkedId) {
dialogBinding.contact.id -> {
updatedShortcutType = SHORTCUT_TYPE_PHONE
dialogBinding.inputField.inputType = InputType.TYPE_CLASS_PHONE
}
dialogBinding.url.id -> {
updatedShortcutType = SHORTCUT_TYPE_URL
dialogBinding.inputField.inputType = InputType.TYPE_TEXT_VARIATION_URI
}
}
}
}
dialogBuilder.getButton(AlertDialog.BUTTON_NEUTRAL).setOnClickListener {
sharedPreferences.edit().remove(KEY_SHORTCUT_NO_ + position).apply()
dialogBuilder.dismiss()
this.onResume()
}
/* save the shortcut values */
dialogBuilder.getButton(AlertDialog.BUTTON_POSITIVE).setOnClickListener {
/* get shortcut value */
val updatedIntentString =
Objects.requireNonNull(dialogBinding.inputField.text).toString().trim { it <= ' ' }
/* get thumbnail letter */
val updatedThumbLetter =
Objects.requireNonNull(dialogBinding.thumbField.text).toString().trim { it <= ' ' }.uppercase()
/* get color value */
val updatedColor =
Objects.requireNonNull(dialogBinding.colorPicker.colorInput.text).toString().trim { it <= ' ' }
/* save the values if every field is filled */
if (updatedShortcutType.isNotEmpty() && updatedIntentString.isNotEmpty() &&
updatedThumbLetter.isNotEmpty() && updatedColor.isNotEmpty()) {
sharedPreferences.edit().putString(KEY_SHORTCUT_NO_ + position,
"$updatedShortcutType$SEPARATOR$updatedIntentString$SEPARATOR" +
"$updatedThumbLetter$SEPARATOR$updatedColor").apply()
dialogBuilder.dismiss()
this.onResume()
}
}
}
/* create text view for shortcut thumbnails */
private val textView: MaterialTextView get() {
val relativeLayout = RelativeLayout(lActivity!!)
relativeLayout.apply {
layoutParams = LinearLayoutCompat.LayoutParams(
LinearLayoutCompat.LayoutParams.WRAP_CONTENT,
LinearLayoutCompat.LayoutParams.WRAP_CONTENT, 1F)
gravity = Gravity.CENTER
}
binding.shortcutsGroup.addView(relativeLayout)
MaterialTextView(requireContext()).apply {
layoutParams = LinearLayoutCompat.LayoutParams(
(iconSize * resources.displayMetrics.density).toInt(),
(iconSize * resources.displayMetrics.density).toInt())
gravity = Gravity.CENTER
textSize = (iconSize / 4) * resources.displayMetrics.density
setTypeface(null, Typeface.BOLD)
background = ContextCompat.getDrawable(requireContext(), R.drawable.rounded_bg)
}.let {
relativeLayout.addView(it)
return it
}
}
/* returns maximum brightness value of the device */
private val maxBrightness: Float get() {
val powerManager = requireContext().getSystemService(Context.POWER_SERVICE) as PowerManager
var value = 255f
for (f in powerManager.javaClass.declaredFields) {
if (f.name.equals("BRIGHTNESS_ON")) {
f.isAccessible = true
value = try {
f.getInt(powerManager).toFloat()
} catch (e: IllegalAccessException) {
255f
}
}
}
return value
}
}
///*
// * Lunar Launcher
// * Copyright (C) 2022 Md Rasel Hossain
// *
// * This program is free software: you can redistribute it and/or modify
// * it under the terms of the GNU General Public License as published by
// * the Free Software Foundation, either version 3 of the License, or
// * (at your option) any later version.
// *
// * This program is distributed in the hope that it will be useful,
// * but WITHOUT ANY WARRANTY; without even the implied warranty of
// * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// * GNU General Public License for more details.
// *
// * You should have received a copy of the GNU General Public License
// * along with this program. If not, see <http://www.gnu.org/licenses/>.
// */
//
//package bums.lunatic.launcher.qaccess
//
//import android.Manifest
//import android.app.AlertDialog
//import android.content.Context
//import android.content.Intent
//import android.content.SharedPreferences
//import android.content.pm.PackageManager
//import android.graphics.BlendMode
//import android.graphics.BlendModeColorFilter
//import android.graphics.Color
//import android.graphics.PorterDuff
//import android.graphics.Typeface
//import android.media.AudioManager
//import android.net.Uri
//import android.os.Build
//import android.os.Bundle
//import android.os.PowerManager
//import android.provider.Settings
//import android.text.InputType
//import android.view.Gravity
//import android.view.LayoutInflater
//import android.view.View
//import android.view.ViewGroup
//import android.widget.RelativeLayout
//import androidx.appcompat.widget.LinearLayoutCompat
//import androidx.core.content.ContextCompat
//import bums.lunatic.launcher.LauncherActivity.Companion.lActivity
//import bums.lunatic.launcher.R
//import bums.lunatic.launcher.databinding.QuickAccessBinding
//import bums.lunatic.launcher.databinding.ShortcutMakerBinding
//import bums.lunatic.launcher.helpers.ColorPicker
//import bums.lunatic.launcher.helpers.Constants.Companion.DEFAULT_ICON_SIZE
//import bums.lunatic.launcher.helpers.Constants.Companion.KEY_ICON_SIZE
//import bums.lunatic.launcher.helpers.Constants.Companion.KEY_SHORTCUT_COUNT
//import bums.lunatic.launcher.helpers.Constants.Companion.KEY_SHORTCUT_NO_
//import bums.lunatic.launcher.helpers.Constants.Companion.MAX_SHORTCUTS
//import bums.lunatic.launcher.helpers.Constants.Companion.PREFS_SETTINGS
//import bums.lunatic.launcher.helpers.Constants.Companion.PREFS_SHORTCUTS
//import bums.lunatic.launcher.helpers.Constants.Companion.SEPARATOR
//import bums.lunatic.launcher.helpers.Constants.Companion.SHORTCUT_TYPE_PHONE
//import bums.lunatic.launcher.helpers.Constants.Companion.SHORTCUT_TYPE_URL
//import bums.lunatic.launcher.model.AppInfo
//import bums.lunatic.launcher.model.SimpleContact
//import bums.lunatic.launcher.utils.Blog
//import bums.lunatic.launcher.workers.WorkersDb
//import com.google.android.material.bottomsheet.BottomSheetDialog
//import com.google.android.material.bottomsheet.BottomSheetDialogFragment
//import com.google.android.material.button.MaterialButtonToggleGroup
//import com.google.android.material.dialog.MaterialAlertDialogBuilder
//import com.google.android.material.slider.Slider
//import com.google.android.material.textview.MaterialTextView
//import io.realm.kotlin.ext.query
//import io.realm.kotlin.query.RealmResults
//import java.util.Objects
//import kotlin.properties.Delegates
//
//
//internal class QuickAccess : BottomSheetDialogFragment() {
//
// private lateinit var binding: QuickAccessBinding
// private lateinit var sharedPreferences: SharedPreferences
// private var iconSize by Delegates.notNull<Int>()
//
// override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View {
// binding = QuickAccessBinding.inflate(inflater, container, false)
//
// sharedPreferences = requireContext().getSharedPreferences(PREFS_SHORTCUTS, 0)
// iconSize = requireContext().getSharedPreferences(PREFS_SETTINGS, 0).getInt(KEY_ICON_SIZE, DEFAULT_ICON_SIZE)
//
// /* set up volume sliders, brightness slider and favorite apps */
// volumeControllers()
// controlBrightness()
//
// return binding.root
// }
//
// override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
// super.onViewCreated(view, savedInstanceState)
// /* enable dismiss animation */
// (requireDialog() as BottomSheetDialog).dismissWithAnimation = true
// }
//
// override fun onResume() {
// super.onResume()
// /* repopulate shortcuts and apps */
// shortcuts()
// }
//
// /* control the volumes */
// private fun volumeControllers() {
// val audioManager = lActivity!!.getSystemService(Context.AUDIO_SERVICE) as AudioManager
// /* max value */
// binding.notification.valueTo = audioManager.getStreamMaxVolume(AudioManager.STREAM_NOTIFICATION).toFloat()
// binding.alarm.valueTo = audioManager.getStreamMaxVolume(AudioManager.STREAM_ALARM).toFloat()
// binding.media.valueTo = audioManager.getStreamMaxVolume(AudioManager.STREAM_MUSIC).toFloat()
// binding.voice.valueTo = audioManager.getStreamMaxVolume(AudioManager.STREAM_VOICE_CALL).toFloat()
// binding.ring.valueTo = audioManager.getStreamMaxVolume(AudioManager.STREAM_RING).toFloat()
// /* current value */
// binding.notification.value = audioManager.getStreamVolume(AudioManager.STREAM_NOTIFICATION).toFloat()
// binding.alarm.value = audioManager.getStreamVolume(AudioManager.STREAM_ALARM).toFloat()
// binding.media.value = audioManager.getStreamVolume(AudioManager.STREAM_MUSIC).toFloat()
// binding.voice.value = audioManager.getStreamVolume(AudioManager.STREAM_VOICE_CALL).toFloat()
// binding.ring.value = audioManager.getStreamVolume(AudioManager.STREAM_RING).toFloat()
//
// /* slider change listener for alarm volume */
// binding.alarm.addOnChangeListener(Slider.OnChangeListener { _: Slider?, value: Float, _: Boolean ->
// audioManager.setStreamVolume(AudioManager.STREAM_ALARM, value.toInt(), 0)
// })
//
// /* slider change listener for media volume */
// binding.media.addOnChangeListener(Slider.OnChangeListener { _: Slider?, value: Float, _: Boolean ->
// audioManager.setStreamVolume(AudioManager.STREAM_MUSIC, value.toInt(), 0)
// })
//
// /* slider change listener for voice call volume */
// binding.voice.addOnChangeListener(Slider.OnChangeListener { _: Slider?, value: Float, _: Boolean ->
// audioManager.setStreamVolume(AudioManager.STREAM_VOICE_CALL, value.toInt(), 0)
// })
//
// /* notify and ring volume sliders will work only if
// the device isn't in dnd or silent mode */
// if (Settings.Global.getInt(lActivity!!.contentResolver, "zen_mode") == 0 &&
// audioManager.ringerMode != AudioManager.RINGER_MODE_SILENT) {
// /* slider change listener for notify volume */
// binding.notification.addOnChangeListener(Slider.OnChangeListener { _: Slider?, value: Float, _: Boolean ->
// audioManager.setStreamVolume(AudioManager.STREAM_NOTIFICATION, value.toInt(), 0)
// })
// /* slider change listener for ring volume */
// binding.ring.addOnChangeListener(Slider.OnChangeListener { _: Slider?, value: Float, _: Boolean ->
// audioManager.setStreamVolume(AudioManager.STREAM_RING, value.toInt(), 0)
// })
// } else {
// binding.notification.isEnabled = false
// binding.ring.isEnabled = false
// }
// }
//
// /* set up contact and url shortcuts */
// private fun shortcuts() {
// binding.shortcutsGroup.removeAllViews()
// val shortcutCount =
// requireContext().getSharedPreferences(PREFS_SETTINGS, 0).getInt(KEY_SHORTCUT_COUNT, MAX_SHORTCUTS)
// if (shortcutCount == 0) binding.shortcutsGroup.visibility = View.GONE
//
// for (position in 1..shortcutCount) {
// val shortcutValue = sharedPreferences.getString(KEY_SHORTCUT_NO_ + position.toString(), "").toString()
// val splitShortcutValue = shortcutValue.split(SEPARATOR).toTypedArray()
//
// var shortcutType = ""
// var intentString = ""
// var thumbLetter = ""
// var color = ""
//
// try {
// if (splitShortcutValue.size >= 4) {
// shortcutType = splitShortcutValue[0]
// intentString = splitShortcutValue[1]
// thumbLetter = splitShortcutValue[2]
// color = splitShortcutValue[3]
// }
// } catch (exception : Exception) {
// exception.printStackTrace()
// }
//
// shortcutsUtil(textView, shortcutType, intentString, thumbLetter, color, position)
// }
// }
//
// /* control the brightness */
// private fun controlBrightness() {
// val resolver = lActivity!!.contentResolver
// /* set max value */
// binding.brightness.valueTo = maxBrightness
//
// /* set slider value to current brightness value */
// try {
// binding.brightness.value = Settings.System.getInt(resolver, Settings.System.SCREEN_BRIGHTNESS).toFloat()
// } catch (settingNotFoundException: Settings.SettingNotFoundException) {
// settingNotFoundException.printStackTrace()
// }
//
// /* listen slider value changes */
// binding.brightness.addOnChangeListener(Slider.OnChangeListener { _: Slider?, value: Float, _: Boolean ->
// /* if write settings permission is not allowed already,
// again ask for it to be granted */
// if (!Settings.System.canWrite(lActivity!!)) {
// lActivity!!.startActivity(
// Intent(Settings.ACTION_MANAGE_WRITE_SETTINGS)
// .setData(Uri.parse("package:" + lActivity!!.packageName))
// .addFlags(Intent.FLAG_ACTIVITY_NEW_TASK)
// )
// /* set the brightness according to the slider value */
// } else {
// Settings.System.putInt(
// resolver,
// Settings.System.SCREEN_BRIGHTNESS_MODE,
// Settings.System.SCREEN_BRIGHTNESS_MODE_MANUAL
// )
// Settings.System.putInt(resolver, Settings.System.SCREEN_BRIGHTNESS, value.toInt())
// }
// })
// }
//
// /* contact/url shortcuts */
// private fun shortcutsUtil(textView: MaterialTextView, shortcutType: String, intentString: String,
// thumbLetter: String, color: String, position: Int) {
// /* show plus sign for empty positions and set click listener */
// if (intentString.isEmpty()) {
// textView.text = "+"
// textView.setOnClickListener {
// shortcutsSaverDialog(position, "00000000", "", "", "")
// }
// } else {
// /* show thumbnail letter */
// textView.text = thumbLetter
// /* set background color */
// if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.Q) {
// textView.background.colorFilter =
// BlendModeColorFilter(Color.parseColor("#$color"), BlendMode.MULTIPLY)
// } else {
// @Suppress("DEPRECATION")
// textView.background.setColorFilter(Color.parseColor("#$color"), PorterDuff.Mode.MULTIPLY)
// }
//
// /* on normal click */
// textView.setOnClickListener {
// /* type is url */
// if (shortcutType == SHORTCUT_TYPE_URL) {
// var url = intentString
// Blog.LOGE("intentString >>>> ${intentString}")
// /* add http before the url if it doesn't have http/https prefix */
// if (!url.startsWith("http")) {
//// url = "http://$intentString"
// /* open the url */
// WorkersDb.getRealm().apply {
// var result = query<AppInfo>("appName CONTAINS $0 OR koreanName CONTAINS $0", url).find()
// if (result.size == 1) {
// result.first().pkgName?.let {
// try {
// context?.startActivity(context?.packageManager?.getLaunchIntentForPackage(it))
// }catch (e : Exception) {}
// }
// } else {
// lActivity!!.startActivity(
// Intent(Intent.ACTION_VIEW, Uri.parse(url)).setFlags(Intent.FLAG_ACTIVITY_NEW_TASK)
// )
// }
// }
// } else {
// lActivity!!.startActivity(
// Intent(Intent.ACTION_VIEW, Uri.parse(url)).setFlags(Intent.FLAG_ACTIVITY_NEW_TASK)
// )
// }
//
// /* type is contact */
// } else if (shortcutType == SHORTCUT_TYPE_PHONE) {
// /* if the necessary permission is not granted already,
// ask for it again */
// if (lActivity!!.checkSelfPermission(Manifest.permission.CALL_PHONE) != PackageManager.PERMISSION_GRANTED) {
// lActivity!!.requestPermissions(arrayOf(Manifest.permission.CALL_PHONE), 1)
// } else {
// /* make phone call */
//
// WorkersDb.getRealm().writeBlocking {
// Blog.LOGE(">>>> ${query<SimpleContact>().query("phoneNumber CONTAINS $0", intentString).description()}")
// var result : RealmResults<SimpleContact>? = null
// if (intentString.startsWith("0")) {
// result = query<SimpleContact>().query("phoneNumber CONTAINS $0 or phoneNumber CONTAINS $1", intentString, intentString.removeRange(0,1)).find()
// } else {
// result = query<SimpleContact>().query("phoneNumber CONTAINS $0", intentString).find()
// }
// Blog.LOGE(">>>> ${result.size}")
// if(result.size > 0){
// result.forEach {
// it.touchCount = 1 + it.touchCount
// it.lastedTouchDateTime = System.currentTimeMillis()
// }
// }
// }
// lActivity!!.startActivity(
// Intent(Intent.ACTION_DIAL, Uri.parse("tel:$intentString"))
// )
// }
// }
// try {
// this.dismissAllowingStateLoss()
// } catch (e : Exception) {
//
// }
// }
//
// /* reset the shortcut on long click */
// textView.setOnLongClickListener {
// shortcutsSaverDialog(position, color, thumbLetter, shortcutType, intentString)
// true
// }
// }
// }
//
// /* dialog for creating shortcuts */
// private fun shortcutsSaverDialog(
// position: Int, color: String, thumbLetter: String, shortcutType: String, intentString: String) {
// val dialogBinding = ShortcutMakerBinding.inflate(lActivity!!.layoutInflater)
// val dialogBuilder = MaterialAlertDialogBuilder(lActivity!!)
// .setView(dialogBinding.root)
// .setNeutralButton(R.string.delete, null)
// .setNegativeButton(android.R.string.cancel, null)
// .setPositiveButton(android.R.string.ok, null)
// .show()
//
// dialogBinding.thumbField.setText(thumbLetter)
// dialogBinding.inputField.setText(intentString)
// when (shortcutType) {
// SHORTCUT_TYPE_PHONE -> dialogBinding.shortcutType.check(dialogBinding.contact.id)
// SHORTCUT_TYPE_URL -> dialogBinding.shortcutType.check(dialogBinding.url.id)
// }
//
// /* set up color picker section */
// ColorPicker(color, dialogBinding.colorPicker.colorInput, dialogBinding.colorPicker.colorA,
// dialogBinding.colorPicker.colorR, dialogBinding.colorPicker.colorG,
// dialogBinding.colorPicker.colorB, dialogBinding.root).pickColor()
//
// /* shortcut type chooser - contact/url */
// var updatedShortcutType = shortcutType
// dialogBinding.shortcutType.addOnButtonCheckedListener {
// _: MaterialButtonToggleGroup?, checkedId: Int, isChecked: Boolean ->
// if (isChecked) {
// when (checkedId) {
// dialogBinding.contact.id -> {
// updatedShortcutType = SHORTCUT_TYPE_PHONE
// dialogBinding.inputField.inputType = InputType.TYPE_CLASS_PHONE
// }
// dialogBinding.url.id -> {
// updatedShortcutType = SHORTCUT_TYPE_URL
// dialogBinding.inputField.inputType = InputType.TYPE_TEXT_VARIATION_URI
// }
// }
// }
// }
//
// dialogBuilder.getButton(AlertDialog.BUTTON_NEUTRAL).setOnClickListener {
// sharedPreferences.edit().remove(KEY_SHORTCUT_NO_ + position).apply()
// dialogBuilder.dismiss()
// this.onResume()
// }
//
// /* save the shortcut values */
// dialogBuilder.getButton(AlertDialog.BUTTON_POSITIVE).setOnClickListener {
// /* get shortcut value */
// val updatedIntentString =
// Objects.requireNonNull(dialogBinding.inputField.text).toString().trim { it <= ' ' }
// /* get thumbnail letter */
// val updatedThumbLetter =
// Objects.requireNonNull(dialogBinding.thumbField.text).toString().trim { it <= ' ' }.uppercase()
// /* get color value */
// val updatedColor =
// Objects.requireNonNull(dialogBinding.colorPicker.colorInput.text).toString().trim { it <= ' ' }
//
// /* save the values if every field is filled */
// if (updatedShortcutType.isNotEmpty() && updatedIntentString.isNotEmpty() &&
// updatedThumbLetter.isNotEmpty() && updatedColor.isNotEmpty()) {
// sharedPreferences.edit().putString(KEY_SHORTCUT_NO_ + position,
// "$updatedShortcutType$SEPARATOR$updatedIntentString$SEPARATOR" +
// "$updatedThumbLetter$SEPARATOR$updatedColor").apply()
// dialogBuilder.dismiss()
// this.onResume()
// }
// }
// }
//
// /* create text view for shortcut thumbnails */
// private val textView: MaterialTextView get() {
// val relativeLayout = RelativeLayout(lActivity!!)
// relativeLayout.apply {
// layoutParams = LinearLayoutCompat.LayoutParams(
// LinearLayoutCompat.LayoutParams.WRAP_CONTENT,
// LinearLayoutCompat.LayoutParams.WRAP_CONTENT, 1F)
// gravity = Gravity.CENTER
// }
// binding.shortcutsGroup.addView(relativeLayout)
//
// MaterialTextView(requireContext()).apply {
// layoutParams = LinearLayoutCompat.LayoutParams(
// (iconSize * resources.displayMetrics.density).toInt(),
// (iconSize * resources.displayMetrics.density).toInt())
// gravity = Gravity.CENTER
// textSize = (iconSize / 4) * resources.displayMetrics.density
// setTypeface(null, Typeface.BOLD)
// background = ContextCompat.getDrawable(requireContext(), R.drawable.rounded_bg)
// }.let {
// relativeLayout.addView(it)
// return it
// }
// }
//
// /* returns maximum brightness value of the device */
// private val maxBrightness: Float get() {
// val powerManager = requireContext().getSystemService(Context.POWER_SERVICE) as PowerManager
// var value = 255f
// for (f in powerManager.javaClass.declaredFields) {
// if (f.name.equals("BRIGHTNESS_ON")) {
// f.isAccessible = true
// value = try {
// f.getInt(powerManager).toFloat()
// } catch (e: IllegalAccessException) {
// 255f
// }
// }
// }
// return value
// }
//
//}

View File

@ -6,15 +6,10 @@ import android.content.pm.ApplicationInfo
import android.content.pm.PackageManager
import android.content.pm.ResolveInfo
import android.os.Build
import androidx.work.WorkerParameters
import bums.lunatic.launcher.BuildConfig
import bums.lunatic.launcher.LauncherActivity.Companion.lActivity
import bums.lunatic.launcher.apps.AppDrawer.Companion.appNamesPrefs
import bums.lunatic.launcher.model.AppInfo
import bums.lunatic.launcher.utils.AlphabetToChosungMap
import bums.lunatic.launcher.utils.Blog
import bums.lunatic.launcher.utils.JamoUtils
import io.realm.kotlin.ext.query
import io.realm.kotlin.types.RealmObject
import java.text.Normalizer
import java.util.regex.Pattern
@ -31,7 +26,7 @@ class AppInfoGetter : BaseGetter {
override fun realWork(): List<RealmObject> {
var result = mutableListOf<RealmObject>()
try {
val packageManager = lActivity?.packageManager ?: return result
val packageManager = context.packageManager ?: return result
// 1. 설치된 앱 목록 가져오기 (시스템 호출 1회)
val intent = Intent(Intent.ACTION_MAIN, null).addCategory(Intent.CATEGORY_LAUNCHER)
@ -44,9 +39,6 @@ class AppInfoGetter : BaseGetter {
resolveInfos.forEach { ri ->
val pkgName = ri.activityInfo.packageName
if (pkgName == BuildConfig.APPLICATION_ID) return@forEach
// 이미 DB에 있는지 Map에서 확인 (고속 검색)
// 신규 앱 발견 -> 추가
val appName = normalize(appName(ri))
result.add(AppInfo().apply {
@ -67,9 +59,10 @@ class AppInfoGetter : BaseGetter {
fun appName(resolver: ResolveInfo): String {
return resolver.loadLabel(lActivity?.packageManager!!).toString().apply {
appNamesPrefs?.edit()?.putString(resolver.activityInfo.packageName, this)?.apply()
}
return resolver.loadLabel(context.packageManager!!).toString()
// .apply {
// appNamesPrefs?.edit()?.putString(resolver.activityInfo.packageName, this)?.apply()
// }
}
fun getCategory(category : Int) : String {

View File

@ -2,8 +2,6 @@ package bums.lunatic.launcher.workers
import android.content.Context
import android.provider.ContactsContract
import androidx.work.WorkerParameters
import bums.lunatic.launcher.LauncherActivity.Companion.lActivity
import bums.lunatic.launcher.model.SimpleContact
import bums.lunatic.launcher.utils.Blog
import io.realm.kotlin.ext.query
@ -25,7 +23,7 @@ class ContactInfoGetter(context: Context) : BaseGetter(context) {
try {
lActivity?.contentResolver?.query(phoneUri, projection, null, null, null)?.use { cursor ->
context.applicationContext?.contentResolver?.query(phoneUri, projection, null, null, null)?.use { cursor ->
val idIdx = cursor.getColumnIndex(projection[0])
val nameIdx = cursor.getColumnIndex(projection[1])
val numberIdx = cursor.getColumnIndex(projection[2])

View File

@ -4,6 +4,7 @@ import android.annotation.SuppressLint
import android.content.Context
import androidx.work.WorkerParameters
import bums.lunatic.launcher.LauncherActivity
import bums.lunatic.launcher.home.NeoRssActivity
import bums.lunatic.launcher.model.RssDataType
import bums.lunatic.launcher.utils.Blog
import io.realm.kotlin.types.RealmObject
@ -26,7 +27,7 @@ class DotaxGetter(context: Context) : BaseGetter(context) {
temp.clear()
CoroutineScope(Dispatchers.Main).launch {
withContext(Dispatchers.Main) {
LauncherActivity.lActivity?.let {
NeoRssActivity.lActivity?.let {
it.contentsLoad("https://m.cafe.daum.net/dotax/Elgq")
}
}

View File

@ -4,7 +4,6 @@ import android.annotation.SuppressLint
import android.content.Context
import android.provider.CallLog
import androidx.work.WorkerParameters
import bums.lunatic.launcher.LauncherActivity.Companion.lActivity
import bums.lunatic.launcher.utils.beforeDay
import bums.lunatic.launcher.utils.getContactId
import com.google.gson.Gson
@ -46,72 +45,72 @@ class RecentCall : RealmObject {
}
}
class RecentCallGetter(context: Context) : BaseGetter(context) {
companion object{
var dayRange = BaseGetter.defaultDay
val TAG = "RecentCallGetter"
val dateFormat = SimpleDateFormat("yyy/MM/dd-HH:mm:ss")
}
@SuppressLint("RestrictedApi")
override fun realWork(): List<RealmObject> {
var temp = mutableListOf<RecentCall>()
var dateParam = beforeDay(dayRange).toString()
var managedCursor = lActivity?.contentResolver?.query(
CallLog.Calls.CONTENT_URI, arrayOf(
CallLog.Calls.NUMBER,
CallLog.Calls.TYPE,
CallLog.Calls.DATE,
CallLog.Calls.DURATION,
CallLog.Calls.CACHED_NAME,
), CallLog.Calls.DATE + " >= ? " , arrayOf<String>(dateParam), CallLog.Calls.DATE + " desc")
if(managedCursor != null && managedCursor.isClosed == false) {
try {
val number = managedCursor.getColumnIndex(CallLog.Calls.NUMBER)
val type = managedCursor.getColumnIndex(CallLog.Calls.TYPE)
val date = managedCursor.getColumnIndex(CallLog.Calls.DATE)
val duration = managedCursor.getColumnIndex(CallLog.Calls.DURATION)
val name = managedCursor.getColumnIndex(CallLog.Calls.CACHED_NAME)
while (managedCursor.moveToNext()) {
val phNumber = managedCursor.getString(number) // mobile number
val callType = managedCursor.getString(type) // call type
val callDate = managedCursor.getString(date) // call date
val callDayTime = callDate.toLong()
val callDuration = managedCursor.getString(duration)
val callerName = managedCursor.getString(name)
var dir: String = ""
val dircode = callType.toInt()
when (dircode) {
CallLog.Calls.INCOMING_TYPE -> { dir = "INCOMING_TYPE" }
CallLog.Calls.OUTGOING_TYPE -> { dir = "OUTGOING_TYPE" }
CallLog.Calls.MISSED_TYPE -> { dir = "MISSED_TYPE" }
CallLog.Calls.VOICEMAIL_TYPE -> { dir = "VOICEMAIL_TYPE" }
CallLog.Calls.REJECTED_TYPE -> { dir = "REJECTED_TYPE" }
CallLog.Calls.BLOCKED_TYPE -> { dir = "BLOCKED_TYPE" }
CallLog.Calls.ANSWERED_EXTERNALLY_TYPE -> { dir = "ANSWERED_EXTERNALLY_TYPE" }
}
temp.add(RecentCall(
1,
callerName,
phNumber,
dircode,
dir,
dateFormat.format(Date(callDayTime)),
callDayTime,
callDuration.toLong()
))
}
} catch (e: Exception) {
e.printStackTrace()
} finally {
managedCursor.close()
}
}
return temp
}
}
//
//class RecentCallGetter(context: Context) : BaseGetter(context) {
// companion object{
// var dayRange = BaseGetter.defaultDay
// val TAG = "RecentCallGetter"
// val dateFormat = SimpleDateFormat("yyy/MM/dd-HH:mm:ss")
// }
//
// @SuppressLint("RestrictedApi")
// override fun realWork(): List<RealmObject> {
// var temp = mutableListOf<RecentCall>()
// var dateParam = beforeDay(dayRange).toString()
// var managedCursor = lActivity?.contentResolver?.query(
// CallLog.Calls.CONTENT_URI, arrayOf(
// CallLog.Calls.NUMBER,
// CallLog.Calls.TYPE,
// CallLog.Calls.DATE,
// CallLog.Calls.DURATION,
// CallLog.Calls.CACHED_NAME,
// ), CallLog.Calls.DATE + " >= ? " , arrayOf<String>(dateParam), CallLog.Calls.DATE + " desc")
//
// if(managedCursor != null && managedCursor.isClosed == false) {
// try {
// val number = managedCursor.getColumnIndex(CallLog.Calls.NUMBER)
// val type = managedCursor.getColumnIndex(CallLog.Calls.TYPE)
// val date = managedCursor.getColumnIndex(CallLog.Calls.DATE)
// val duration = managedCursor.getColumnIndex(CallLog.Calls.DURATION)
// val name = managedCursor.getColumnIndex(CallLog.Calls.CACHED_NAME)
// while (managedCursor.moveToNext()) {
// val phNumber = managedCursor.getString(number) // mobile number
// val callType = managedCursor.getString(type) // call type
// val callDate = managedCursor.getString(date) // call date
// val callDayTime = callDate.toLong()
// val callDuration = managedCursor.getString(duration)
// val callerName = managedCursor.getString(name)
//
// var dir: String = ""
// val dircode = callType.toInt()
// when (dircode) {
// CallLog.Calls.INCOMING_TYPE -> { dir = "INCOMING_TYPE" }
// CallLog.Calls.OUTGOING_TYPE -> { dir = "OUTGOING_TYPE" }
// CallLog.Calls.MISSED_TYPE -> { dir = "MISSED_TYPE" }
// CallLog.Calls.VOICEMAIL_TYPE -> { dir = "VOICEMAIL_TYPE" }
// CallLog.Calls.REJECTED_TYPE -> { dir = "REJECTED_TYPE" }
// CallLog.Calls.BLOCKED_TYPE -> { dir = "BLOCKED_TYPE" }
// CallLog.Calls.ANSWERED_EXTERNALLY_TYPE -> { dir = "ANSWERED_EXTERNALLY_TYPE" }
// }
// temp.add(RecentCall(
// 1,
// callerName,
// phNumber,
// dircode,
// dir,
// dateFormat.format(Date(callDayTime)),
// callDayTime,
// callDuration.toLong()
// ))
//
// }
// } catch (e: Exception) {
// e.printStackTrace()
// } finally {
// managedCursor.close()
// }
// }
// return temp
// }
//
//}

View File

@ -1,107 +1,116 @@
package bums.lunatic.launcher.workers
import android.annotation.SuppressLint
import android.content.ContentResolver
import android.content.Context
import android.database.Cursor
import android.net.Uri
import android.provider.Telephony
import androidx.work.WorkerParameters
import bums.lunatic.launcher.LauncherActivity.Companion.lActivity
import bums.lunatic.launcher.utils.beforeDay
import bums.lunatic.launcher.utils.getContactName
import bums.lunatic.launcher.workers.RecentSmsGetter.Companion.dayRange
import com.google.gson.Gson
import io.realm.kotlin.ext.query
import io.realm.kotlin.ext.realmListOf
import io.realm.kotlin.types.RealmList
import io.realm.kotlin.types.RealmObject
import io.realm.kotlin.types.annotations.Ignore
import io.realm.kotlin.types.annotations.PrimaryKey
import java.io.BufferedReader
import java.io.IOException
import java.io.InputStream
import java.io.InputStreamReader
class RecentSmsGetter(context: Context) : BaseGetter(context) {
companion object {
var dayRange = BaseGetter.defaultDay
val SMS_WORK_TAG = "RecentSmsGetter"
}
@SuppressLint("RestrictedApi")
override fun realWork(): List<RealmObject> {
var temp = mutableListOf<RecentSms>()
var dateParam = beforeDay(dayRange).toString()
val managedCursor = lActivity?.contentResolver?.query(
Telephony.Sms.CONTENT_URI, arrayOf(
Telephony.Sms.THREAD_ID,
Telephony.Sms.ADDRESS,
Telephony.Sms.TYPE,
Telephony.Sms.DATE,
Telephony.Sms.DATE_SENT,
Telephony.Sms.BODY,
Telephony.Sms.PERSON,
), Telephony.Sms.DATE + "> ${dateParam}", null, Telephony.Sms.DEFAULT_SORT_ORDER)
if (managedCursor != null && managedCursor.isClosed == false) {
try {
val tid = managedCursor.getColumnIndex(Telephony.Sms.THREAD_ID)
val address = managedCursor.getColumnIndex(Telephony.Sms.ADDRESS)
val type = managedCursor.getColumnIndex(Telephony.Sms.TYPE)
val date = managedCursor.getColumnIndex(Telephony.Sms.DATE)
val sendDate = managedCursor.getColumnIndex(Telephony.Sms.DATE_SENT)
val bodyIdx = managedCursor.getColumnIndex(Telephony.Sms.BODY)
val name = managedCursor.getColumnIndex(Telephony.Sms.PERSON)
while (managedCursor.moveToNext()) {
val id = managedCursor.getString(tid) // mobile number
val phNumber = managedCursor.getString(address) // mobile number
val callType = managedCursor.getString(type) // call type
val reciveDate = managedCursor.getLong(date) // call date
val sendedDate = managedCursor.getLong(sendDate) // call date
val smsBody = managedCursor.getString(bodyIdx).replace("\n"," ")
val callerName = managedCursor.getString(name)
var dir: String = ""
val dircode = callType.toInt()
when (dircode) {
Telephony.Sms.MESSAGE_TYPE_ALL -> {dir = "MESSAGE_TYPE_ALL"}
Telephony.Sms.MESSAGE_TYPE_INBOX -> {dir = "MESSAGE_TYPE_INBOX"}
Telephony.Sms.MESSAGE_TYPE_SENT -> {dir = "MESSAGE_TYPE_SENT"}
Telephony.Sms.MESSAGE_TYPE_DRAFT -> {dir = "MESSAGE_TYPE_DRAFT"}
Telephony.Sms.MESSAGE_TYPE_OUTBOX -> {dir = "MESSAGE_TYPE_OUTBOX"}
Telephony.Sms.MESSAGE_TYPE_FAILED -> {dir = "MESSAGE_TYPE_FAILED"}
Telephony.Sms.MESSAGE_TYPE_QUEUED -> {dir = "MESSAGE_TYPE_QUEUED"}
}
var log = RecentSms(
id.plus("_").plus(reciveDate).plus("_").plus(sendedDate),
phNumber,
dir,
reciveDate,
sendedDate,
smsBody,
callerName ?: ""
)
log.isMms = false
// BLog.LOGE("RecentSmsGetter resultData put ${phNumber +"_"+ reciveDate} >>> ${log.toJson()}")
log.sender = getContactName(context.applicationContext.contentResolver,phNumber) ?: ""
temp.add(log)
}
} catch (e: Exception) {
} finally {
managedCursor.close()
}
}
if (lActivity?.contentResolver != null) {
MmsQueryHelper(lActivity?.contentResolver!!).query()
}
return temp
}
}
internal class RecentSms : RealmObject {
//
//import android.annotation.SuppressLint
//import android.content.ContentResolver
//import android.content.Context
//import android.database.Cursor
//import android.net.Uri
//import android.provider.Telephony
//import androidx.work.WorkerParameters
//import bums.lunatic.launcher.LauncherActivity.Companion.lActivity
//import bums.lunatic.launcher.utils.beforeDay
//import bums.lunatic.launcher.utils.getContactName
//import bums.lunatic.launcher.workers.RecentSmsGetter.Companion.dayRange
//import com.google.gson.Gson
//import io.realm.kotlin.ext.query
//import io.realm.kotlin.ext.realmListOf
//import io.realm.kotlin.types.RealmList
//import io.realm.kotlin.types.RealmObject
//import io.realm.kotlin.types.annotations.Ignore
//import io.realm.kotlin.types.annotations.PrimaryKey
//import java.io.BufferedReader
//import java.io.IOException
//import java.io.InputStream
//import java.io.InputStreamReader
//
//class RecentSmsGetter(context: Context) : BaseGetter(context) {
// companion object {
// var dayRange = BaseGetter.defaultDay
// val SMS_WORK_TAG = "RecentSmsGetter"
// }
//
//
// @SuppressLint("RestrictedApi")
// override fun realWork(): List<RealmObject> {
// var temp = mutableListOf<RecentSms>()
// var dateParam = beforeDay(dayRange).toString()
// val managedCursor = lActivity?.contentResolver?.query(
// Telephony.Sms.CONTENT_URI, arrayOf(
// Telephony.Sms.THREAD_ID,
// Telephony.Sms.ADDRESS,
// Telephony.Sms.TYPE,
// Telephony.Sms.DATE,
// Telephony.Sms.DATE_SENT,
// Telephony.Sms.BODY,
// Telephony.Sms.PERSON,
// ), Telephony.Sms.DATE + "> ${dateParam}", null, Telephony.Sms.DEFAULT_SORT_ORDER)
// if (managedCursor != null && managedCursor.isClosed == false) {
// try {
// val tid = managedCursor.getColumnIndex(Telephony.Sms.THREAD_ID)
// val address = managedCursor.getColumnIndex(Telephony.Sms.ADDRESS)
// val type = managedCursor.getColumnIndex(Telephony.Sms.TYPE)
// val date = managedCursor.getColumnIndex(Telephony.Sms.DATE)
// val sendDate = managedCursor.getColumnIndex(Telephony.Sms.DATE_SENT)
// val bodyIdx = managedCursor.getColumnIndex(Telephony.Sms.BODY)
// val name = managedCursor.getColumnIndex(Telephony.Sms.PERSON)
// while (managedCursor.moveToNext()) {
// val id = managedCursor.getString(tid) // mobile number
// val phNumber = managedCursor.getString(address) // mobile number
// val callType = managedCursor.getString(type) // call type
// val reciveDate = managedCursor.getLong(date) // call date
// val sendedDate = managedCursor.getLong(sendDate) // call date
// val smsBody = managedCursor.getString(bodyIdx).replace("\n"," ")
// val callerName = managedCursor.getString(name)
//
// var dir: String = ""
// val dircode = callType.toInt()
// when (dircode) {
// Telephony.Sms.MESSAGE_TYPE_ALL -> {dir = "MESSAGE_TYPE_ALL"}
// Telephony.Sms.MESSAGE_TYPE_INBOX -> {dir = "MESSAGE_TYPE_INBOX"}
// Telephony.Sms.MESSAGE_TYPE_SENT -> {dir = "MESSAGE_TYPE_SENT"}
// Telephony.Sms.MESSAGE_TYPE_DRAFT -> {dir = "MESSAGE_TYPE_DRAFT"}
// Telephony.Sms.MESSAGE_TYPE_OUTBOX -> {dir = "MESSAGE_TYPE_OUTBOX"}
// Telephony.Sms.MESSAGE_TYPE_FAILED -> {dir = "MESSAGE_TYPE_FAILED"}
// Telephony.Sms.MESSAGE_TYPE_QUEUED -> {dir = "MESSAGE_TYPE_QUEUED"}
// }
// var log = RecentSms(
// id.plus("_").plus(reciveDate).plus("_").plus(sendedDate),
// phNumber,
// dir,
// reciveDate,
// sendedDate,
// smsBody,
// callerName ?: ""
// )
// log.isMms = false
//// BLog.LOGE("RecentSmsGetter resultData put ${phNumber +"_"+ reciveDate} >>> ${log.toJson()}")
// log.sender = getContactName(context.applicationContext.contentResolver,phNumber) ?: ""
// temp.add(log)
// }
// } catch (e: Exception) {
//
// } finally {
// managedCursor.close()
// }
// }
// if (lActivity?.contentResolver != null) {
// MmsQueryHelper(lActivity?.contentResolver!!).query()
// }
// return temp
// }
//
//}
//
//internal
class RecentSms : RealmObject {
@PrimaryKey
var uniqKey : String = ""
@ -164,199 +173,199 @@ internal class RecentSms : RealmObject {
return Gson().toJson(this)
}
}
internal class MmsQueryHelper(
private val _contentResolver: ContentResolver
) {
private val mmsUri: Uri = Telephony.Mms.CONTENT_URI
private val cursor: Cursor?
get() =
_contentResolver.query(
mmsUri,
null,
null,
null,
null
)
fun dataMapper(cursor: Cursor): RecentSms {
val id = cursor.getInt(cursor.getColumnIndexOrThrow(Telephony.Mms._ID))
val date = cursor.getLong(cursor.getColumnIndexOrThrow(Telephony.Mms.DATE)) * 1000
val sender : String = getSender(id) ?: throw NullPointerException("NotFound Sender For Mms")
val body = getBody(id) ?: throw NullPointerException("NotFound Body by Mms")
return RecentSms(
id = id.toString(),
date = date,
body = body,
sender = sender
).apply {
isMms = true
this.sender = getContactName(_contentResolver,addr) ?: ""
}
}
private fun getSender(id: Int): String? {
_contentResolver.query(
Uri.parse("content://mms/$id/addr"),
null,
"${Telephony.Mms.Addr.MSG_ID} = ?",
arrayOf(id.toString()),
null
)?.use { senderAddressCursor ->
if (senderAddressCursor.moveToFirst()) {
do {
// 137 수신, 151 발신 타입 값이다. Telephony.Mms.Addr.Type 의 주석 참고.
val isSender = senderAddressCursor.getInt(
senderAddressCursor.getColumnIndexOrThrow(Telephony.Mms.Addr.TYPE)
) == 137
var sender = senderAddressCursor.getString(
senderAddressCursor.getColumnIndexOrThrow(Telephony.Mms.Addr.ADDRESS)
)
// BLog.LOGE("sender >> ${sender}")
if (isSender) {
return sender
}
} while (senderAddressCursor.moveToNext())
}
}
return null
}
private fun getMmsText(id: String): String {
val partURI = Uri.parse("content://mms/part/$id")
var `is`: InputStream? = null
val sb = StringBuilder()
try {
`is` = _contentResolver.openInputStream(partURI)
if (`is` != null) {
val isr = InputStreamReader(`is`, "UTF-8")
val reader = BufferedReader(isr)
var temp = reader.readLine()
while (temp != null) {
sb.append(temp)
temp = reader.readLine()
}
}
} catch (e: IOException) {
} finally {
if (`is` != null) {
try {
`is`.close()
} catch (e: IOException) {
}
}
}
return sb.toString()
}
private fun getBody(id: Int): HashMap<String?,ArrayList<String>> {
var returns = hashMapOf<String?,ArrayList<String>>()
val text = arrayListOf<String>()
val image = arrayListOf<String>()
val audio = arrayListOf<String>()
val partsIds = arrayListOf<String>()
partsIds.add(id.toString())
val projection = arrayOf("*")
val video = arrayListOf<String>()
_contentResolver.query(
Uri.parse("content://mms/part"),
projection,
"${Telephony.Mms.Part.MSG_ID} = ?",
arrayOf(id.toString()),
null
)?.use { partsCursor ->
if (partsCursor.moveToFirst()) {
do {
val partId: String = partsCursor.getString(partsCursor.getColumnIndexOrThrow(
Telephony.Mms.Part._ID))
val partContentType =
partsCursor.getString(partsCursor.getColumnIndexOrThrow(Telephony.Mms.Part.CONTENT_TYPE))
// BLog.LOGE("partContentType >> ${partContentType}")
partsIds.add(partId.toString())
if(partContentType?.contains("text") == true) {
// BLog.LOGE("partContentType text >> ${partContentType} :: ${partId}")
val data =
partsCursor.getString(partsCursor.getColumnIndexOrThrow(Telephony.Mms.Part._DATA))
val textBody =
partsCursor.getString(partsCursor.getColumnIndexOrThrow(Telephony.Mms.Part.TEXT))
if (data != null && data.length > 0) {
text.add(getMmsText(partId))
} else {
text.add(textBody)
}
}
else if(partContentType?.contains("image") == true) {
// BLog.LOGE("partContentType image >> ${partContentType}:: ${partId}")
image.add(partId)
}
else if(partContentType?.contains("audio") == true) {
// BLog.LOGE("partContentType audio >> ${partContentType}:: ${partId}")
audio.add(partId)
}
else if(partContentType?.contains("video") == true) {
// BLog.LOGE("partContentType video >> ${partContentType}:: ${partId}")
video.add(partId)
}
else {
// BLog.LOGE("partContentType >> ${partContentType}:: ${partId}")
}
// if (partContentType == "text/plain") {
// var textBody =
// partsCursor.getString(partsCursor.getColumnIndexOrThrow(Telephony.Mms.Part.TEXT))
//// .replace("\n\n", "\n").replace("\n", " ")
//// if (textBody.length > 60) {
//// textBody = textBody.substring(0, Math.min(textBody.length, 60)).plus(" ... ")
//// }
//// BLog.LOGE("textBody >>> ${textBody}")
// return Pair(textBody , partContentType)
//
//internal class MmsQueryHelper(
// private val _contentResolver: ContentResolver
//) {
//
// private val mmsUri: Uri = Telephony.Mms.CONTENT_URI
// private val cursor: Cursor?
// get() =
// _contentResolver.query(
// mmsUri,
// null,
// null,
// null,
// null
// )
//
// fun dataMapper(cursor: Cursor): RecentSms {
// val id = cursor.getInt(cursor.getColumnIndexOrThrow(Telephony.Mms._ID))
// val date = cursor.getLong(cursor.getColumnIndexOrThrow(Telephony.Mms.DATE)) * 1000
// val sender : String = getSender(id) ?: throw NullPointerException("NotFound Sender For Mms")
// val body = getBody(id) ?: throw NullPointerException("NotFound Body by Mms")
//
// return RecentSms(
// id = id.toString(),
// date = date,
// body = body,
// sender = sender
// ).apply {
// isMms = true
// this.sender = getContactName(_contentResolver,addr) ?: ""
// }
// }
//
// private fun getSender(id: Int): String? {
// _contentResolver.query(
// Uri.parse("content://mms/$id/addr"),
// null,
// "${Telephony.Mms.Addr.MSG_ID} = ?",
// arrayOf(id.toString()),
// null
// )?.use { senderAddressCursor ->
// if (senderAddressCursor.moveToFirst()) {
// do {
// // 137 수신, 151 발신 타입 값이다. Telephony.Mms.Addr.Type 의 주석 참고.
// val isSender = senderAddressCursor.getInt(
// senderAddressCursor.getColumnIndexOrThrow(Telephony.Mms.Addr.TYPE)
// ) == 137
// var sender = senderAddressCursor.getString(
// senderAddressCursor.getColumnIndexOrThrow(Telephony.Mms.Addr.ADDRESS)
// )
//// BLog.LOGE("sender >> ${sender}")
// if (isSender) {
// return sender
// }
} while (partsCursor.moveToNext())
}
}
returns.put("partId", partsIds)
returns.put("text", text)
returns.put("image", image)
returns.put("audio", audio)
returns.put("video", video)
// BLog.LOGE("returns.get(text).join => ${text.size} :: ${text.joinToString("\n")}")
return returns
}
fun convertData(cursor: Cursor?) {
cursor ?: return
val dateTime = beforeDay(dayRange)
cursor.use {
if (cursor.moveToFirst()) {
do {
val data = kotlin.runCatching {
dataMapper(cursor)
}.getOrNull()
data?.let {
if (it?.pstDate ?: 0L > dateTime || it?.rcvDate ?: 0L > dateTime) {
WorkersDb.getRealm().apply {
if (query<RecentSms>("uniqKey == $0", it.uniqKey).find().size == 0) {
writeBlocking {
copyToRealm(it)
}
}
// else if (it.isMms && it.addr.contains("#CMAS#")){
// } while (senderAddressCursor.moveToNext())
// }
// }
// return null
// }
//
// private fun getMmsText(id: String): String {
// val partURI = Uri.parse("content://mms/part/$id")
// var `is`: InputStream? = null
// val sb = StringBuilder()
// try {
// `is` = _contentResolver.openInputStream(partURI)
// if (`is` != null) {
// val isr = InputStreamReader(`is`, "UTF-8")
// val reader = BufferedReader(isr)
// var temp = reader.readLine()
// while (temp != null) {
// sb.append(temp)
// temp = reader.readLine()
// }
// }
// } catch (e: IOException) {
// } finally {
// if (`is` != null) {
// try {
// `is`.close()
// } catch (e: IOException) {
// }
// }
// }
// return sb.toString()
// }
// private fun getBody(id: Int): HashMap<String?,ArrayList<String>> {
// var returns = hashMapOf<String?,ArrayList<String>>()
// val text = arrayListOf<String>()
// val image = arrayListOf<String>()
// val audio = arrayListOf<String>()
// val partsIds = arrayListOf<String>()
// partsIds.add(id.toString())
// val projection = arrayOf("*")
// val video = arrayListOf<String>()
// _contentResolver.query(
// Uri.parse("content://mms/part"),
// projection,
// "${Telephony.Mms.Part.MSG_ID} = ?",
// arrayOf(id.toString()),
// null
// )?.use { partsCursor ->
// if (partsCursor.moveToFirst()) {
// do {
// val partId: String = partsCursor.getString(partsCursor.getColumnIndexOrThrow(
// Telephony.Mms.Part._ID))
// val partContentType =
// partsCursor.getString(partsCursor.getColumnIndexOrThrow(Telephony.Mms.Part.CONTENT_TYPE))
//// BLog.LOGE("partContentType >> ${partContentType}")
// partsIds.add(partId.toString())
// if(partContentType?.contains("text") == true) {
//// BLog.LOGE("partContentType text >> ${partContentType} :: ${partId}")
// val data =
// partsCursor.getString(partsCursor.getColumnIndexOrThrow(Telephony.Mms.Part._DATA))
// val textBody =
// partsCursor.getString(partsCursor.getColumnIndexOrThrow(Telephony.Mms.Part.TEXT))
// if (data != null && data.length > 0) {
// text.add(getMmsText(partId))
// } else {
// text.add(textBody)
// }
// }
// else if(partContentType?.contains("image") == true) {
//// BLog.LOGE("partContentType image >> ${partContentType}:: ${partId}")
// image.add(partId)
// }
// else if(partContentType?.contains("audio") == true) {
//// BLog.LOGE("partContentType audio >> ${partContentType}:: ${partId}")
// audio.add(partId)
// }
// else if(partContentType?.contains("video") == true) {
//// BLog.LOGE("partContentType video >> ${partContentType}:: ${partId}")
// video.add(partId)
// }
// else {
//// BLog.LOGE("partContentType >> ${partContentType}:: ${partId}")
// }
//
//// if (partContentType == "text/plain") {
//// var textBody =
//// partsCursor.getString(partsCursor.getColumnIndexOrThrow(Telephony.Mms.Part.TEXT))
////// .replace("\n\n", "\n").replace("\n", " ")
////// if (textBody.length > 60) {
////// textBody = textBody.substring(0, Math.min(textBody.length, 60)).plus(" ... ")
////// }
////// BLog.LOGE("textBody >>> ${textBody}")
//// return Pair(textBody , partContentType)
//// }
// } while (partsCursor.moveToNext())
// }
// }
// returns.put("partId", partsIds)
// returns.put("text", text)
// returns.put("image", image)
// returns.put("audio", audio)
// returns.put("video", video)
//// BLog.LOGE("returns.get(text).join => ${text.size} :: ${text.joinToString("\n")}")
// return returns
// }
//
// fun convertData(cursor: Cursor?) {
// cursor ?: return
// val dateTime = beforeDay(dayRange)
// cursor.use {
// if (cursor.moveToFirst()) {
// do {
// val data = kotlin.runCatching {
// dataMapper(cursor)
// }.getOrNull()
// data?.let {
// if (it?.pstDate ?: 0L > dateTime || it?.rcvDate ?: 0L > dateTime) {
// WorkersDb.getRealm().apply {
// if (query<RecentSms>("uniqKey == $0", it.uniqKey).find().size == 0) {
// writeBlocking {
// it.uniqKey = it.uniqKey.plus("1")
// copyToRealm(it)
// }
// }
}
// smsList.add(it)
}
}
} while (cursor.moveToNext())
}
}
}
fun query() {
return convertData(cursor)
}
}
//// else if (it.isMms && it.addr.contains("#CMAS#")){
//// writeBlocking {
//// it.uniqKey = it.uniqKey.plus("1")
//// copyToRealm(it)
//// }
//// }
// }
//// smsList.add(it)
// }
// }
// } while (cursor.moveToNext())
// }
// }
// }
// fun query() {
// return convertData(cursor)
// }
//
//}

View File

@ -28,7 +28,8 @@ object TaskAggregator {
// 2. [일괄 저장 및 병합] 트랜잭션 시작
realm.write {
var oldA = 0
var newA = 0
// --- [A] 앱 정보 병합 (AppInfo) ---
// DB에 있는 기존 앱들을 패키지명(Key) 기준으로 Map 생성
val existingAppsMap = query<AppInfo>(AppInfo::class).find().associateBy { it.pkgName }
@ -38,57 +39,46 @@ object TaskAggregator {
val pkgName = newApp.pkgName ?: return@forEach
activeAppPkgNames.add(pkgName)
// 기존 데이터가 있으면 카운트 정보 이식
val oldApp = existingAppsMap[pkgName]
if (oldApp != null) {
newApp.clickCount = oldApp.clickCount
newApp.lastUseDate = oldApp.lastUseDate
newApp.visibilityMode = oldApp.visibilityMode
newApp.blockRecommend = oldApp.blockRecommend
// 즐겨찾기 여부 등 보존해야 할 다른 필드가 있다면 여기서 복사
// newApp.isFavorite = oldApp.isFavorite
if (existingAppsMap.contains(pkgName)) {
existingAppsMap.get(pkgName)?.let { oldApp->
newApp.clickCount = oldApp.clickCount
newApp.lastUseDate = oldApp.lastUseDate
newApp.visibilityMode = oldApp.visibilityMode
newApp.blockRecommend = oldApp.blockRecommend
oldA += 1
}
} else {
newA += 1
}
// 병합된 데이터 저장 (덮어쓰기)
copyToRealm(newApp, UpdatePolicy.ALL)
}
Blog.LOGE("scannedApps Size ${scannedApps.size} OLD APP UPDATE ${oldA} NEW APP INSERT ${newA} TOTAL ${oldA + newA}")
// 삭제된 앱 처리 (시스템 스캔 목록에 없는 앱은 DB에서 삭제)
val appsToDelete = query<AppInfo>(AppInfo::class).find().filter {
!activeAppPkgNames.contains(it.pkgName)
}
appsToDelete.forEach { delete(it) }
// --- [B] 연락처 정보 병합 (SimpleContact) ---
// DB에 있는 기존 연락처들을 ID(Key) 기준으로 Map 생성
// (SimpleContact의 PrimaryKey가 id라고 가정)
val existingContactsMap = query<SimpleContact>(SimpleContact::class).find().associateBy { it.id }
val activeContactIds = HashSet<String>()
oldA = 0
newA = 0
scannedContacts.forEach { newContact ->
// SimpleContact 타입 캐스팅 (fetchData 반환형이 List<RealmObject>이므로)
val contact = newContact as? SimpleContact ?: return@forEach
val contactId = contact.id ?: return@forEach
activeContactIds.add(contactId)
val oldContact = existingContactsMap[contactId]
if (oldContact != null) {
contact.touchCount = oldContact.touchCount
contact.lastedTouchDateTime = oldContact.lastedTouchDateTime
contact.visibilityMode = oldContact.visibilityMode
contact.blockRecommend = oldContact.blockRecommend
if (existingContactsMap.contains(contactId)) {
existingContactsMap.get(contactId)?.let { oldContact->
contact.touchCount = oldContact.touchCount
contact.lastedTouchDateTime = oldContact.lastedTouchDateTime
contact.visibilityMode = oldContact.visibilityMode
contact.blockRecommend = oldContact.blockRecommend
oldA += 1
}
} else {
newA += 1
}
copyToRealm(contact, UpdatePolicy.ALL)
}
// 삭제된 연락처 처리
// val contactsToDelete = query<SimpleContact>(SimpleContact::class).find().filter {
// !activeContactIds.contains(it.id)
// }
// contactsToDelete.forEach { delete(it) }
Blog.LOGE("scannedContacts Size ${scannedContacts.size} OLD APP UPDATE ${oldA} NEW APP INSERT ${newA} TOTAL ${oldA + newA}")
}

View File

@ -29,11 +29,11 @@ import bums.lunatic.launcher.model.TelegramFrom
import bums.lunatic.launcher.model.TelegramMessage
import bums.lunatic.launcher.model.WeatherForcast
import bums.lunatic.launcher.model.WidgetData
import bums.lunatic.launcher.tokiz.ContentsCollection
import bums.lunatic.launcher.tokiz.ContentsPageInfo
import bums.lunatic.launcher.tokiz.HistoryItem
import bums.lunatic.launcher.tokiz.LastInfo
import bums.lunatic.launcher.tokiz.ReaderConfig
import bums.lunatic.launcher.home.tokiz.ContentsCollection
import bums.lunatic.launcher.home.tokiz.ContentsPageInfo
import bums.lunatic.launcher.home.tokiz.HistoryItem
import bums.lunatic.launcher.home.tokiz.LastInfo
import bums.lunatic.launcher.home.tokiz.ReaderConfig
import bums.lunatic.launcher.utils.Blog
import bums.lunatic.launcher.utils.JamoUtils
import bums.lunatic.launcher.utils.afterDay
@ -293,29 +293,7 @@ object WorkersDb {
}
}
fun update(info: AppInfo) {
getRealm().apply {
this.writeBlocking {
try {
this.copyToRealm(info, UpdatePolicy.ALL)
} catch (e : Exception) {
e.printStackTrace()
}
}
}
}
fun update(contact: SimpleContact) {
getRealm().apply {
this.writeBlocking {
try {
this.copyToRealm(contact, UpdatePolicy.ALL)
} catch (e : Exception) {
e.printStackTrace()
}
}
}
}
fun insertCall(contact: RecentCall) {
getRealm().apply {
this.writeBlocking {

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:drawable="@drawable/bg_circle_emoji_red" android:state_selected="true"/>
<item android:drawable="@drawable/bg_circle_emoji"/>
</selector>

View File

@ -0,0 +1,28 @@
<?xml version="1.0" encoding="utf-8"?>
<ripple xmlns:android="http://schemas.android.com/apk/res/android"
android:color="#4DFFFFFF"> <item android:id="@android:id/mask">
<shape android:shape="rectangle">
<solid android:color="#FFFFFF" />
<corners
android:topLeftRadius="2dp"
android:topRightRadius="8dp"
android:bottomLeftRadius="8dp"
android:bottomRightRadius="2dp" />
</shape>
</item>
<item>
<shape android:shape="rectangle">
<solid android:color="#26FFFFFF" />
<stroke
android:width="1dp"
android:color="#1AFFFFFF" />
<corners
android:topLeftRadius="2dp"
android:topRightRadius="8dp"
android:bottomLeftRadius="8dp"
android:bottomRightRadius="2dp" />
</shape>
</item>
</ripple>

View File

@ -8,7 +8,7 @@
android:layout_height="match_parent"
>
<bums.lunatic.launcher.tokiz.view.BWebview
<bums.lunatic.launcher.home.tokiz.view.BWebview
android:id="@+id/menu_web"
android:layout_margin="5dp"
android:layout_width="match_parent"
@ -86,7 +86,7 @@
/>
<bums.lunatic.launcher.tokiz.view.PagedTextLayout
<bums.lunatic.launcher.home.tokiz.view.PagedTextLayout
android:id="@+id/paged_layer"
android:layout_margin="1dp"
android:layout_width="0dp"

View File

@ -126,26 +126,64 @@
</androidx.constraintlayout.widget.ConstraintLayout>
</androidx.core.widget.NestedScrollView>
<LinearLayout
android:id="@+id/quickSearch"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="horizontal"
android:background="@drawable/bg_grid_item"
android:gravity="center_vertical"
app:layout_constraintBottom_toBottomOf="parent">
<HorizontalScrollView
android:layout_width="wrap_content"
app:layout_constraintLeft_toLeftOf="parent"
app:layout_constraintRight_toRightOf="parent"
app:layout_constraintBottom_toBottomOf="parent"
android:layout_height="wrap_content">
<LinearLayout
android:id="@+id/quickSearch"
android:layout_width="wrap_content"
android:layout_height="30dp"
android:orientation="horizontal"
android:background="@color/black"
android:gravity="center_vertical"
>
<TextView
style="@style/SearchAccs"
app:autoSizeTextType="uniform"
android:id="@+id/search_tmap"
android:text="TMAP"
/>
<bums.lunatic.launcher.view.CircleImageView
android:id="@+id/search_nmap"
style="@style/SearchIcons"
android:src="@drawable/navermap"/>
<bums.lunatic.launcher.view.CircleImageView
android:id="@+id/search_naver"
style="@style/SearchIcons"
android:src="@drawable/naver"/>
<bums.lunatic.launcher.view.CircleImageView
android:id="@+id/search_youtube"
style="@style/SearchIcons"
android:src="@drawable/youtube"/>
</LinearLayout>
<TextView
style="@style/SearchAccs"
app:autoSizeTextType="uniform"
android:id="@+id/search_music"
android:text="SPOTIFY"
/>
<TextView
style="@style/SearchAccs"
app:autoSizeTextType="uniform"
android:id="@+id/search_taxi"
android:text="TAXI"
/>
<TextView
style="@style/SearchAccs"
app:autoSizeTextType="uniform"
android:id="@+id/search_youtube"
android:text="YOUTUBE"
/>
<TextView
style="@style/SearchAccs"
app:autoSizeTextType="uniform"
android:id="@+id/search_nmap"
android:text="NMAP"
/>
<TextView
style="@style/SearchAccs"
app:autoSizeTextType="uniform"
android:id="@+id/search_naver"
android:text="NAVER"
/>
<TextView
style="@style/SearchAccs"
app:autoSizeTextType="uniform"
android:id="@+id/hidden"
android:text="HIDDEN"
/>
</LinearLayout>
</HorizontalScrollView>
</androidx.constraintlayout.widget.ConstraintLayout>

View File

@ -32,166 +32,5 @@
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintEnd_toEndOf="parent"
android:layout_marginTop="10dp"/>
<LinearLayout
android:id="@+id/fragment_layer"
android:orientation="vertical"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:clipChildren="false"
android:visibility="visible"
app:layout_constraintTop_toTopOf="parent"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintEnd_toEndOf="parent" >
<androidx.fragment.app.FragmentContainerView
android:id="@+id/fragment_container"
android:visibility="gone"
android:layout_weight="1"
android:layout_width="match_parent"
android:layout_height="0dp" />
<LinearLayout
android:id="@+id/controll_panel"
android:visibility="gone"
android:layout_width="match_parent"
android:layout_height="40dp">
<ImageButton
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintTop_toBottomOf="@id/fragment_container"
app:layout_constraintLeft_toLeftOf="parent"
android:id="@+id/back"
android:src="@drawable/back_vector"
tools:ignore="ContentDescription"
style="@style/CommonBottom" />
<ImageButton
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintTop_toBottomOf="@id/fragment_container"
app:layout_constraintLeft_toRightOf="@id/back"
android:id="@+id/reload"
android:src="@drawable/ic_refresh"
tools:ignore="ContentDescription"
style="@style/CommonBottom"/>
<TextView
android:text="asdasdsadasd"
android:layout_weight="1"
android:id="@+id/current_address"
app:layout_constraintTop_toTopOf="@id/back"
app:layout_constraintRight_toLeftOf="@id/dl_video"
app:layout_constraintLeft_toRightOf="@id/reload"
android:textColor="@color/white"
android:gravity="center"
android:textSize="@dimen/_12sp"
android:ellipsize="middle"
app:layout_constraintRight_toRightOf="parent"
android:layout_width="0dp"
android:layout_height="@dimen/main_top_height"/>
<ImageButton
app:layout_constraintTop_toTopOf="@id/back"
app:layout_constraintRight_toLeftOf="@id/share"
app:layout_constraintBottom_toBottomOf="parent"
android:id="@+id/dl_video"
android:src="@drawable/dl_vid"
tools:ignore="ContentDescription"
style="@style/CommonBottom"/>
<ImageButton
app:layout_constraintTop_toTopOf="@id/back"
app:layout_constraintRight_toRightOf="parent"
app:layout_constraintBottom_toBottomOf="parent"
android:layout_marginRight="60dp"
android:id="@+id/share"
android:foregroundTint="@color/white"
android:src="@drawable/ic_share"
tools:ignore="ContentDescription"
style="@style/CommonBottom"/>
</LinearLayout>
</LinearLayout>
<bums.lunatic.launcher.view.FloatingActionMenu
android:id="@+id/floating_action_menu"
android:layout_margin="5dp"
android:visibility="gone"
app:menu_colorNormal="#80FF0000"
app:menu_fab_size="mini"
app:menu_icon="@drawable/ic_add"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintRight_toRightOf="parent"
android:layout_height="match_parent"
android:layout_width="match_parent"
>
<bums.lunatic.launcher.view.FloatingActionButton
app:fab_label="feeds"
android:id="@+id/feeds"
app:fab_showShadow="true"
app:fab_size="mini"
android:onClick="floatClick"
android:layout_width="wrap_content"
android:layout_height="20dp"/>
<bums.lunatic.launcher.view.FloatingActionButton
app:fab_label="booktoki"
android:id="@+id/books"
app:fab_showShadow="true"
app:fab_size="mini"
android:onClick="floatClick"
android:layout_width="wrap_content"
android:layout_height="20dp"/>
<bums.lunatic.launcher.view.FloatingActionButton
app:fab_label="newtoki"
android:id="@+id/webtoons"
app:fab_showShadow="true"
app:fab_size="mini"
android:onClick="floatClick"
android:layout_width="wrap_content"
android:layout_height="20dp"/>
<bums.lunatic.launcher.view.FloatingActionButton
app:fab_label="manatoki"
android:id="@+id/comics"
app:fab_showShadow="true"
app:fab_size="mini"
android:onClick="floatClick"
android:layout_width="wrap_content"
android:layout_height="20dp"/>
<bums.lunatic.launcher.view.FloatingActionButton
app:fab_label="youtube"
android:id="@+id/youtube"
app:fab_showShadow="true"
app:fab_size="mini"
android:onClick="floatClick"
android:layout_width="wrap_content"
android:layout_height="20dp"/>
<bums.lunatic.launcher.view.FloatingActionButton
app:fab_label="perplexity"
android:id="@+id/perplexity"
app:fab_showShadow="true"
app:fab_size="mini"
android:onClick="floatClick"
android:layout_width="wrap_content"
android:layout_height="20dp"/>
<bums.lunatic.launcher.view.FloatingActionButton
app:fab_label="짤방"
android:id="@+id/zota"
app:fab_showShadow="true"
app:fab_size="mini"
android:onClick="floatClick"
android:layout_width="wrap_content"
android:layout_height="20dp"/>
<bums.lunatic.launcher.view.FloatingActionButton
app:fab_label="setting"
android:id="@+id/setting"
app:fab_showShadow="true"
app:fab_size="mini"
android:onClick="floatClick"
android:layout_width="wrap_content"
android:layout_height="20dp"/>
<bums.lunatic.launcher.view.FloatingActionButton
app:fab_label="close"
android:id="@+id/close"
app:fab_showShadow="true"
app:fab_size="mini"
android:onClick="floatClick"
android:layout_width="wrap_content"
android:layout_height="20dp"/>
</bums.lunatic.launcher.view.FloatingActionMenu>
</androidx.constraintlayout.widget.ConstraintLayout>

View File

@ -13,7 +13,7 @@
android:orientation="horizontal"
android:layout_width="match_parent"
android:layout_height="match_parent">
<bums.lunatic.launcher.tokiz.view.PagedTextView
<bums.lunatic.launcher.home.tokiz.view.PagedTextView
android:layout_margin="5dp"
android:id="@+id/hidden_view"
android:visibility="visible"

View File

@ -0,0 +1,174 @@
<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:background="@android:color/transparent"
android:orientation="vertical"
android:id="@+id/mainFragmentsContainer"
>
<LinearLayout
android:id="@+id/fragment_layer"
android:orientation="vertical"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:clipChildren="false"
android:visibility="visible"
app:layout_constraintTop_toTopOf="parent"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintEnd_toEndOf="parent" >
<androidx.fragment.app.FragmentContainerView
android:id="@+id/fragment_container"
android:visibility="visible"
android:layout_weight="1"
android:layout_width="match_parent"
android:layout_height="0dp" />
<LinearLayout
android:id="@+id/controll_panel"
android:visibility="visible"
android:layout_width="match_parent"
android:layout_height="40dp">
<ImageButton
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintTop_toBottomOf="@id/fragment_container"
app:layout_constraintLeft_toLeftOf="parent"
android:id="@+id/back"
android:src="@drawable/back_vector"
tools:ignore="ContentDescription"
style="@style/CommonBottom" />
<ImageButton
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintTop_toBottomOf="@id/fragment_container"
app:layout_constraintLeft_toRightOf="@id/back"
android:id="@+id/reload"
android:src="@drawable/ic_refresh"
tools:ignore="ContentDescription"
style="@style/CommonBottom"/>
<TextView
android:text="asdasdsadasd"
android:layout_weight="1"
android:id="@+id/current_address"
app:layout_constraintTop_toTopOf="@id/back"
app:layout_constraintRight_toLeftOf="@id/dl_video"
app:layout_constraintLeft_toRightOf="@id/reload"
android:textColor="@color/white"
android:gravity="center"
android:textSize="@dimen/_12sp"
android:ellipsize="middle"
app:layout_constraintRight_toRightOf="parent"
android:layout_width="0dp"
android:layout_height="@dimen/main_top_height"/>
<ImageButton
app:layout_constraintTop_toTopOf="@id/back"
app:layout_constraintRight_toLeftOf="@id/share"
app:layout_constraintBottom_toBottomOf="parent"
android:id="@+id/dl_video"
android:src="@drawable/dl_vid"
tools:ignore="ContentDescription"
style="@style/CommonBottom"/>
<ImageButton
app:layout_constraintTop_toTopOf="@id/back"
app:layout_constraintRight_toRightOf="parent"
app:layout_constraintBottom_toBottomOf="parent"
android:layout_marginRight="60dp"
android:id="@+id/share"
android:foregroundTint="@color/white"
android:src="@drawable/ic_share"
tools:ignore="ContentDescription"
style="@style/CommonBottom"/>
</LinearLayout>
</LinearLayout>
<bums.lunatic.launcher.view.FloatingActionMenu
android:id="@+id/floating_action_menu"
android:layout_margin="5dp"
android:visibility="visible"
app:menu_colorNormal="#80FF0000"
app:menu_fab_size="mini"
app:menu_icon="@drawable/ic_add"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintRight_toRightOf="parent"
android:layout_height="match_parent"
android:layout_width="match_parent"
>
<bums.lunatic.launcher.view.FloatingActionButton
app:fab_label="feeds"
android:id="@+id/feeds"
app:fab_showShadow="true"
app:fab_size="mini"
android:onClick="floatClick"
android:layout_width="wrap_content"
android:layout_height="20dp"/>
<bums.lunatic.launcher.view.FloatingActionButton
app:fab_label="booktoki"
android:id="@+id/books"
app:fab_showShadow="true"
app:fab_size="mini"
android:onClick="floatClick"
android:layout_width="wrap_content"
android:layout_height="20dp"/>
<bums.lunatic.launcher.view.FloatingActionButton
app:fab_label="newtoki"
android:id="@+id/webtoons"
app:fab_showShadow="true"
app:fab_size="mini"
android:onClick="floatClick"
android:layout_width="wrap_content"
android:layout_height="20dp"/>
<bums.lunatic.launcher.view.FloatingActionButton
app:fab_label="manatoki"
android:id="@+id/comics"
app:fab_showShadow="true"
app:fab_size="mini"
android:onClick="floatClick"
android:layout_width="wrap_content"
android:layout_height="20dp"/>
<bums.lunatic.launcher.view.FloatingActionButton
app:fab_label="youtube"
android:id="@+id/youtube"
app:fab_showShadow="true"
app:fab_size="mini"
android:onClick="floatClick"
android:layout_width="wrap_content"
android:layout_height="20dp"/>
<bums.lunatic.launcher.view.FloatingActionButton
app:fab_label="perplexity"
android:id="@+id/perplexity"
app:fab_showShadow="true"
app:fab_size="mini"
android:onClick="floatClick"
android:layout_width="wrap_content"
android:layout_height="20dp"/>
<bums.lunatic.launcher.view.FloatingActionButton
app:fab_label="짤방"
android:id="@+id/zota"
app:fab_showShadow="true"
app:fab_size="mini"
android:onClick="floatClick"
android:layout_width="wrap_content"
android:layout_height="20dp"/>
<bums.lunatic.launcher.view.FloatingActionButton
app:fab_label="setting"
android:id="@+id/setting"
app:fab_showShadow="true"
app:fab_size="mini"
android:onClick="floatClick"
android:layout_width="wrap_content"
android:layout_height="20dp"/>
<bums.lunatic.launcher.view.FloatingActionButton
app:fab_label="close"
android:id="@+id/close"
app:fab_showShadow="true"
app:fab_size="mini"
android:onClick="floatClick"
android:layout_width="wrap_content"
android:layout_height="20dp"/>
</bums.lunatic.launcher.view.FloatingActionMenu>
</androidx.constraintlayout.widget.ConstraintLayout>

View File

@ -39,22 +39,22 @@
android:layout_width="match_parent"
android:layout_height="wrap_content">
<include layout="@layout/item_setting_title"/>
<bums.lunatic.launcher.tokiz.view.StepsEditor
<bums.lunatic.launcher.home.tokiz.view.StepsEditor
android:id="@+id/text_size"
style="@style/StepsEditorStyle" />
<bums.lunatic.launcher.tokiz.view.StepsEditor
<bums.lunatic.launcher.home.tokiz.view.StepsEditor
android:id="@+id/letter_space"
style="@style/StepsEditorStyle" />
<bums.lunatic.launcher.tokiz.view.StepsEditor
<bums.lunatic.launcher.home.tokiz.view.StepsEditor
android:id="@+id/line_space"
style="@style/StepsEditorStyle" />
<bums.lunatic.launcher.tokiz.view.StepsEditor
<bums.lunatic.launcher.home.tokiz.view.StepsEditor
android:id="@+id/page_padding"
style="@style/StepsEditorStyle" />
<bums.lunatic.launcher.tokiz.view.ScopeEditor
<bums.lunatic.launcher.home.tokiz.view.ScopeEditor
android:id="@+id/page_typesface"
style="@style/StepsEditorStyle" />
<bums.lunatic.launcher.tokiz.view.ScopeEditor
<bums.lunatic.launcher.home.tokiz.view.ScopeEditor
android:id="@+id/page_style"
style="@style/StepsEditorStyle" />
</LinearLayout>

View File

@ -36,6 +36,17 @@
<item name="civ_border_width">1dp</item>
<item name="civ_border_color">#000000</item>
</style>
<style name="SearchAccs">
<item name="android:paddingLeft">5dp</item>
<item name="android:paddingRight">5dp</item>
<item name="android:layout_marginLeft">6dp</item>
<item name="android:layout_marginRight">6dp</item>
<item name="android:layout_width">wrap_content</item>
<item name="android:layout_height">35dp</item>
<item name="android:gravity">center</item>
<item name="android:textColor">@color/finestSilver</item>
<item name="android:visibility">visible</item>
</style>
<style name="asdda" parent="Widget.Material3.Button.OutlinedButton">
<!-- <item name="android:paddingLeft">@dimen/m3_btn_padding_left</item>-->
<!-- <item name="android:paddingRight">@dimen/m3_btn_padding_right</item>-->