This commit is contained in:
lunaticbum 2025-07-24 16:09:35 +09:00
parent 193946cadf
commit dc69070823
11 changed files with 326 additions and 210 deletions

View File

@ -0,0 +1,9 @@
(function() {
var meta = document.querySelector('meta[name=viewport]');
if (!meta) {
meta = document.createElement('meta');
meta.name = 'viewport';
document.head.appendChild(meta);
}
meta.setAttribute('content', 'width=device-width, initial-scale=1.0');
})();

View File

@ -15,7 +15,7 @@
{
"run_at": "document_end",
"matches": ["<all_urls>"],
"js": ["messaging.js"]
"js": ["messaging.js","inject-viewport.js"]
}
],
"permissions": [

View File

@ -414,20 +414,21 @@ var time2 = null
function gotoNext() {
clearTimeout(time1)
try{
console.log("targetUrl :: " + targetUrl);
time2 = setTimeout(function () {
clearTimeout(time2)
document.querySelector('[class="btn-group"]').querySelectorAll('a').forEach(function(e){
if(e.hasAttribute("href") &&
(
(e.getAttribute("href").search("page=2") > -1 && location.href.search("page") < 0) ||
(e.getAttribute("href").search("page=3") > -1 && location.href.search("page=2") > 0)
)) {
e.click()
}
})
}, 5000);
console.log("targetUrl :: " + targetUrl);
if (document.querySelector('[class="btn-group"]')) {
time2 = setTimeout(function () {
clearTimeout(time2)
document.querySelector('[class="btn-group"]').querySelectorAll('a').forEach(function(e){
if(e.hasAttribute("href") &&
(
(e.getAttribute("href").search("page=2") > -1 && location.href.search("page") < 0) ||
(e.getAttribute("href").search("page=3") > -1 && location.href.search("page=2") > 0)
)) {
e.click()
}
})
}, 5000);
}
} catch (e) {
}

View File

@ -731,7 +731,7 @@ internal class LauncherActivity : CommonActivity() {
when(currentFragment) {
is RssHome ->{
if (currentFragment.binding.layoutRssSummary.root.isVisible) {
currentFragment.openGecko(rssData = currentFragment.lasted.randomOrNull())
currentFragment.openGecko(rssData = currentFragment.randomOrNull())
} else {
currentFragment.doNextPage()
}

View File

@ -27,6 +27,7 @@ import android.view.View
import android.widget.ProgressBar
import android.widget.Toast
import androidx.appcompat.app.AlertDialog
import androidx.core.view.isVisible
import bums.lunatic.launcher.LauncherActivity.Companion.getRuntime
import bums.lunatic.launcher.tokiz.data.HistoryManager
import bums.lunatic.launcher.tokiz.data.model.History
@ -110,6 +111,7 @@ class GeckoWeb : BWebview {
var canGoBack: Boolean? = null
var mPort: WebExtension.Port? = null
var mCaache : WebExtension.Port? = null
var privateMode = false
object WebExtensionInfo {
val mPortNam = "browser"
val extPath = "resource://android/assets/extensions/my_extension/"
@ -347,20 +349,9 @@ class GeckoWeb : BWebview {
}
override fun onPageStart(session: GeckoSession, url: String) {
super.onPageStart(session, url)
if (url.contains(getFilterF()) && url.contains("jpg") == false) {
if (url.contains(getFilterF()) && privateMode) {
this@GeckoWeb.visibility = View.INVISIBLE
}
// if (url?.contains("reddit.app.link") == true) {
// session.stop()
// Uri.parse(url)?.let { uri ->
// context.startActivity(Intent().apply {
// action = Intent.ACTION_VIEW
// flags = Intent.FLAG_ACTIVITY_EXCLUDE_FROM_RECENTS.or(FLAG_ACTIVITY_CLEAR_TOP).or(
// FLAG_ACTIVITY_NEW_TASK)
// data = uri
// })
// }
// }
}
override fun onPageStop(session: GeckoSession, success: Boolean) {
@ -368,12 +359,12 @@ class GeckoWeb : BWebview {
super.onPageStop(session, success)
if (success && mPort != null) {
if (mPort == null) {
// No extension registered yet, let's ignore this message
return
}
}
}
}
@ -423,7 +414,7 @@ class GeckoWeb : BWebview {
Blog.LOGE("GeckoView", "현재 session: $session")
url?.let { url ->
if (url?.contains(getFilterF()) == true && url.contains("jpg") == false) {
if (url?.contains(getFilterF()) == true && privateMode) {
this@GeckoWeb.visibility = View.INVISIBLE
}
if (url.split("//").size > 1) {
@ -482,7 +473,7 @@ class GeckoWeb : BWebview {
copyToRealm(it, UpdatePolicy.ALL)
}
}
Toast.makeText(context, "Received Msg privates form ${lPortMessage.currentPage} data => ${lPortMessage.privates?.size ?: 0}", Toast.LENGTH_SHORT).show()
context.toast("Received Msg privates form ${lPortMessage.currentPage} data => ${lPortMessage.privates?.size ?: 0}")
}
}
"Cookies"->{
@ -657,6 +648,35 @@ class GeckoWeb : BWebview {
return super.dispatchKeyEvent(ev)
}
override fun loadUrl(url: String, param : String?) {
var nUrl = url
Blog.LOGE("url >>>> ${url}")
if (url.endsWith("=")) {
nUrl = String(java.util.Base64.getMimeDecoder().decode(url.toByteArray()))
param?.let {
nUrl = nUrl.plus(param)
}
} else if (url.startsWith("http") == false) {
nUrl = lastDomain
}
if (!privateMode && this.isVisible == false) {
this.visibility = View.VISIBLE
}
Blog.LOGE("nUrl >>>> ${nUrl}")
nUrl?.let { url ->
if (url.split("//").size > 1) {
url.replace("//","/").replace("https:/","https://").let {
Blog.LOGE("url >> ${url} , it >>> ${it}")
this.session?.loadUri(it)
}
} else {
this.session?.loadUri(url)
}
}
BWebview.Companion.currentRetryCount = 0;
}
companion object {
private const val TAG = "DualScreenStatus"

View File

@ -19,6 +19,7 @@
package bums.lunatic.launcher.home
import android.annotation.SuppressLint
import android.content.Context
import android.content.DialogInterface
import android.content.Intent
import android.content.SharedPreferences
@ -109,121 +110,123 @@ internal class RssHome : Fragment() {
var mRssDataResult: RealmResults<RssData>? = null
val mSimpleFingerGestures = SimpleFingerGestures(omfgl = object : SimpleFingerGestures.OnFingerGestureListener{
val mSimpleFingerGestures =
SimpleFingerGestures(omfgl = object : SimpleFingerGestures.OnFingerGestureListener {
override fun onSwipeUp(
targetView: View,
fingers: Int,
gestureDuration: Long,
gestureDistance: Double
): Boolean {
Blog.LOGE("")
if (imageView){
openGecko(rssData = lasted.randomOrNull())
override fun onSwipeUp(
targetView: View,
fingers: Int,
gestureDuration: Long,
gestureDistance: Double
): Boolean {
Blog.LOGE("")
if (imageView) {
openGecko(rssData = randomOrNull())
}
return true
}
return true
}
override fun onSwipeDown(
targetView: View,
fingers: Int,
gestureDuration: Long,
gestureDistance: Double
): Boolean {
if (imageView){
openGecko(rssData = lasted.randomOrNull())
override fun onSwipeDown(
targetView: View,
fingers: Int,
gestureDuration: Long,
gestureDistance: Double
): Boolean {
if (imageView) {
openGecko(rssData = randomOrNull())
}
Blog.LOGE("")
return true
}
Blog.LOGE("")
return true
}
override fun onSwipeLeft(
targetView: View,
fingers: Int,
gestureDuration: Long,
gestureDistance: Double
): Boolean {
Blog.LOGE("")
return true
}
override fun onSwipeLeft(
targetView: View,
fingers: Int,
gestureDuration: Long,
gestureDistance: Double
): Boolean {
Blog.LOGE("")
return true
}
override fun onSwipeRight(
targetView: View,
fingers: Int,
gestureDuration: Long,
gestureDistance: Double
): Boolean {
Blog.LOGE("")
return true
}
override fun onSwipeRight(
targetView: View,
fingers: Int,
gestureDuration: Long,
gestureDistance: Double
): Boolean {
Blog.LOGE("")
return true
}
override fun onPinch(
targetView: View,
fingers: Int,
gestureDuration: Long,
gestureDistance: Double
): Boolean {
Blog.LOGE("onPinch")
return false
}
override fun onPinch(
targetView: View,
fingers: Int,
gestureDuration: Long,
gestureDistance: Double
): Boolean {
Blog.LOGE("onPinch")
return false
}
override fun onUnpinch(
targetView: View,
fingers: Int,
gestureDuration: Long,
gestureDistance: Double
): Boolean {
Blog.LOGE("")
return true
}
override fun onUnpinch(
targetView: View,
fingers: Int,
gestureDuration: Long,
gestureDistance: Double
): Boolean {
Blog.LOGE("")
return true
}
override fun onDoubleTap(
targetView: View,
fingers: Int
): Boolean {
Blog.LOGE("")
return true
}
override fun onDoubleTap(
targetView: View,
fingers: Int
): Boolean {
Blog.LOGE("")
return true
}
override fun onLongPress(
targetView: View,
fingers: Int
): Boolean {
Blog.LOGE("onLongPress")
return false
}
override fun onLongPress(
targetView: View,
fingers: Int
): Boolean {
Blog.LOGE("onLongPress")
return false
}
override fun onClick(
targetView: View,
fingers: Int
): Boolean {
Blog.LOGE("onClick")
return false
}
})
override fun onClick(
targetView: View,
fingers: Int
): Boolean {
Blog.LOGE("onClick")
return false
}
})
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
home = this
}
var targetList = arrayListOf<String>()
val dateViewClick = View.OnClickListener { v ->
val dateViewClick = View.OnClickListener { v ->
Blog.LOGE("click view >> ${v}")
(v?.tag as? RssData)?.let { rss ->
WorkersDb.getRealm().apply {
writeBlocking {
rss.read = rss.read + 1
if(rss.getCho()?.length ?: 0 < 1) {
if (rss.getCho()?.length ?: 0 < 1) {
rss.chosung = rss.title
}
copyToRealm(rss,UpdatePolicy.ALL)
copyToRealm(rss, UpdatePolicy.ALL)
}
}
when(rss.category()) {
RssDataType.REDDIT_NSFW,RssDataType.PRIVATE -> {
when (rss.category()) {
RssDataType.REDDIT_NSFW, RssDataType.PRIVATE -> {
v.findViewById<ShapeableImageView>(R.id.circle_preview)?.let {
if (RssDataType.PRIVATE.equals(rss.category()) && imageView) {
openGecko(rssData = lasted.randomOrNull())
openGecko(rssData = rss)
} else {
if (it.visibility == View.GONE) {
it.visibility = View.VISIBLE
@ -245,17 +248,23 @@ internal class RssHome : Fragment() {
}
}
}
RssDataType.REDDIT -> {
openReddit(rss.originPage())
}
RssDataType.DOTAX -> {
openGecko(rss.originPage())
}
RssDataType.YOUTUBE -> { openYouTube(rss.originPage())
RssDataType.YOUTUBE -> {
openYouTube(rss.originPage())
}
RssDataType.CLIEN -> {
openGecko(rss.originPage())
}
else -> {
openGecko(rss.originPage())
}
@ -271,17 +280,22 @@ internal class RssHome : Fragment() {
.inflate(R.layout.text_inpu_password, binding.root as ViewGroup?, false)
val input = viewInflated.findViewById<View>(R.id.input) as EditText
builder.setView(viewInflated)
builder.setPositiveButton(android.R.string.ok,
builder.setPositiveButton(
android.R.string.ok,
DialogInterface.OnClickListener { dialog, which ->
dialog.dismiss()
var command = input.editableText?.toString()
if (command?.length ?: 0 > 0) {
binding.geckoWeb.loadUrl("aHR0cHM6Ly9pamF2dG9ycmVudC5jb20=", "/?searchTerm=${command}")
binding.geckoWeb.loadUrl(
"aHR0cHM6Ly9pamF2dG9ycmVudC5jb20=",
"/?searchTerm=${command}"
)
} else {
binding.geckoWeb.loadUrl("aHR0cHM6Ly9pamF2dG9ycmVudC5jb20=")
}
})
builder.setNegativeButton(android.R.string.cancel,
builder.setNegativeButton(
android.R.string.cancel,
DialogInterface.OnClickListener { dialog, which -> dialog.cancel() })
builder.show()
@ -304,12 +318,20 @@ internal class RssHome : Fragment() {
}
} else {
rssData?.let {
lasted.removeAll { target -> target.originPage.equals(it.originPage) }
appendReadCount(it, 1, false)
Blog.LOGE("removeFirst >>> ${Gson().toJson(it)}")
binding.layoutRssSummary.title.tag = it
binding.layoutRssSummary.root.visibility = View.VISIBLE
it.title()?.let {
var vote = it.vote
var read = it.read
it.title?.let {
Blog.LOGE(it)
binding.layoutRssSummary.title.text = it
binding.layoutRssSummary.title.text = it.replace(Regex("[\\r\\n]+"), " ").plus( "\n[V:${if (vote) {
"O"
}else {
"X"
}} , R:${read}]")
}
it.pubDate()?.let {
@ -320,7 +342,7 @@ internal class RssHome : Fragment() {
binding.layoutRssSummary.desc.tag = it
it.description()?.let {
Blog.LOGE(it)
binding.layoutRssSummary.desc.text = it
binding.layoutRssSummary.desc.text = it.replace(Regex("[\\r\\n]+"), " ")
}
binding.layoutRssSummary.link.tag = it
it.getMagnet().let {
@ -354,15 +376,19 @@ internal class RssHome : Fragment() {
binding = LauncherHomeBinding.inflate(inflater, container, false)
fragManager = lActivity!!.supportFragmentManager
settingsPrefs = requireContext().getSharedPreferences(PREFS_SETTINGS, 0)
mRssAdapter = RssItemAdapter(requireContext(),dateViewClick)
mRssAdapter = RssItemAdapter(requireContext(), dateViewClick)
val decoration = DividerItemDecoration(requireContext(), DividerItemDecoration.VERTICAL)
binding.infoList.addItemDecoration(decoration)
binding.infoList.visibility = View.VISIBLE
binding.infoList.adapter = mRssAdapter
binding.infoList.setOnTouchListener { v,e ->
if (e.device.name?.contains("JX-12",true) == true|| e.device.name?.equals("J06",true) == true) {
binding.infoList.setOnTouchListener { v, e ->
if (e.device.name?.contains("JX-12", true) == true || e.device.name?.equals(
"J06",
true
) == true
) {
Blog.LOGE("touchEvent -> ${e}")
return@setOnTouchListener mSimpleFingerGestures.onTouch(v,e)
return@setOnTouchListener mSimpleFingerGestures.onTouch(v, e)
} else {
return@setOnTouchListener false
@ -374,7 +400,7 @@ internal class RssHome : Fragment() {
}
}
binding.test.setOnClickListener {
if(binding.geckoWeb.isVisible) {
if (binding.geckoWeb.isVisible) {
binding.geckoWeb.visibility = View.GONE
}
@ -389,7 +415,7 @@ internal class RssHome : Fragment() {
val result = query<RssData>().query("originPage == $0", rssId).find()
if (result.size > 0) {
result.forEach {
if(it.vote) {
if (it.vote) {
it.vote = false
}
}
@ -404,13 +430,13 @@ internal class RssHome : Fragment() {
if (binding.geckoWeb.isVisible) {
binding.geckoWeb.visibility = View.GONE
}
binding.layoutRssSummary.root.visibility = View.GONE
binding.layoutRssSummary.root.visibility = View.GONE
queryInfos()
}
binding.bookmark.setOnClickListener {
binding.layoutRssSummary.root.visibility = View.GONE
binding.layoutRssSummary.root.visibility = View.GONE
queryVotes()
}
binding.prv.setOnClickListener {
@ -424,25 +450,27 @@ internal class RssHome : Fragment() {
binding.layoutRssSummary.title.setOnClickListener {
(it.tag as? RssData)?.let {
appendReadCount(it, nomoreShowCount, false)
openGecko(rssData = lasted.randomOrNull())
openGecko(rssData = randomOrNull())
}
}
binding.layoutRssSummary.close.setOnClickListener {
binding.layoutRssSummary.root.visibility = View.GONE
binding.layoutRssSummary.root.visibility = View.GONE
}
queryInfos()
binding.geckoWeb.progress = binding.progressBar
binding.geckoWeb.jxInteface = { jxEvent ->
when(jxEvent) {
when (jxEvent) {
JxEvent.SCROLL_UP -> binding.geckoWeb.sendScrollDown(false)
JxEvent.SCROLL_DOWN -> binding.geckoWeb.sendScrollDown(true)
JxEvent.ON_CLICK -> {
binding.geckoWeb.visibility = View.GONE
}
JxEvent.SWIPE_LEFT -> {
doNextPage()
}
JxEvent.SWIPE_RIGHT -> {
vote()
}
@ -456,11 +484,14 @@ internal class RssHome : Fragment() {
return binding.root
}
fun vote(){
fun vote() {
Blog.LOGE("Arrow Center Click")
WorkersDb.getRealm().apply {
writeBlocking {
val result = query<RssData>().query(if(imageView)"thumbnail == $0" else "originPage == $0", rssId).find()
val result = query<RssData>().query(
if (imageView) "thumbnail == $0" else "originPage == $0",
rssId
).find()
if (result.size > 0) {
result.forEach { it.vote = true }
}
@ -474,7 +505,10 @@ internal class RssHome : Fragment() {
fun doNextPage() {
WorkersDb.getRealm().apply {
writeBlocking {
val result = query<RssData>().query(if(imageView)"thumbnail == $0" else "originPage == $0", rssId).find()
val result = query<RssData>().query(
if (imageView) "thumbnail == $0" else "originPage == $0",
rssId
).find()
if (result.size > 0) {
result.forEach {
it.read = it.read + nomoreShowCount
@ -492,9 +526,17 @@ internal class RssHome : Fragment() {
}
}
fun clearJob(job : Job?) {
try { job?.cancel() } catch (e: Exception) { e.printStackTrace() }
try { System.gc() } catch (e: Exception) { e.printStackTrace() }
fun clearJob(job: Job?) {
try {
job?.cancel()
} catch (e: Exception) {
e.printStackTrace()
}
try {
System.gc()
} catch (e: Exception) {
e.printStackTrace()
}
}
fun beforeQuery() {
@ -504,59 +546,76 @@ internal class RssHome : Fragment() {
delete(
query<RssData>()
.query("pubDate < $0", beforeDay(30))
.query("category != $0 AND category != $1 ", RssDataType.PRIVATE.name, RssDataType.REDDIT_NSFW.name)
.query(
"category != $0 AND category != $1 ",
RssDataType.PRIVATE.name,
RssDataType.REDDIT_NSFW.name
)
.query("vote != $0", true).find()
)
}
}
fun updateQuery(q: RealmQuery<RssData>) {
mRssDataResult = q.sort("pubDate ", Sort.DESCENDING).limit(300).distinct("originPage", "title").find()
mRssDataResult =
q.sort("pubDate ", Sort.DESCENDING).limit(300).distinct("originPage", "title").find()
mRssDataResult?.asFlow()?.let { flow ->
infosJob = CoroutineScope(Dispatchers.IO).launch {
flow.collect { changes: ResultsChange<RssData> ->
when(changes) {
is InitialResults -> {
// when (changes) {
// is InitialResults -> {
commandHandler.removeCallbacks(infoUpdate)
WorkersDb.getRealm().apply {
lasted.clear()
lasted.addAll(copyFromRealm(changes.list))
}
commandHandler.post(infoUpdate)
}
is UpdatedResults -> {
CoroutineScope(Dispatchers.Main).launch {
changes.changeRanges.forEach {
mRssAdapter.notifyItemRangeChanged(it.startIndex, it.length)
}
}
}
}
// }
//
// is UpdatedResults -> {
// CoroutineScope(Dispatchers.Main).launch {
// changes.changeRanges.forEach {
// mRssAdapter.notifyItemRangeChanged(it.startIndex, it.length)
// }
// }
// }
//
// }
}
}
infosJob?.start()
}
}
fun queryPrevate() {
imageView = true
beforeQuery()
updateQuery(WorkersDb.getPrivate())
}
fun queryVotes() {
imageView = false
beforeQuery()
updateQuery(WorkersDb.getVotedRss())
}
var imageView = false
fun queryInfos(
filter: Collection<RssDataType>? = arrayListOf(RssDataType.REDDIT_NSFW,RssDataType.PRIVATE), noLimit: Boolean = false
filter: Collection<RssDataType>? = arrayListOf(
RssDataType.REDDIT_NSFW,
RssDataType.PRIVATE
), noLimit: Boolean = false
) {
imageView = false
beforeQuery()
var rQ = WorkersDb.getRealm().query<RssData>().query("read < $0", nomoreShowCount).distinct("originPage", "title")
var rQ = WorkersDb.getRealm().query<RssData>().query("read < $0", nomoreShowCount)
.distinct("originPage", "title")
if (!noLimit) rQ.query("pubDate > $0", beforeOneDay())
((filter?.size ?: 0) > 0).letTrue {filter!!.forEach {rQ = rQ.query("category != $0", it.name)}}
((filter?.size ?: 0) > 0).letTrue {
filter!!.forEach {
rQ = rQ.query("category != $0", it.name)
}
}
updateQuery(rQ)
}
@ -566,11 +625,10 @@ internal class RssHome : Fragment() {
noLimit: Boolean = false
) {
beforeQuery()
updateQuery(WorkersDb.getRssQuery(keyword,category,noLimit))
updateQuery(WorkersDb.getRssQuery(keyword, category, noLimit))
}
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
super.onViewCreated(view, savedInstanceState)
@ -591,13 +649,12 @@ internal class RssHome : Fragment() {
}
fun chooseAdpater() {
binding.infoList.visibility = View.VISIBLE
lasted?.let { mRssAdapter.updateData(it) }
}
fun appendReadCount(rss: RssData, appendCount : Int, vote : Boolean = false) {
fun appendReadCount(rss: RssData, appendCount: Int, vote: Boolean = false) {
WorkersDb.getRealm().apply {
writeBlocking {
var results = query<RssData>("originPage == $0", rss.originPage).find()
@ -615,7 +672,10 @@ internal class RssHome : Fragment() {
val swipeToDeleteCallback: SwipeToDeleteCallback =
object : SwipeToDeleteCallback(requireContext()) {
override fun onSwiped(@NonNull viewHolder: RecyclerView.ViewHolder, direction: Int) {
override fun onSwiped(
@NonNull viewHolder: RecyclerView.ViewHolder,
direction: Int
) {
Blog.LOGE("onSwiped direction >>>> $direction")
(viewHolder.itemView.tag as? RssData)?.let { rss ->
CoroutineScope(Dispatchers.IO).launch {
@ -673,48 +733,56 @@ internal class RssHome : Fragment() {
override fun onPause() {
super.onPause()
}
}
fun loadImage(imageView: ImageView, url: String?, retryCount: Int = 3) {
Picasso.get().cancelRequest(imageView)
url?.let { url ->
if (url.length > 4) {
try {
imageView.visibility = View.VISIBLE
imageView.setAlpha(0.05f)
Blog.LOGE("loadImage >>> $url")
Picasso.get()
.load(url)
.into(imageView, object : com.squareup.picasso.Callback {
override fun onSuccess() {
imageView.setAlpha(0.05f)
}
override fun onError(e: Exception?) {
e?.printStackTrace()
if (retryCount > 0) {
// 메인 스레드에서 재시도
Handler(Looper.getMainLooper()).post {
loadImage(imageView, url, retryCount - 1)
}
} else {
// 3회 모두 실패: 대체 이미지 표시
imageView.setImageResource(R.drawable.ic_info)
imageView.setAlpha(1f)
fun loadImage(imageView: ImageView, url: String?, retryCount: Int = 3) {
Picasso.get().cancelRequest(imageView)
url?.let { url ->
if (url.length > 4) {
try {
imageView.visibility = View.INVISIBLE
imageView.setAlpha(0.05f)
Blog.LOGE("loadImage >>> $url")
Picasso.get()
.load(url)
.into(imageView, object : com.squareup.picasso.Callback {
override fun onSuccess() {
imageView.setAlpha(0.05f)
Blog.LOGE("Picasso load into onSuccess URL:$url")
}
}
})
imageView.contentDescription = url
}catch (e: Exception){
override fun onError(e: Exception?) {
e?.printStackTrace()
if (retryCount > 0) {
// 메인 스레드에서 재시도
Handler(Looper.getMainLooper()).postDelayed({
loadImage(imageView, url, retryCount - 1)
}, 1500L)
} else {
// 3회 모두 실패: 대체 이미지 표시
imageView.setImageResource(R.drawable.ic_info)
imageView.setAlpha(1f)
}
}
})
imageView.contentDescription = url
} catch (e: Exception) {
}
} else {
imageView.visibility = View.INVISIBLE
}
} else {
} ?: {
imageView.visibility = View.INVISIBLE
}
} ?: {
imageView.visibility = View.INVISIBLE
}
fun randomOrNull() : RssData? = lasted.sortedByDescending { it.read }.filter { it.vote == false && it.read < nomoreShowCount }.randomOrNull()
}
var toast: Toast? = null
fun Context.toast(string: String) {
if (toast == null) {
toast = Toast.makeText(this,string,Toast.LENGTH_SHORT)
}
toast?.setText(string)
toast?.show()
}

View File

@ -254,7 +254,7 @@ class RssData : RealmObject, RssDataInterface {
var mRssDataType : RssDataType? = null
override fun title(): String {
return when(category()){
RssDataType.NEWSFEED -> {
RssDataType.NEWSFEED,RssDataType.PRIVATE -> {
if(title?.length ?: 0 > 30) title?.substring(0,30).plus("...") else title ?: ""
}
else -> title ?: ""

View File

@ -160,7 +160,7 @@ open class BWebview : GeckoView {
var lastDomain : String = ""
fun loadUrl(url: String, param : String? = null) {
open fun loadUrl(url: String, param : String? = null) {
var nUrl = url
Blog.LOGE("url >>>> ${url}")
if (url.endsWith("=")) {

View File

@ -26,21 +26,25 @@
android:layout_width="match_parent"
android:layout_height="wrap_content">
<TextView
android:layout_margin="@dimen/_9sp"
android:padding="@dimen/_26sp"
app:layout_constraintTop_toTopOf="parent"
android:id="@+id/title"
android:gravity="center"
android:singleLine="false"
android:background="#000"
android:textSize="@dimen/_20sp"
android:textSize="@dimen/_26sp"
android:textColor="@color/white"
android:layout_width="match_parent"
android:layout_height="wrap_content"/>
<TextView
android:padding="@dimen/_20sp"
app:layout_constraintTop_toBottomOf="@id/title"
android:id="@+id/date"
android:gravity="center_vertical|right"
android:singleLine="false"
android:background="#000"
android:textSize="@dimen/_20sp"
android:textSize="@dimen/_14sp"
android:textColor="@color/white"
android:layout_width="match_parent"
android:layout_height="wrap_content"/>
@ -63,11 +67,13 @@
android:layout_width="match_parent"
android:layout_height="wrap_content"/>
<TextView
android:padding="@dimen/_20sp"
app:layout_constraintTop_toBottomOf="@id/cover"
android:id="@+id/desc"
android:gravity="center_vertical|right"
android:singleLine="false"
android:background="#000"
android:textSize="@dimen/_20sp"
android:textSize="@dimen/_14sp"
android:textColor="@color/white"
android:layout_width="match_parent"
android:layout_height="wrap_content"/>
@ -90,11 +96,12 @@
android:layout_width="match_parent"
android:layout_height="wrap_content"/>
<TextView
android:padding="@dimen/_20sp"
app:layout_constraintTop_toBottomOf="@id/screen"
android:id="@+id/link"
android:singleLine="false"
android:background="#000"
android:textSize="@dimen/_20sp"
android:textSize="@dimen/_9sp"
android:textColor="@color/white"
android:layout_width="match_parent"
android:layout_height="wrap_content"/>

View File

@ -3,16 +3,18 @@
android:layout_width="match_parent"
android:layout_height="match_parent"
xmlns:app="http://schemas.android.com/apk/res-auto">
<com.google.android.material.textfield.TextInputLayout
android:id="@+id/colorInputLayout"
android:layout_width="@dimen/oneNinetySix"
android:layout_height="wrap_content"
android:hint="inpout text"
android:orientation="horizontal"
app:boxBackgroundColor="?attr/colorSurface"
app:endIconMode="clear_text"
android:gravity="right"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent">
app:layout_constraintStart_toStartOf="parent">
<com.google.android.material.textfield.TextInputEditText
android:id="@+id/input"
@ -20,6 +22,15 @@
android:layout_height="wrap_content"
android:imeOptions="actionDone"
android:inputType="text" />
<CheckBox
android:padding="0dp"
android:text="PRIVATE MODE"
android:textColor="@color/white"
app:layout_constraintLeft_toLeftOf="parent"
app:layout_constraintRight_toRightOf="parent"
android:id="@+id/parivate_mode"
android:checked="true"
android:layout_width="wrap_content"
android:layout_height="wrap_content"/>
</com.google.android.material.textfield.TextInputLayout>
</androidx.constraintlayout.widget.ConstraintLayout>

View File

@ -27,7 +27,7 @@
<dimen name="_20sp">23sp</dimen>
<dimen name="_14sp">17sp</dimen>
<dimen name="_12sp">14sp</dimen>
<dimen name="_9sp">8sp</dimen>
<!-- toolbar height -->
<dimen name="toolbar_height">100dp</dimen>