...
This commit is contained in:
parent
428b16cda2
commit
2a25b49baa
@ -54,6 +54,9 @@
|
|||||||
tools:ignore="ScopedStorage" />
|
tools:ignore="ScopedStorage" />
|
||||||
<uses-permission android:name="android.permission.BLUETOOTH" />
|
<uses-permission android:name="android.permission.BLUETOOTH" />
|
||||||
<uses-permission android:name="android.permission.FOREGROUND_SERVICE" />
|
<uses-permission android:name="android.permission.FOREGROUND_SERVICE" />
|
||||||
|
<uses-permission android:name="android.permission.BLUETOOTH_ADMIN" />
|
||||||
|
<uses-permission android:name="android.permission.FOREGROUND_SERVICE" />
|
||||||
|
|
||||||
<queries>
|
<queries>
|
||||||
<intent>
|
<intent>
|
||||||
<action android:name="android.intent.action.MAIN" />
|
<action android:name="android.intent.action.MAIN" />
|
||||||
@ -101,6 +104,10 @@
|
|||||||
</intent-filter>
|
</intent-filter>
|
||||||
</activity>
|
</activity>
|
||||||
|
|
||||||
|
<service
|
||||||
|
android:name=".helpers.BluetoothManager"
|
||||||
|
android:enabled="true"
|
||||||
|
android:exported="false" />
|
||||||
<service
|
<service
|
||||||
android:name=".wall.MyWallpaperService"
|
android:name=".wall.MyWallpaperService"
|
||||||
android:label="Bums Live Wallpaper"
|
android:label="Bums Live Wallpaper"
|
||||||
|
|||||||
@ -84,3 +84,22 @@ function check2() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
check2();
|
check2();
|
||||||
|
|
||||||
|
fetch("https://dv-m.nhmembers.co.kr/nhpot/common/saveCertInf.ajax",{
|
||||||
|
method: "POST",
|
||||||
|
headers: {
|
||||||
|
"Content-Type": "application/x-www-form-urlencoded",
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
|
if (document.querySelectorAll('[class^="w-full flex"]').length > 1) {
|
||||||
|
document.querySelectorAll('[class^="w-full flex"]').forEach(function (e) {
|
||||||
|
|
||||||
|
|
||||||
|
var description = ""
|
||||||
|
if(e.querySelector('[class^="pb-2 w-100 text-gray-500"]')){
|
||||||
|
description = e.querySelector('[class^="pb-2 w-100 text-gray-500"]').textContent.replace(/\s+/g, ' ').trim();
|
||||||
|
}
|
||||||
|
console.log(description)
|
||||||
|
})
|
||||||
|
}
|
||||||
@ -1,93 +0,0 @@
|
|||||||
video-item ::> <div class="img-area">
|
|
||||||
<table>
|
|
||||||
<tbody>
|
|
||||||
<tr>
|
|
||||||
<td><a onclick="sendEvent('Cover Click','Main List Movie','201882')" href="/movie/ipzz-574-201882" data-link="https://images.ijavtorrent.com/data/covers/201882.jpg"> <img sizes="
|
|
||||||
(max-width: 1536px) 480px,
|
|
||||||
(max-width: 1920px) 620px,
|
|
||||||
(min-width: 1921px) 800px,
|
|
||||||
" src="https://images.ijavtorrent.com/data/covers/201882.jpg" alt="IPZZ-574 I Didn't Know About My Wife's Twisted Sexual Habits... My Beloved Wife, Who Is Usually Kind, Was A Masochistic Slave Trained By A Sadistic Neighbor. Kana Momonogi" title="IPZZ-574 I Didn't Know About My Wife's Twisted Sexual Habits... My Beloved Wife, Who Is Usually Kind, Was A Masochistic Slave Trained By A Sadistic Neighbor. Kana Momonogi" class="lazy mw-100" style="" srcset="
|
|
||||||
https://images.ijavtorrent.com/data/covers/201882.jpg?width=480 480w,
|
|
||||||
https://images.ijavtorrent.com/data/covers/201882.jpg?width=620 620w,
|
|
||||||
https://images.ijavtorrent.com/data/covers/201882.jpg?width=800 800w,
|
|
||||||
"> </a></td>
|
|
||||||
</tr>
|
|
||||||
</tbody>
|
|
||||||
</table>
|
|
||||||
</div>
|
|
||||||
<div class="name">
|
|
||||||
<a onclick="sendEvent('movie-click','Main List Movie','201882')" href="/movie/ipzz-574-201882"> <span>ipzz-574 i didn't know about my wife's twisted sexual habits... my beloved wife, who is usually kind, was a masochistic slave trained by a sadistic neighbor. kana momonogi</span> </a>
|
|
||||||
</div>
|
|
||||||
<div class="mb-2">
|
|
||||||
<a onclick="sendEvent('movie-click','Main List Movie','201882')" href="/movie/ipzz-574-201882"> 08/07/2025 </a> | <i class="fas fa-eye"></i> <span class="pageview-value">4260</span> | <i class="fa fa-fw fa-download"></i> <span class="download-value">2602</span>
|
|
||||||
</div>
|
|
||||||
<div class="mb-1">
|
|
||||||
<div class="badge badge-info" data-toggle="popover" data-html="true" data-content="<div><img src='https://images.ijavtorrent.com/data/actresses/451.jpg?v=772750732' alt='Kana Momonogi' style='width: 150px; height: 150px;'></div>" data-original-title="" title="">
|
|
||||||
<a href="/actress/kana-momonogi-451"> <i class="fas fa-info"></i> Kana Momonogi </a> <img src="https://images.ijavtorrent.com/data/actresses/451.jpg?v=772750732" class="d-none">
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
<div>
|
|
||||||
<div class="badge badge-warning">
|
|
||||||
<a href="/?editorrate=6"><i class="fab fa-hotjar"></i> 6</a>
|
|
||||||
</div>
|
|
||||||
<div class="badge badge-warning">
|
|
||||||
<a href="/tag/top-5-daily-2483">Top 5 Daily</a>
|
|
||||||
</div>
|
|
||||||
<div class="badge badge-secondary">
|
|
||||||
<a href="/tag/cuckold-112">Cuckold</a>
|
|
||||||
</div>
|
|
||||||
<div class="badge badge-secondary">
|
|
||||||
<a href="/tag/nasty-hardcore-85">Nasty, Hardcore</a>
|
|
||||||
</div>
|
|
||||||
<div class="badge badge-secondary">
|
|
||||||
<a href="/tag/sm-95">SM</a>
|
|
||||||
</div>
|
|
||||||
<div class="badge badge-secondary">
|
|
||||||
<a href="/tag/solowork-1">Solowork</a>
|
|
||||||
</div>
|
|
||||||
<div class="badge badge-secondary">
|
|
||||||
<a href="/tag/married-woman-19">Married Woman</a>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
<div class="text-right">
|
|
||||||
<div class="btn btn-sm btn-warning">
|
|
||||||
<a onclick="sendEvent('Screenshot-Click','Main List Movie','201882')" href="https://images.ijavtorrent.com/data/screenshots/201882.jpg" data-featherlight="image" target="_blank"> <i class="far fa-images"></i> Screenshot </a>
|
|
||||||
</div>
|
|
||||||
<div class="btn btn-sm btn-outline-primary movie-like-button" data-movie-id="201882">
|
|
||||||
<i class="fas fa-heart"></i> <span class="like-value">0</span>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
<table class="table table-sm mt-2">
|
|
||||||
<tbody>
|
|
||||||
<tr style="vertical-align: middle">
|
|
||||||
2025-07-23 11:22:20.062 26023-26023 Lunatic bums.lunatic.launcher E <td><a onclick="sendEvent('Torrent Click','Main List Movie','201882')" href="/download/463171" rel="nofollow" class="download-click-track"><i class="fa fa-fw fa-download"></i> Download</a> <a onclick="sendEvent('Magnet Click','Main List Movie','201882')" href="magnet:?xt=urn:btih:8c64238f2bfd260a6793b3b8ec97aad93e4d1dd8&amp;dn=IPZZ-574%E3%80%90%E7%A0%B4%E5%A3%8A%E7%89%88%E3%80%91%E4%BF%BA%E3%81%AE%E7%9F%A5%E3%82%89%E3%81%AA%E3%81%84%E5%A6%BB%E3%81%AE%E6%AD%AA%E3%82%93%E3%81%A0%E6%80%A7%E7%99%96%E2%80%A6%20%E6%99%AE%E6%AE%B5%E5%84%AA%E3%81%97%E3%81%84%E6%9C%80%E6%84%9B%E3%81%AE%E5%A6%BB%E3%81%AF%E3%83%89S%E9%9A%A3%E4%BA%BA%E3%81%AB%E8%AA%BF%E6%95%99%E6%B8%88%E3%81%AE%E3%83%9E%E3%82%BE%E5%A5%B4%E2%97%8F%E3%81%A7%E3%81%97%E3%81%9F%E3%80%82%20%E6%A1%83%E4%B9%83%E6%9C%A8%E3%81%8B%E3%81%AA&amp;tr=http%3A%2F%2Fsukebei.tracker.wf%3A8888%2Fannounce&amp;tr=udp%3A%2F%2Fopen.stealth.si%3A80%2Fannounce&amp;tr=udp%3A%2F%2Ftracker.opentrackr.org%3A1337%2Fannounce&amp;tr=udp%3A%2F%2Fexodus.desync.com%3A6969%2Fannounce&amp;tr=udp%3A%2F%2Ftracker.torrent.eu.org%3A451%2Fannounce" rel="nofollow" class="magnet-click-track"><i class="fa fa-fw fa-magnet" rel="nofollow"></i> Magnet</a></td>
|
|
||||||
<td><i class="fas fa-weight-hanging"></i> 3.4gb</td>
|
|
||||||
<td><strong>S:</strong> 41</td>
|
|
||||||
<td><strong>L:</strong> 667</td>
|
|
||||||
<td><i class="far fa-calendar-alt"></i> 23/07/25</td>
|
|
||||||
<td><span class="badge badge-info">Decen</span></td>
|
|
||||||
</tr>
|
|
||||||
<tr style="vertical-align: middle">
|
|
||||||
<td><a onclick="sendEvent('Torrent Click','Main List Movie','201882')" href="/download/459739" rel="nofollow" class="download-click-track"><i class="fa fa-fw fa-download"></i> Download</a> <a onclick="sendEvent('Magnet Click','Main List Movie','201882')" href="magnet:?xt=urn:btih:6a020162885ec725961eeca6ccb15153586f09d3&amp;dn=%5BHD%2F720p%5D%20IPZZ-574%20%E4%BF%BA%E3%81%AE%E7%9F%A5%E3%82%89%E3%81%AA%E3%81%84%E5%A6%BB%E3%81%AE%E6%AD%AA%E3%82%93%E3%81%A0%E6%80%A7%E7%99%96%E2%80%A6%20%E6%99%AE%E6%AE%B5%E5%84%AA%E3%81%97%E3%81%84%E6%9C%80%E6%84%9B%E3%81%AE%E5%A6%BB%E3%81%AF%E3%83%89S%E9%9A%A3%E4%BA%BA%E3%81%AB%E8%AA%BF%E6%95%99%E6%B8%88%E3%81%AE%E3%83%9E%E3%82%BE%E5%A5%B4%E2%97%8F%E3%81%A7%E3%81%97%E3%81%9F%E3%80%82%20%E6%A1%83%E4%B9%83%E6%9C%A8%E3%81%8B%E3%81%AA&amp;tr=http%3A%2F%2Fsukebei.tracker.wf%3A8888%2Fannounce&amp;tr=udp%3A%2F%2Fopen.stealth.si%3A80%2Fannounce&amp;tr=udp%3A%2F%2Ftracker.opentrackr.org%3A1337%2Fannounce&amp;tr=udp%3A%2F%2Fexodus.desync.com%3A6969%2Fannounce&amp;tr=udp%3A%2F%2Ftracker.torrent.eu.org%3A451%2Fannounce" rel="nofollow" class="magnet-click-track"><i class="fa fa-fw fa-magnet" rel="nofollow"></i> Magnet</a></td>
|
|
||||||
<td><i class="fas fa-weight-hanging"></i> 1.3gb</td>
|
|
||||||
<td><strong>S:</strong> 30</td>
|
|
||||||
<td><strong>L:</strong> 6</td>
|
|
||||||
<td><i class="far fa-calendar-alt"></i> 22/07/25</td>
|
|
||||||
</tr>
|
|
||||||
<tr style="vertical-align: middle">
|
|
||||||
2025-07-23 11:22:20.062 26023-26023 Lunatic bums.lunatic.launcher E <td><a onclick="sendEvent('Torrent Click','Main List Movie','201882')" href="/download/460809" rel="nofollow" class="download-click-track"><i class="fa fa-fw fa-download"></i> Download</a> <a onclick="sendEvent('Magnet Click','Main List Movie','201882')" href="magnet:?xt=urn:btih:cb582ed50fb3d342c2c668d2a33f7b143e1f1b03&amp;dn=%2B%2B%2B%20%5BFHDC%5D%20IPZZ-574%20%E4%BF%BA%E3%81%AE%E7%9F%A5%E3%82%89%E3%81%AA%E3%81%84%E5%A6%BB%E3%81%AE%E6%AD%AA%E3%82%93%E3%81%A0%E6%80%A7%E7%99%96%E2%80%A6%20%E6%99%AE%E6%AE%B5%E5%84%AA%E3%81%97%E3%81%84%E6%9C%80%E6%84%9B%E3%81%AE%E5%A6%BB%E3%81%AF%E3%83%89S%E9%9A%A3%E4%BA%BA%E3%81%AB%E8%AA%BF%E6%95%99%E6%B8%88%E3%81%AE%E3%83%9E%E3%82%BE%E5%A5%B4%E2%97%8F%E3%81%A7%E3%81%97%E3%81%9F%E3%80%82%20%E6%A1%83%E4%B9%83%E6%9C%A8%E3%81%8B%E3%81%AA&amp;tr=http%3A%2F%2Fsukebei.tracker.wf%3A8888%2Fannounce&amp;tr=udp%3A%2F%2Fopen.stealth.si%3A80%2Fannounce&amp;tr=udp%3A%2F%2Ftracker.opentrackr.org%3A1337%2Fannounce&amp;tr=udp%3A%2F%2Fexodus.desync.com%3A6969%2Fannounce&amp;tr=udp%3A%2F%2Ftracker.torrent.eu.org%3A451%2Fannounce" rel="nofollow" class="magnet-click-track"><i class="fa fa-fw fa-magnet" rel="nofollow"></i> Magnet</a></td>
|
|
||||||
<td><i class="fas fa-weight-hanging"></i> 5.3gb</td>
|
|
||||||
<td><strong>S:</strong> 60</td>
|
|
||||||
<td><strong>L:</strong> 23</td>
|
|
||||||
<td><i class="far fa-calendar-alt"></i> 22/07/25</td>
|
|
||||||
</tr>
|
|
||||||
<tr>
|
|
||||||
<td colspan="5">
|
|
||||||
<div class="text-right">
|
|
||||||
<a href="/movie/ipzz-574-201882"> more torrents >> </a>
|
|
||||||
</div></td>
|
|
||||||
</tr>
|
|
||||||
</tbody>
|
|
||||||
</table>
|
|
||||||
<div class="mb-4">
|
|
||||||
</div>
|
|
||||||
@ -291,6 +291,180 @@ if (port) {
|
|||||||
e.remove()
|
e.remove()
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
if (document.querySelectorAll('[class^="code-block"]')) {
|
||||||
|
document.querySelectorAll('[class^="code-block"]').forEach(e => e.remove())
|
||||||
|
}
|
||||||
|
if (document.querySelectorAll('.ad-template')) {
|
||||||
|
document.querySelectorAll('.ad-template').forEach(function (e) {
|
||||||
|
e.remove()
|
||||||
|
})
|
||||||
|
}
|
||||||
|
if (document.querySelectorAll('[class^="popupBanner_w popupOpen"]')) {
|
||||||
|
document.querySelectorAll('[class^="popupBanner_w popupOpen"]').forEach(function (e) {
|
||||||
|
e.remove()
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
if (document.querySelectorAll('iframe')) {
|
||||||
|
document.querySelectorAll('iframe').forEach(function (e) {
|
||||||
|
if (e.getAttribute("src") != null && (e.getAttribute("src").search("ads") > -1 || e.getAttribute("src").search("coupang") > -1)) {
|
||||||
|
e.remove()
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
if (location.href.search("x.com") > -1) {
|
||||||
|
var mainClass = document.querySelector('section').className
|
||||||
|
|
||||||
|
document.querySelector('section').querySelectorAll('div[class="'+ mainClass +'"]').forEach(function (e) {
|
||||||
|
if (e.hasAttribute("data-testid") && e.querySelector('video')) {
|
||||||
|
e.querySelectorAll('[poster]').forEach(function (e) {
|
||||||
|
|
||||||
|
})
|
||||||
|
console.log(e.innerHTML)
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
if (document.querySelectorAll('[data-banner^="coupang-"]')) {
|
||||||
|
document.querySelectorAll('[data-banner^="coupang-"]').forEach(e => e.remove())
|
||||||
|
}
|
||||||
|
|
||||||
|
if (document.querySelectorAll('[id^="mobonDivBanner"]')) {
|
||||||
|
document.querySelectorAll('[id^="mobonDivBanner"]').forEach(e => e.remove())
|
||||||
|
}
|
||||||
|
if (document.querySelectorAll('[id^="pnlTopAd"]')) {
|
||||||
|
document.querySelectorAll('[id^="pnlTopAd"]').forEach(e => e.remove())
|
||||||
|
}
|
||||||
|
if (document.querySelectorAll('[class^="ad-tag"]')) {
|
||||||
|
document.querySelectorAll('[class^="ad-tag"]').forEach(e => e.remove())
|
||||||
|
}
|
||||||
|
if (document.querySelectorAll('[class^="science-banner-area"]')) {
|
||||||
|
document.querySelectorAll('[class^="science-banner-area"]').forEach(e=> e.remove())
|
||||||
|
}
|
||||||
|
if (location.href.search("torrentzota") > -1 && document.querySelectorAll('a')) {
|
||||||
|
document.querySelectorAll('a').forEach(function (e) {
|
||||||
|
if (e.getAttribute('href') != null && e.getAttribute('href').startsWith("/adver-")) {
|
||||||
|
e.remove()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
)
|
||||||
|
if(document.querySelectorAll('[class^="py-4 flex flex-row border-b topic-item"]').length > 1) {
|
||||||
|
var datas = []
|
||||||
|
document.querySelectorAll('[class^="py-4 flex flex-row border-b topic-item"]').forEach(function (e) {
|
||||||
|
var title = ""
|
||||||
|
var link = ""
|
||||||
|
e.querySelectorAll("a").forEach(function (e){
|
||||||
|
if(e.getAttribute("class") === "item-link"){
|
||||||
|
title = e.getAttribute('title')
|
||||||
|
}
|
||||||
|
if(e.getAttribute("class") === "item-link"){
|
||||||
|
link = e.getAttribute('href')
|
||||||
|
if (link.length > 0) {
|
||||||
|
link = location.protocol + '//' + location.hostname + link
|
||||||
|
}
|
||||||
|
}
|
||||||
|
})
|
||||||
|
var description = e.querySelector('.flex-none w-16 text-center').textContent + e.querySelector('.badge badge-third w-auto px-1 flex-none mr-2 float-left').textContent
|
||||||
|
var md = e.querySelector(".flex-none w-14 text-center hidden md:block").textContent
|
||||||
|
|
||||||
|
let todayYear = new Date().getFullYear();
|
||||||
|
let now = new Date();
|
||||||
|
let hh = String(now.getHours()).padStart(2, '0'); // 시 (2자리)
|
||||||
|
let mm = String(now.getMinutes()).padStart(2, '0'); // 분 (2자리)
|
||||||
|
let ss = String(now.getSeconds()).padStart(2, '0'); // 초 (2자리)
|
||||||
|
|
||||||
|
let time = `${hh}:${mm}:${ss}`;
|
||||||
|
let combinedStr = todayYear + "-" + md + " " + time;
|
||||||
|
let dateObj = new Date(combinedStr);
|
||||||
|
|
||||||
|
datas.push({
|
||||||
|
"title" : title,
|
||||||
|
"description" : description,
|
||||||
|
"originPage" : link,
|
||||||
|
"pubDate" : dateObj.getTime(),
|
||||||
|
"category" : "TORRENT"
|
||||||
|
});
|
||||||
|
})
|
||||||
|
if(datas.length > 0) {
|
||||||
|
sendMessage(
|
||||||
|
{
|
||||||
|
type: "PRIVATES",
|
||||||
|
privates: datas,
|
||||||
|
currentPage : location.href
|
||||||
|
}
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (document.querySelectorAll('[class^="w-full flex"]').length > 1) {
|
||||||
|
var datas = []
|
||||||
|
document.querySelectorAll('[class^="w-full flex"]').forEach(function (e) {
|
||||||
|
var thumbnail = ""
|
||||||
|
e.querySelectorAll("img").forEach(function (e){
|
||||||
|
if(e.getAttribute("class") === "border"){
|
||||||
|
thumbnail = e.getAttribute('src')
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
|
var title = ""
|
||||||
|
var link = ""
|
||||||
|
e.querySelectorAll("a").forEach(function (e){
|
||||||
|
if(e.getAttribute("class") === "item-link"){
|
||||||
|
title = e.getAttribute('title')
|
||||||
|
}
|
||||||
|
if(e.getAttribute("class") === "item-link"){
|
||||||
|
link = e.getAttribute('href')
|
||||||
|
if (link.length > 0) {
|
||||||
|
link = location.protocol + '//' + location.hostname + link
|
||||||
|
}
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
|
|
||||||
|
var description = ""
|
||||||
|
var time = ""
|
||||||
|
var md = ""
|
||||||
|
if(e.querySelector('[class^="pb-2 w-100 text-gray-500"]')){
|
||||||
|
description = e.querySelector('[class^="pb-2 w-100 text-gray-500"]').textContent.replace(/\s+/g, ' ').trim();
|
||||||
|
md = description.split(" ")[1].trim();
|
||||||
|
time = description.split(" ")[2].trim();
|
||||||
|
description = description.split(" ")[0].trim();
|
||||||
|
}
|
||||||
|
console.log(link)
|
||||||
|
console.log(thumbnail)
|
||||||
|
console.log(title)
|
||||||
|
console.log(description)
|
||||||
|
console.log(md)
|
||||||
|
console.log(time)
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
let todayYear = new Date().getFullYear();
|
||||||
|
let combinedStr = todayYear + "-" + md + " " + time;
|
||||||
|
let dateObj = new Date(combinedStr);
|
||||||
|
|
||||||
|
datas.push({
|
||||||
|
"title" : title,
|
||||||
|
"description" : description,
|
||||||
|
"originPage" : link,
|
||||||
|
"thumbnail" : thumbnail,
|
||||||
|
"pubDate" : dateObj.getTime(),
|
||||||
|
"category" : "TORRENT"
|
||||||
|
});
|
||||||
|
})
|
||||||
|
if(datas.length > 0) {
|
||||||
|
sendMessage(
|
||||||
|
{
|
||||||
|
type: "PRIVATES",
|
||||||
|
privates: datas,
|
||||||
|
currentPage : location.href
|
||||||
|
}
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
if (document.querySelectorAll('[class^="col-md-4 mb-4 video-item"]').length > 1) {
|
if (document.querySelectorAll('[class^="col-md-4 mb-4 video-item"]').length > 1) {
|
||||||
var datas = []
|
var datas = []
|
||||||
@ -441,17 +615,3 @@ function gotoNext() {
|
|||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
//
|
|
||||||
// if (document.readyState === "complete" || document.readyState === "interactive") {
|
|
||||||
// reportCookiesToNative();
|
|
||||||
// } else {
|
|
||||||
// window.addEventListener("DOMContentLoaded", reportCookiesToNative);
|
|
||||||
// }
|
|
||||||
// function reportCookiesToNative() {
|
|
||||||
// // 모든 쿠키를 읽어 네이티브로 전달
|
|
||||||
// sendMessage({type: "MSG", cookies: "DOMContentLoaded try to cookies send"});
|
|
||||||
// window.cookies.getAll({url: window.location.href}).then((cookies) => {
|
|
||||||
// // 쿠키 데이터를 네이티브(Android)로 전송
|
|
||||||
// sendMessage({type: "Cookies", cookies: cookies});
|
|
||||||
// });
|
|
||||||
// }
|
|
||||||
@ -46,6 +46,7 @@ import android.view.WindowInsets
|
|||||||
import android.view.WindowManager
|
import android.view.WindowManager
|
||||||
import androidx.activity.OnBackPressedCallback
|
import androidx.activity.OnBackPressedCallback
|
||||||
import androidx.annotation.RequiresApi
|
import androidx.annotation.RequiresApi
|
||||||
|
import androidx.core.content.ContextCompat
|
||||||
import androidx.core.net.toUri
|
import androidx.core.net.toUri
|
||||||
import androidx.core.splashscreen.SplashScreen.Companion.installSplashScreen
|
import androidx.core.splashscreen.SplashScreen.Companion.installSplashScreen
|
||||||
import androidx.core.view.ViewCompat
|
import androidx.core.view.ViewCompat
|
||||||
@ -62,6 +63,7 @@ import bums.lunatic.launcher.tokiz.Novels
|
|||||||
import bums.lunatic.launcher.common.CommonActivity
|
import bums.lunatic.launcher.common.CommonActivity
|
||||||
import bums.lunatic.launcher.databinding.LauncherActivityBinding
|
import bums.lunatic.launcher.databinding.LauncherActivityBinding
|
||||||
import bums.lunatic.launcher.feeds.WidgetHost
|
import bums.lunatic.launcher.feeds.WidgetHost
|
||||||
|
import bums.lunatic.launcher.helpers.BluetoothManager
|
||||||
import bums.lunatic.launcher.helpers.Constants.Companion.KEY_STATUS_BAR
|
import bums.lunatic.launcher.helpers.Constants.Companion.KEY_STATUS_BAR
|
||||||
import bums.lunatic.launcher.helpers.Constants.Companion.PREFS_SETTINGS
|
import bums.lunatic.launcher.helpers.Constants.Companion.PREFS_SETTINGS
|
||||||
import bums.lunatic.launcher.helpers.Constants.Companion.widgetHostId
|
import bums.lunatic.launcher.helpers.Constants.Companion.widgetHostId
|
||||||
@ -72,7 +74,9 @@ import bums.lunatic.launcher.home.RssViewBuilder
|
|||||||
import bums.lunatic.launcher.model.RssData
|
import bums.lunatic.launcher.model.RssData
|
||||||
import bums.lunatic.launcher.model.RssDataType
|
import bums.lunatic.launcher.model.RssDataType
|
||||||
import bums.lunatic.launcher.tokiz.Comics
|
import bums.lunatic.launcher.tokiz.Comics
|
||||||
|
import bums.lunatic.launcher.tokiz.Twitter
|
||||||
import bums.lunatic.launcher.tokiz.Webtoons
|
import bums.lunatic.launcher.tokiz.Webtoons
|
||||||
|
import bums.lunatic.launcher.tokiz.Zota
|
||||||
import bums.lunatic.launcher.utils.Blog
|
import bums.lunatic.launcher.utils.Blog
|
||||||
import bums.lunatic.launcher.utils.FeedParseManager
|
import bums.lunatic.launcher.utils.FeedParseManager
|
||||||
import bums.lunatic.launcher.utils.getJ
|
import bums.lunatic.launcher.utils.getJ
|
||||||
@ -115,6 +119,7 @@ import java.util.Calendar
|
|||||||
import java.util.Date
|
import java.util.Date
|
||||||
import java.util.concurrent.Executors
|
import java.util.concurrent.Executors
|
||||||
import java.util.concurrent.TimeUnit
|
import java.util.concurrent.TimeUnit
|
||||||
|
import kotlin.jvm.java
|
||||||
|
|
||||||
|
|
||||||
internal class LauncherActivity : CommonActivity() {
|
internal class LauncherActivity : CommonActivity() {
|
||||||
@ -130,41 +135,40 @@ internal class LauncherActivity : CommonActivity() {
|
|||||||
return sRuntime
|
return sRuntime
|
||||||
}
|
}
|
||||||
|
|
||||||
private var mWorkManager: WorkManager? = null
|
|
||||||
var isOpendFold = false
|
var isOpendFold = false
|
||||||
val qDayPeriod = 60L * 8L
|
val qDayPeriod = 60L * 8L
|
||||||
|
|
||||||
@JvmStatic var lActivity: LauncherActivity? = null
|
@JvmStatic var lActivity: LauncherActivity? = null
|
||||||
@JvmStatic var appWidgetManager: AppWidgetManager? = null
|
|
||||||
@JvmStatic var appWidgetHost: WidgetHost? = null
|
|
||||||
fun refreshDeviceData()
|
|
||||||
{
|
|
||||||
|
|
||||||
mWorkManager?.cancelAllWorkByTag(SMS_WORK_TAG)
|
// fun refreshDeviceData()
|
||||||
mWorkManager?.enqueueUniquePeriodicWork(
|
// {
|
||||||
SMS_WORK_TAG,
|
//
|
||||||
ExistingPeriodicWorkPolicy.CANCEL_AND_REENQUEUE,
|
// mWorkManager?.cancelAllWorkByTag(SMS_WORK_TAG)
|
||||||
PeriodicWorkRequestBuilder<RecentSmsGetter>(PrefLong.longTimePeriod.get(), TimeUnit.MINUTES)
|
// mWorkManager?.enqueueUniquePeriodicWork(
|
||||||
.addTag(SMS_WORK_TAG)
|
// SMS_WORK_TAG,
|
||||||
.build())
|
// ExistingPeriodicWorkPolicy.CANCEL_AND_REENQUEUE,
|
||||||
mWorkManager?.cancelAllWorkByTag(RecentCallGetter.TAG)
|
// PeriodicWorkRequestBuilder<RecentSmsGetter>(PrefLong.longTimePeriod.get(), TimeUnit.MINUTES)
|
||||||
mWorkManager?.enqueueUniquePeriodicWork(
|
// .addTag(SMS_WORK_TAG)
|
||||||
RecentCallGetter.TAG,
|
// .build())
|
||||||
ExistingPeriodicWorkPolicy.CANCEL_AND_REENQUEUE,
|
// mWorkManager?.cancelAllWorkByTag(RecentCallGetter.TAG)
|
||||||
PeriodicWorkRequestBuilder<RecentCallGetter>(PrefLong.longTimePeriod.get(), TimeUnit.MINUTES)
|
// mWorkManager?.enqueueUniquePeriodicWork(
|
||||||
.addTag(RecentCallGetter.TAG)
|
// RecentCallGetter.TAG,
|
||||||
.build())
|
// ExistingPeriodicWorkPolicy.CANCEL_AND_REENQUEUE,
|
||||||
|
// PeriodicWorkRequestBuilder<RecentCallGetter>(PrefLong.longTimePeriod.get(), TimeUnit.MINUTES)
|
||||||
mWorkManager?.cancelAllWorkByTag(ContactInfoGetter.TAG)
|
// .addTag(RecentCallGetter.TAG)
|
||||||
mWorkManager?.enqueueUniquePeriodicWork(
|
// .build())
|
||||||
ContactInfoGetter.TAG, ExistingPeriodicWorkPolicy.CANCEL_AND_REENQUEUE,
|
//
|
||||||
PeriodicWorkRequestBuilder<ContactInfoGetter>(12, TimeUnit.HOURS)
|
// mWorkManager?.cancelAllWorkByTag(ContactInfoGetter.TAG)
|
||||||
.addTag(ContactInfoGetter.TAG)
|
// mWorkManager?.enqueueUniquePeriodicWork(
|
||||||
.build())
|
// ContactInfoGetter.TAG, ExistingPeriodicWorkPolicy.CANCEL_AND_REENQUEUE,
|
||||||
|
// PeriodicWorkRequestBuilder<ContactInfoGetter>(12, TimeUnit.HOURS)
|
||||||
mWorkManager?.enqueue(OneTimeWorkRequest.from(AppInfoGetter::class.java))
|
// .addTag(ContactInfoGetter.TAG)
|
||||||
|
// .build())
|
||||||
}
|
//
|
||||||
|
// mWorkManager?.enqueue(OneTimeWorkRequest.from(AppInfoGetter::class.java))
|
||||||
|
//
|
||||||
|
// }
|
||||||
|
|
||||||
// fun runWeatherGetter() {
|
// fun runWeatherGetter() {
|
||||||
// Executors.newSingleThreadScheduledExecutor().schedule({
|
// Executors.newSingleThreadScheduledExecutor().schedule({
|
||||||
@ -172,92 +176,14 @@ internal class LauncherActivity : CommonActivity() {
|
|||||||
// }, 200L, TimeUnit.MILLISECONDS)
|
// }, 200L, TimeUnit.MILLISECONDS)
|
||||||
// }
|
// }
|
||||||
|
|
||||||
fun getCal() {
|
// fun getCal() {
|
||||||
Executors.newSingleThreadScheduledExecutor().schedule({
|
// Executors.newSingleThreadScheduledExecutor().schedule({
|
||||||
mWorkManager?.enqueue(OneTimeWorkRequest.from(CalendarGetter::class.java))
|
// mWorkManager?.enqueue(OneTimeWorkRequest.from(CalendarGetter::class.java))
|
||||||
}, 5, TimeUnit.SECONDS)
|
// }, 5, TimeUnit.SECONDS)
|
||||||
}
|
// }
|
||||||
|
|
||||||
val defaultDelay = 10L
|
|
||||||
|
|
||||||
fun refreshFeeds() {
|
|
||||||
mWorkManager?.cancelAllWork()
|
|
||||||
mWorkManager?.cancelAllWorkByTag(RuliWebGetter.TAG)
|
|
||||||
mWorkManager?.enqueueUniquePeriodicWork(
|
|
||||||
RuliWebGetter.TAG, ExistingPeriodicWorkPolicy.CANCEL_AND_REENQUEUE,
|
|
||||||
PeriodicWorkRequestBuilder<RuliWebGetter>(PrefLong.midTimePeriod.get(), TimeUnit.MINUTES)
|
|
||||||
.addTag(RuliWebGetter.TAG)
|
|
||||||
.build())
|
|
||||||
|
|
||||||
mWorkManager?.cancelAllWorkByTag(FEDDS_WORK_TAG)
|
|
||||||
mWorkManager?.enqueueUniquePeriodicWork(
|
|
||||||
FEDDS_WORK_TAG, ExistingPeriodicWorkPolicy.CANCEL_AND_REENQUEUE,
|
|
||||||
PeriodicWorkRequestBuilder<NewsFeedsGetter>(PrefLong.shortTimePeriod.get(), TimeUnit.MINUTES)
|
|
||||||
.addTag(FEDDS_WORK_TAG)
|
|
||||||
.build())
|
|
||||||
mWorkManager?.cancelAllWorkByTag(YT_WORK_TAG)
|
|
||||||
mWorkManager?.enqueueUniquePeriodicWork(
|
|
||||||
YT_WORK_TAG, ExistingPeriodicWorkPolicy.CANCEL_AND_REENQUEUE,
|
|
||||||
PeriodicWorkRequestBuilder<YoutubeGetter>(PrefLong.longTimePeriod.get(), TimeUnit.MINUTES)
|
|
||||||
.addTag(YT_WORK_TAG)
|
|
||||||
.build())
|
|
||||||
mWorkManager?.cancelAllWorkByTag(REDDIT_WORK_TAG)
|
|
||||||
mWorkManager?.enqueueUniquePeriodicWork(
|
|
||||||
REDDIT_WORK_TAG, ExistingPeriodicWorkPolicy.CANCEL_AND_REENQUEUE,
|
|
||||||
PeriodicWorkRequestBuilder<RedditGetter>(PrefLong.midTimePeriod.get(), TimeUnit.MINUTES)
|
|
||||||
.addTag(REDDIT_WORK_TAG)
|
|
||||||
.build())
|
|
||||||
mWorkManager?.cancelAllWorkByTag(FM_WORK_TAG)
|
|
||||||
mWorkManager?.enqueueUniquePeriodicWork(
|
|
||||||
FM_WORK_TAG, ExistingPeriodicWorkPolicy.CANCEL_AND_REENQUEUE,
|
|
||||||
PeriodicWorkRequestBuilder<FmKoreaGetter>(PrefLong.midTimePeriod.get(), TimeUnit.MINUTES)
|
|
||||||
.addTag(FM_WORK_TAG)
|
|
||||||
.build())
|
|
||||||
mWorkManager?.cancelAllWorkByTag(COMIC2_WORK_TAG)
|
|
||||||
mWorkManager?.enqueueUniquePeriodicWork(
|
|
||||||
COMIC2_WORK_TAG, ExistingPeriodicWorkPolicy.CANCEL_AND_REENQUEUE,
|
|
||||||
PeriodicWorkRequestBuilder<DotaxGetter>(PrefLong.midTimePeriod.get(), TimeUnit.MINUTES)
|
|
||||||
.addTag(COMIC2_WORK_TAG)
|
|
||||||
.build())
|
|
||||||
mWorkManager?.cancelAllWorkByTag(ClienGetter.TAG)
|
|
||||||
mWorkManager?.enqueueUniquePeriodicWork(
|
|
||||||
ClienGetter.TAG, ExistingPeriodicWorkPolicy.CANCEL_AND_REENQUEUE,
|
|
||||||
PeriodicWorkRequestBuilder<ClienGetter>(PrefLong.midTimePeriod.get(), TimeUnit.MINUTES)
|
|
||||||
.addTag(ClienGetter.TAG)
|
|
||||||
.build())
|
|
||||||
mWorkManager?.cancelAllWorkByTag(DCGetter.TAG)
|
|
||||||
mWorkManager?.enqueueUniquePeriodicWork(
|
|
||||||
DCGetter.TAG, ExistingPeriodicWorkPolicy.CANCEL_AND_REENQUEUE,
|
|
||||||
PeriodicWorkRequestBuilder<DCGetter>(PrefLong.midTimePeriod.get(), TimeUnit.MINUTES)
|
|
||||||
.addTag(DCGetter.TAG)
|
|
||||||
.build())
|
|
||||||
mWorkManager?.cancelAllWorkByTag(TheQooGetter.TAG)
|
|
||||||
mWorkManager?.enqueueUniquePeriodicWork(
|
|
||||||
TheQooGetter.TAG, ExistingPeriodicWorkPolicy.CANCEL_AND_REENQUEUE,
|
|
||||||
PeriodicWorkRequestBuilder<TheQooGetter>(PrefLong.midTimePeriod.get(), TimeUnit.MINUTES)
|
|
||||||
.addTag(TheQooGetter.TAG)
|
|
||||||
.build())
|
|
||||||
mWorkManager?.cancelAllWorkByTag(ArcaGetter.TAG)
|
|
||||||
mWorkManager?.enqueueUniquePeriodicWork(
|
|
||||||
ArcaGetter.TAG, ExistingPeriodicWorkPolicy.CANCEL_AND_REENQUEUE,
|
|
||||||
PeriodicWorkRequestBuilder<ArcaGetter>(PrefLong.midTimePeriod.get(), TimeUnit.MINUTES)
|
|
||||||
.addTag(ArcaGetter.TAG)
|
|
||||||
.build())
|
|
||||||
mWorkManager?.cancelAllWorkByTag(LocationGetter.TAG)
|
|
||||||
mWorkManager?.enqueueUniquePeriodicWork(
|
|
||||||
LocationGetter.TAG, ExistingPeriodicWorkPolicy.CANCEL_AND_REENQUEUE,
|
|
||||||
PeriodicWorkRequestBuilder<LocationGetter>(PrefLong.locationTimePeriod.get(), TimeUnit.MINUTES)
|
|
||||||
.addTag(LocationGetter.TAG)
|
|
||||||
.build())
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
fun workmanager() : WorkManager? {
|
|
||||||
if (mWorkManager == null && lActivity != null) {
|
|
||||||
mWorkManager = WorkManager.getInstance(lActivity!!)
|
|
||||||
}
|
|
||||||
return mWorkManager
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -305,15 +231,6 @@ internal class LauncherActivity : CommonActivity() {
|
|||||||
when(ev.keyCode) {
|
when(ev.keyCode) {
|
||||||
KEYCODE_BUTTON_Y->{
|
KEYCODE_BUTTON_Y->{
|
||||||
|
|
||||||
CoroutineScope(Dispatchers.IO).launch {
|
|
||||||
String(Base64.getMimeDecoder().decode("aHR0cHM6Ly9qYXZtb3N0LnRvL2xhdGVzdC11cGRhdGVzCg==".toByteArray())).getJ().let { doc -> FeedParseManager.parse(doc){Blog.LOGE(it)} }
|
|
||||||
}
|
|
||||||
CoroutineScope(Dispatchers.IO).launch {
|
|
||||||
String.format(String(Base64.getMimeDecoder().decode("aHR0cHM6Ly9qYXZtb3N0LnRvL3NlYXJjaC9tb3ZpZS8lcw==".toByteArray())),"").getJ().let { doc -> FeedParseManager.parse(doc){Blog.LOGE(it)} }
|
|
||||||
}
|
|
||||||
CoroutineScope(Dispatchers.IO).launch {
|
|
||||||
String.format(String(Base64.getMimeDecoder().decode("aHR0cHM6Ly9rcjcxLnNvZ2lybC5zby8/cz0lcw==".toByteArray())),"").getJ().let { doc -> FeedParseManager.parse(doc){Blog.LOGE(it)} }
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
KEYCODE_BUTTON_X->{
|
KEYCODE_BUTTON_X->{
|
||||||
|
|
||||||
@ -332,11 +249,7 @@ internal class LauncherActivity : CommonActivity() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
KEYCODE_BUTTON_B->{
|
KEYCODE_BUTTON_B->{
|
||||||
// RssViewBuilder(lActivity!!)
|
|
||||||
// .setRssId("https://jav.guru")
|
|
||||||
// .webViewJavaScriptEnabled(true)
|
|
||||||
// .showIconClose(true).showIconBack(false).showProgressBar(true).backPressToClose(false).webViewMixedContentMode(1)
|
|
||||||
// .show("https://jav.guru")
|
|
||||||
}
|
}
|
||||||
KEYCODE_DPAD_DOWN->{
|
KEYCODE_DPAD_DOWN->{
|
||||||
|
|
||||||
@ -411,7 +324,6 @@ internal class LauncherActivity : CommonActivity() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
fun onClickCenterButton() {
|
fun onClickCenterButton() {
|
||||||
|
|
||||||
WorkersDb.getRealm().apply {
|
WorkersDb.getRealm().apply {
|
||||||
writeBlocking {
|
writeBlocking {
|
||||||
delete(
|
delete(
|
||||||
@ -584,7 +496,7 @@ internal class LauncherActivity : CommonActivity() {
|
|||||||
installSplashScreen()
|
installSplashScreen()
|
||||||
getWindow().addFlags(WindowManager.LayoutParams.FLAG_SECURE);
|
getWindow().addFlags(WindowManager.LayoutParams.FLAG_SECURE);
|
||||||
lActivity = this
|
lActivity = this
|
||||||
mWorkManager = WorkManager.getInstance(this)
|
|
||||||
DynamicColors.applyToActivityIfAvailable(this)
|
DynamicColors.applyToActivityIfAvailable(this)
|
||||||
|
|
||||||
|
|
||||||
@ -594,9 +506,6 @@ internal class LauncherActivity : CommonActivity() {
|
|||||||
|
|
||||||
binding = LauncherActivityBinding.inflate(layoutInflater)
|
binding = LauncherActivityBinding.inflate(layoutInflater)
|
||||||
setContentView(binding.root)
|
setContentView(binding.root)
|
||||||
appWidgetManager = AppWidgetManager.getInstance(applicationContext)
|
|
||||||
appWidgetHost = WidgetHost(applicationContext, widgetHostId)
|
|
||||||
appWidgetHost?.startListening()
|
|
||||||
HeadsetActionButtonReceiver.register(this)
|
HeadsetActionButtonReceiver.register(this)
|
||||||
|
|
||||||
|
|
||||||
@ -617,6 +526,9 @@ internal class LauncherActivity : CommonActivity() {
|
|||||||
handleBackPress()
|
handleBackPress()
|
||||||
updateLocationService()
|
updateLocationService()
|
||||||
binding.feeds.isChecked = true
|
binding.feeds.isChecked = true
|
||||||
|
|
||||||
|
val intent = Intent(this, BluetoothManager::class.java)
|
||||||
|
ContextCompat.startForegroundService(this, intent)
|
||||||
}
|
}
|
||||||
|
|
||||||
fun showContents(id : Int) {
|
fun showContents(id : Int) {
|
||||||
@ -641,6 +553,16 @@ internal class LauncherActivity : CommonActivity() {
|
|||||||
.replace(R.id.fragment_container, Comics())
|
.replace(R.id.fragment_container, Comics())
|
||||||
.commit()
|
.commit()
|
||||||
}
|
}
|
||||||
|
R.id.zota ->{
|
||||||
|
supportFragmentManager.beginTransaction()
|
||||||
|
.replace(R.id.fragment_container, Zota())
|
||||||
|
.commit()
|
||||||
|
}
|
||||||
|
R.id.twitter ->{
|
||||||
|
supportFragmentManager.beginTransaction()
|
||||||
|
.replace(R.id.fragment_container, Twitter())
|
||||||
|
.commit()
|
||||||
|
}
|
||||||
else -> {}
|
else -> {}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -665,7 +587,6 @@ internal class LauncherActivity : CommonActivity() {
|
|||||||
override fun onDestroy() {
|
override fun onDestroy() {
|
||||||
|
|
||||||
|
|
||||||
appWidgetHost?.stopListening()
|
|
||||||
try {
|
try {
|
||||||
sRuntime?.shutdown()
|
sRuntime?.shutdown()
|
||||||
sRuntime = null
|
sRuntime = null
|
||||||
@ -689,8 +610,6 @@ internal class LauncherActivity : CommonActivity() {
|
|||||||
@RequiresApi(Build.VERSION_CODES.O_MR1)
|
@RequiresApi(Build.VERSION_CODES.O_MR1)
|
||||||
override fun onResume() {
|
override fun onResume() {
|
||||||
super.onResume()
|
super.onResume()
|
||||||
refreshFeeds()
|
|
||||||
// blutoothManager?.getPairedDevices()
|
|
||||||
Blog.LOGE("LauncherActivity onResume")
|
Blog.LOGE("LauncherActivity onResume")
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -746,6 +665,9 @@ internal class LauncherActivity : CommonActivity() {
|
|||||||
currentFragment.doNextPage()
|
currentFragment.doNextPage()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
is Novels -> {
|
||||||
|
currentFragment.actionNextEvent(false)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
|||||||
@ -2,6 +2,10 @@ package bums.lunatic.launcher.helpers
|
|||||||
|
|
||||||
import android.Manifest
|
import android.Manifest
|
||||||
import android.annotation.SuppressLint
|
import android.annotation.SuppressLint
|
||||||
|
import android.app.Notification
|
||||||
|
import android.app.NotificationChannel
|
||||||
|
import android.app.NotificationManager
|
||||||
|
import android.app.Service
|
||||||
import android.bluetooth.BluetoothAdapter
|
import android.bluetooth.BluetoothAdapter
|
||||||
import android.bluetooth.BluetoothDevice
|
import android.bluetooth.BluetoothDevice
|
||||||
import android.content.BroadcastReceiver
|
import android.content.BroadcastReceiver
|
||||||
@ -9,8 +13,33 @@ import android.content.Context
|
|||||||
import android.content.Intent
|
import android.content.Intent
|
||||||
import android.content.IntentFilter
|
import android.content.IntentFilter
|
||||||
import android.content.pm.PackageManager
|
import android.content.pm.PackageManager
|
||||||
|
import android.os.Build
|
||||||
|
import android.os.IBinder
|
||||||
import androidx.core.app.ActivityCompat
|
import androidx.core.app.ActivityCompat
|
||||||
|
import androidx.core.app.NotificationCompat
|
||||||
|
import androidx.work.ExistingPeriodicWorkPolicy
|
||||||
|
import androidx.work.PeriodicWorkRequestBuilder
|
||||||
|
import androidx.work.WorkManager
|
||||||
|
import bums.lunatic.launcher.LauncherActivity.Companion.lActivity
|
||||||
|
import bums.lunatic.launcher.R
|
||||||
|
import bums.lunatic.launcher.home.GeckoWeb
|
||||||
import bums.lunatic.launcher.utils.Blog
|
import bums.lunatic.launcher.utils.Blog
|
||||||
|
import bums.lunatic.launcher.workers.ArcaGetter
|
||||||
|
import bums.lunatic.launcher.workers.ClienGetter
|
||||||
|
import bums.lunatic.launcher.workers.DCGetter
|
||||||
|
import bums.lunatic.launcher.workers.DotaxGetter
|
||||||
|
import bums.lunatic.launcher.workers.DotaxGetter.Companion.COMIC2_WORK_TAG
|
||||||
|
import bums.lunatic.launcher.workers.FmKoreaGetter
|
||||||
|
import bums.lunatic.launcher.workers.FmKoreaGetter.Companion.FM_WORK_TAG
|
||||||
|
import bums.lunatic.launcher.workers.LocationGetter
|
||||||
|
import bums.lunatic.launcher.workers.NewsFeedsGetter
|
||||||
|
import bums.lunatic.launcher.workers.NewsFeedsGetter.Companion.FEDDS_WORK_TAG
|
||||||
|
import bums.lunatic.launcher.workers.RedditGetter
|
||||||
|
import bums.lunatic.launcher.workers.RedditGetter.Companion.REDDIT_WORK_TAG
|
||||||
|
import bums.lunatic.launcher.workers.RuliWebGetter
|
||||||
|
import bums.lunatic.launcher.workers.TheQooGetter
|
||||||
|
import bums.lunatic.launcher.workers.YoutubeGetter
|
||||||
|
import bums.lunatic.launcher.workers.YoutubeGetter.Companion.YT_WORK_TAG
|
||||||
import kotlinx.coroutines.CoroutineScope
|
import kotlinx.coroutines.CoroutineScope
|
||||||
import kotlinx.coroutines.Dispatchers
|
import kotlinx.coroutines.Dispatchers
|
||||||
import kotlinx.coroutines.launch
|
import kotlinx.coroutines.launch
|
||||||
@ -22,7 +51,7 @@ import okhttp3.ResponseBody
|
|||||||
import java.util.concurrent.TimeUnit
|
import java.util.concurrent.TimeUnit
|
||||||
|
|
||||||
|
|
||||||
class BluetoothManager {
|
class BluetoothManager : Service() {
|
||||||
|
|
||||||
enum class BLUETOOTH_STATE(val statestr: String) {
|
enum class BLUETOOTH_STATE(val statestr: String) {
|
||||||
ENABLED("enabledBlutooth"),
|
ENABLED("enabledBlutooth"),
|
||||||
@ -30,50 +59,61 @@ class BluetoothManager {
|
|||||||
NOT_SUPPORT("notSupport")
|
NOT_SUPPORT("notSupport")
|
||||||
}
|
}
|
||||||
|
|
||||||
lateinit var context: Context
|
|
||||||
var blueToothAdapter:BluetoothAdapter? = null
|
var blueToothAdapter:BluetoothAdapter? = null
|
||||||
|
private var mWorkManager: WorkManager? = null
|
||||||
|
|
||||||
constructor(context: Context) {
|
val NOTIF_ID = 830721
|
||||||
this.context = context
|
override fun onCreate() {
|
||||||
|
super.onCreate()
|
||||||
|
Blog.LOGE("onCreate")
|
||||||
|
mWorkManager = WorkManager.getInstance(this)
|
||||||
|
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
|
||||||
|
startForeground(NOTIF_ID, createNotification(this))
|
||||||
}
|
}
|
||||||
constructor() {
|
val filter = IntentFilter(BluetoothDevice.ACTION_ACL_CONNECTED)
|
||||||
|
registerReceiver(bluetoothreceiver, filter)
|
||||||
}
|
refreshFeeds()
|
||||||
|
// GeckoWeb(applicationContext).apply {
|
||||||
// init {
|
// loadUrl("aHR0cHM6Ly9pamF2dG9ycmVudC5jb20=")
|
||||||
// this.context = context
|
|
||||||
// }
|
// }
|
||||||
|
|
||||||
fun initBluetoothAdapter(){
|
|
||||||
if ( blueToothAdapter == null ){
|
|
||||||
val bluetoothManager = context.getSystemService(Context.BLUETOOTH_SERVICE) as android.bluetooth.BluetoothManager
|
|
||||||
blueToothAdapter = bluetoothManager.getAdapter()
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
fun register(){
|
override fun onBind(intent: Intent?): IBinder? {
|
||||||
if (context == null) return
|
Blog.LOGE("intent >>> ${intent}")
|
||||||
context.registerReceiver(bluetoothreceiver, addFilterAction())
|
return null
|
||||||
|
}
|
||||||
|
private val CHANNEL_ID = "ble_service_channel"
|
||||||
|
private val CHANNEL_NAME = "BLE 서비스"
|
||||||
|
|
||||||
|
fun createNotification(context: Context): Notification {
|
||||||
|
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
|
||||||
|
val channel = NotificationChannel(
|
||||||
|
CHANNEL_ID,
|
||||||
|
CHANNEL_NAME,
|
||||||
|
NotificationManager.IMPORTANCE_HIGH // 중요도 낮게 (필요시 변경)
|
||||||
|
)
|
||||||
|
val notificationManager =
|
||||||
|
context.getSystemService(Context.NOTIFICATION_SERVICE) as NotificationManager
|
||||||
|
notificationManager.createNotificationChannel(channel)
|
||||||
|
}
|
||||||
|
return NotificationCompat.Builder(context, CHANNEL_ID)
|
||||||
|
.setContentTitle("BLE 서비스")
|
||||||
|
.setContentText("실행중입니다.")
|
||||||
|
.setPriority(NotificationCompat.PRIORITY_MAX)
|
||||||
|
.setSmallIcon(R.drawable.ic_b)
|
||||||
|
.setOngoing(true) // 사용자가 알림을 스와이프로 지울 수 없게 만듦
|
||||||
|
.build()
|
||||||
}
|
}
|
||||||
|
|
||||||
fun unregister(){
|
|
||||||
if (context == null) return
|
|
||||||
context.unregisterReceiver(bluetoothreceiver)
|
|
||||||
}
|
|
||||||
|
|
||||||
//페어링된 디바이스 정보 가져오기
|
//페어링된 디바이스 정보 가져오기
|
||||||
|
|
||||||
fun getPairedDevices() {
|
fun getPairedDevices() {
|
||||||
val bluetoothManager = context.getSystemService(Context.BLUETOOTH_SERVICE) as android.bluetooth.BluetoothManager
|
val bluetoothManager = applicationContext.getSystemService(Context.BLUETOOTH_SERVICE) as android.bluetooth.BluetoothManager
|
||||||
blueToothAdapter = bluetoothManager.adapter
|
blueToothAdapter = bluetoothManager.adapter
|
||||||
if (ActivityCompat.checkSelfPermission(context,Manifest.permission.BLUETOOTH_CONNECT) != PackageManager.PERMISSION_GRANTED) return
|
if (ActivityCompat.checkSelfPermission(applicationContext,Manifest.permission.BLUETOOTH_CONNECT) != PackageManager.PERMISSION_GRANTED) return
|
||||||
var pairedDevices = blueToothAdapter?.bondedDevices
|
var pairedDevices = blueToothAdapter?.bondedDevices
|
||||||
if (pairedDevices?.size ?: 0 > 0) {
|
if (pairedDevices?.size ?: 0 > 0) {
|
||||||
pairedDevices?.forEach { i ->
|
pairedDevices?.forEach { i ->
|
||||||
//bondState : 12 (페어링 등록된 상태)
|
|
||||||
//bondState : 10 (페어링 등록 안됨)
|
|
||||||
// BLog.LOGE("getPairedDevices() / name : ${i.name}")
|
|
||||||
// BLog.LOGE("getPairedDevices() / bondState : ${i.bondState}")
|
|
||||||
val isConnected = isConnected(i)
|
val isConnected = isConnected(i)
|
||||||
if(PrefString.carName.get().length > 2 && i.name.equals(PrefString.carName.get()) && isConnected != PrefBoolean.isConnectedCar.get()) {
|
if(PrefString.carName.get().length > 2 && i.name.equals(PrefString.carName.get()) && isConnected != PrefBoolean.isConnectedCar.get()) {
|
||||||
PrefBoolean.isConnectedCar.set(isConnected)
|
PrefBoolean.isConnectedCar.set(isConnected)
|
||||||
@ -83,6 +123,84 @@ class BluetoothManager {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fun refreshFeeds() {
|
||||||
|
mWorkManager?.cancelAllWork()
|
||||||
|
mWorkManager?.cancelAllWorkByTag(RuliWebGetter.TAG)
|
||||||
|
mWorkManager?.enqueueUniquePeriodicWork(
|
||||||
|
RuliWebGetter.TAG, ExistingPeriodicWorkPolicy.CANCEL_AND_REENQUEUE,
|
||||||
|
PeriodicWorkRequestBuilder<RuliWebGetter>(PrefLong.midTimePeriod.get(), TimeUnit.MINUTES)
|
||||||
|
.addTag(RuliWebGetter.TAG)
|
||||||
|
.build())
|
||||||
|
|
||||||
|
mWorkManager?.cancelAllWorkByTag(FEDDS_WORK_TAG)
|
||||||
|
mWorkManager?.enqueueUniquePeriodicWork(
|
||||||
|
FEDDS_WORK_TAG, ExistingPeriodicWorkPolicy.CANCEL_AND_REENQUEUE,
|
||||||
|
PeriodicWorkRequestBuilder<NewsFeedsGetter>(PrefLong.shortTimePeriod.get(), TimeUnit.MINUTES)
|
||||||
|
.addTag(FEDDS_WORK_TAG)
|
||||||
|
.build())
|
||||||
|
mWorkManager?.cancelAllWorkByTag(YT_WORK_TAG)
|
||||||
|
mWorkManager?.enqueueUniquePeriodicWork(
|
||||||
|
YT_WORK_TAG, ExistingPeriodicWorkPolicy.CANCEL_AND_REENQUEUE,
|
||||||
|
PeriodicWorkRequestBuilder<YoutubeGetter>(PrefLong.longTimePeriod.get(), TimeUnit.MINUTES)
|
||||||
|
.addTag(YT_WORK_TAG)
|
||||||
|
.build())
|
||||||
|
mWorkManager?.cancelAllWorkByTag(REDDIT_WORK_TAG)
|
||||||
|
mWorkManager?.enqueueUniquePeriodicWork(
|
||||||
|
REDDIT_WORK_TAG, ExistingPeriodicWorkPolicy.CANCEL_AND_REENQUEUE,
|
||||||
|
PeriodicWorkRequestBuilder<RedditGetter>(PrefLong.midTimePeriod.get(), TimeUnit.MINUTES)
|
||||||
|
.addTag(REDDIT_WORK_TAG)
|
||||||
|
.build())
|
||||||
|
mWorkManager?.cancelAllWorkByTag(FM_WORK_TAG)
|
||||||
|
mWorkManager?.enqueueUniquePeriodicWork(
|
||||||
|
FM_WORK_TAG, ExistingPeriodicWorkPolicy.CANCEL_AND_REENQUEUE,
|
||||||
|
PeriodicWorkRequestBuilder<FmKoreaGetter>(PrefLong.midTimePeriod.get(), TimeUnit.MINUTES)
|
||||||
|
.addTag(FM_WORK_TAG)
|
||||||
|
.build())
|
||||||
|
mWorkManager?.cancelAllWorkByTag(COMIC2_WORK_TAG)
|
||||||
|
mWorkManager?.enqueueUniquePeriodicWork(
|
||||||
|
COMIC2_WORK_TAG, ExistingPeriodicWorkPolicy.CANCEL_AND_REENQUEUE,
|
||||||
|
PeriodicWorkRequestBuilder<DotaxGetter>(PrefLong.midTimePeriod.get(), TimeUnit.MINUTES)
|
||||||
|
.addTag(COMIC2_WORK_TAG)
|
||||||
|
.build())
|
||||||
|
mWorkManager?.cancelAllWorkByTag(ClienGetter.TAG)
|
||||||
|
mWorkManager?.enqueueUniquePeriodicWork(
|
||||||
|
ClienGetter.TAG, ExistingPeriodicWorkPolicy.CANCEL_AND_REENQUEUE,
|
||||||
|
PeriodicWorkRequestBuilder<ClienGetter>(PrefLong.midTimePeriod.get(), TimeUnit.MINUTES)
|
||||||
|
.addTag(ClienGetter.TAG)
|
||||||
|
.build())
|
||||||
|
mWorkManager?.cancelAllWorkByTag(DCGetter.TAG)
|
||||||
|
mWorkManager?.enqueueUniquePeriodicWork(
|
||||||
|
DCGetter.TAG, ExistingPeriodicWorkPolicy.CANCEL_AND_REENQUEUE,
|
||||||
|
PeriodicWorkRequestBuilder<DCGetter>(PrefLong.midTimePeriod.get(), TimeUnit.MINUTES)
|
||||||
|
.addTag(DCGetter.TAG)
|
||||||
|
.build())
|
||||||
|
mWorkManager?.cancelAllWorkByTag(TheQooGetter.TAG)
|
||||||
|
mWorkManager?.enqueueUniquePeriodicWork(
|
||||||
|
TheQooGetter.TAG, ExistingPeriodicWorkPolicy.CANCEL_AND_REENQUEUE,
|
||||||
|
PeriodicWorkRequestBuilder<TheQooGetter>(PrefLong.midTimePeriod.get(), TimeUnit.MINUTES)
|
||||||
|
.addTag(TheQooGetter.TAG)
|
||||||
|
.build())
|
||||||
|
mWorkManager?.cancelAllWorkByTag(ArcaGetter.TAG)
|
||||||
|
mWorkManager?.enqueueUniquePeriodicWork(
|
||||||
|
ArcaGetter.TAG, ExistingPeriodicWorkPolicy.CANCEL_AND_REENQUEUE,
|
||||||
|
PeriodicWorkRequestBuilder<ArcaGetter>(PrefLong.midTimePeriod.get(), TimeUnit.MINUTES)
|
||||||
|
.addTag(ArcaGetter.TAG)
|
||||||
|
.build())
|
||||||
|
mWorkManager?.cancelAllWorkByTag(LocationGetter.TAG)
|
||||||
|
mWorkManager?.enqueueUniquePeriodicWork(
|
||||||
|
LocationGetter.TAG, ExistingPeriodicWorkPolicy.CANCEL_AND_REENQUEUE,
|
||||||
|
PeriodicWorkRequestBuilder<LocationGetter>(PrefLong.locationTimePeriod.get(), TimeUnit.MINUTES)
|
||||||
|
.addTag(LocationGetter.TAG)
|
||||||
|
.build())
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
fun workmanager() : WorkManager? {
|
||||||
|
if (mWorkManager == null && lActivity != null) {
|
||||||
|
mWorkManager = WorkManager.getInstance(lActivity!!)
|
||||||
|
}
|
||||||
|
return mWorkManager
|
||||||
|
}
|
||||||
|
|
||||||
fun sendToI(boolean: Boolean) {
|
fun sendToI(boolean: Boolean) {
|
||||||
if (PrefString.telegramSendTarget.get().length > 5) {
|
if (PrefString.telegramSendTarget.get().length > 5) {
|
||||||
@ -94,20 +212,10 @@ class BluetoothManager {
|
|||||||
"${PrefString.carName.get()}의 시동이 꺼졌다요."
|
"${PrefString.carName.get()}의 시동이 꺼졌다요."
|
||||||
}}"
|
}}"
|
||||||
//7068729507
|
//7068729507
|
||||||
// OkHttp 클라이언트 객체 생성
|
val response: Response = OkHttpClient.Builder()
|
||||||
val client = OkHttpClient.Builder()
|
|
||||||
.connectionPool(ConnectionPool(5, 60, TimeUnit.SECONDS))
|
.connectionPool(ConnectionPool(5, 60, TimeUnit.SECONDS))
|
||||||
.build()
|
.build().newCall(Request.Builder().url(url)
|
||||||
|
.addHeader("Content-Type", "application/json").get().build()).execute()
|
||||||
// GET 요청 객체 생성
|
|
||||||
val builder: Request.Builder = Request.Builder().url(url)
|
|
||||||
.addHeader("Content-Type", "application/json").get()
|
|
||||||
|
|
||||||
val request: Request = builder.build()
|
|
||||||
|
|
||||||
// BLog.LOGE("sendToI telegram before request ")
|
|
||||||
// OkHttp 클라이언트로 GET 요청 객체 전송
|
|
||||||
val response: Response = client.newCall(request).execute()
|
|
||||||
if (response.isSuccessful()) {
|
if (response.isSuccessful()) {
|
||||||
// 응답 받아서 처리
|
// 응답 받아서 처리
|
||||||
val body: ResponseBody? = response.body()
|
val body: ResponseBody? = response.body()
|
||||||
|
|||||||
@ -29,7 +29,7 @@ enum class PrefLong(val def : Long) : PrefKey<Long> {
|
|||||||
maxQueryCount(18L);
|
maxQueryCount(18L);
|
||||||
override fun set(value : Long) { PrefHelper.putLong(this.name, value) }
|
override fun set(value : Long) { PrefHelper.putLong(this.name, value) }
|
||||||
override fun get(def : Long?) : Long {
|
override fun get(def : Long?) : Long {
|
||||||
val value = PrefHelper.getLong(this.name, def ?: this.def) ?: this.def
|
val value = Math.max(15,PrefHelper.getLong(this.name, def ?: this.def) ?: this.def)
|
||||||
|
|
||||||
// Blog.LOGE("$name : $value")
|
// Blog.LOGE("$name : $value")
|
||||||
|
|
||||||
|
|||||||
@ -286,6 +286,7 @@ class GeckoWeb : BWebview {
|
|||||||
}
|
}
|
||||||
|
|
||||||
fun downloadImage(context: Context, url: Uri) {
|
fun downloadImage(context: Context, url: Uri) {
|
||||||
|
Blog.LOGE("url.lastPathSegment ${url.lastPathSegment}")
|
||||||
val fileName = url.lastPathSegment ?: "${SimpleDateFormat("yyyyMMddHHmmsss")}.jpg"
|
val fileName = url.lastPathSegment ?: "${SimpleDateFormat("yyyyMMddHHmmsss")}.jpg"
|
||||||
val request = DownloadManager.Request(url)
|
val request = DownloadManager.Request(url)
|
||||||
request.setTitle(fileName)
|
request.setTitle(fileName)
|
||||||
@ -687,10 +688,14 @@ class GeckoWeb : BWebview {
|
|||||||
var nUrl = url
|
var nUrl = url
|
||||||
Blog.LOGE("url >>>> ${url}")
|
Blog.LOGE("url >>>> ${url}")
|
||||||
if (url.endsWith("=")) {
|
if (url.endsWith("=")) {
|
||||||
|
try {
|
||||||
nUrl = String(java.util.Base64.getMimeDecoder().decode(url.toByteArray()))
|
nUrl = String(java.util.Base64.getMimeDecoder().decode(url.toByteArray()))
|
||||||
param?.let {
|
param?.let {
|
||||||
nUrl = nUrl.plus(param)
|
nUrl = nUrl.plus(param)
|
||||||
}
|
}
|
||||||
|
}catch (e: Exception) {
|
||||||
|
nUrl = url
|
||||||
|
}
|
||||||
} else if (url.startsWith("http") == false) {
|
} else if (url.startsWith("http") == false) {
|
||||||
nUrl = lastDomain
|
nUrl = lastDomain
|
||||||
}
|
}
|
||||||
|
|||||||
@ -50,7 +50,6 @@ import bums.lunatic.launcher.common.letTrue
|
|||||||
import bums.lunatic.launcher.databinding.LauncherHomeBinding
|
import bums.lunatic.launcher.databinding.LauncherHomeBinding
|
||||||
import bums.lunatic.launcher.helpers.Constants.Companion.PREFS_SETTINGS
|
import bums.lunatic.launcher.helpers.Constants.Companion.PREFS_SETTINGS
|
||||||
import bums.lunatic.launcher.home.adapters.RssItemAdapter
|
import bums.lunatic.launcher.home.adapters.RssItemAdapter
|
||||||
import bums.lunatic.launcher.home.adapters.RssItemAdapter.Companion.rssList
|
|
||||||
import bums.lunatic.launcher.home.adapters.SwipeToDeleteCallback
|
import bums.lunatic.launcher.home.adapters.SwipeToDeleteCallback
|
||||||
import bums.lunatic.launcher.model.RssData
|
import bums.lunatic.launcher.model.RssData
|
||||||
import bums.lunatic.launcher.model.RssDataType
|
import bums.lunatic.launcher.model.RssDataType
|
||||||
@ -101,7 +100,7 @@ internal class RssHome : Fragment() {
|
|||||||
fun rssStateVote() = (lasted?.filter { it.vote == true }?.size ?: -1) == (lasted?.size ?: 0)
|
fun rssStateVote() = (lasted?.filter { it.vote == true }?.size ?: -1) == (lasted?.size ?: 0)
|
||||||
var lasted: ArrayList<RssData> = arrayListOf()
|
var lasted: ArrayList<RssData> = arrayListOf()
|
||||||
var infosJob: Job? = null
|
var infosJob: Job? = null
|
||||||
var rssId = ""
|
// var rssId = ""
|
||||||
lateinit var mRssAdapter: RssItemAdapter
|
lateinit var mRssAdapter: RssItemAdapter
|
||||||
|
|
||||||
var mRssDataResult: RealmResults<RssData>? = null
|
var mRssDataResult: RealmResults<RssData>? = null
|
||||||
@ -336,25 +335,32 @@ internal class RssHome : Fragment() {
|
|||||||
builder.show()
|
builder.show()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
var currentRss : RssData? = null
|
||||||
@SuppressLint("SimpleDateFormat")
|
@SuppressLint("SimpleDateFormat")
|
||||||
fun openGecko(rssData: RssData? = null) {
|
fun openGecko(rssData: RssData? = null) {
|
||||||
binding.layoutRssSummary.root.visibility = View.GONE
|
binding.layoutRssSummary.root.visibility = View.GONE
|
||||||
if (rssData?.category()?.equals(RssDataType.PRIVATE) == false && rssData?.originPage?.isNotEmpty() == true) {
|
if (rssData?.category()?.equals(RssDataType.PRIVATE) == false && rssData?.originPage?.isNotEmpty() == true) {
|
||||||
rssData?.originPage?.let {
|
rssData?.let { rss ->
|
||||||
|
currentRss = rss
|
||||||
binding.geckoWeb.privateMode = false
|
binding.geckoWeb.privateMode = false
|
||||||
rssId = it
|
appendReadCount(rss, 1, false)
|
||||||
targetList.clear()
|
rss?.originPage?.let { rssId->
|
||||||
var setString = hashSetOf<String>()
|
synchronized(lasted) {
|
||||||
setString.addAll(rssList)
|
if (lasted.isNotEmpty()) {
|
||||||
setString.removeAll { it.equals(rssId) }
|
lasted.removeAll { target -> target.originPage.equals(rssId) }
|
||||||
targetList.addAll(setString)
|
}
|
||||||
|
}
|
||||||
binding.geckoWeb.loadUrl(rssId)
|
binding.geckoWeb.loadUrl(rssId)
|
||||||
}
|
}
|
||||||
|
}
|
||||||
} else if (rssData?.category()?.equals(RssDataType.PRIVATE) == true){
|
} else if (rssData?.category()?.equals(RssDataType.PRIVATE) == true){
|
||||||
rssData?.let {
|
rssData?.let {
|
||||||
binding.geckoWeb.privateMode = true
|
binding.geckoWeb.privateMode = true
|
||||||
|
synchronized(lasted) {
|
||||||
|
if (lasted.isNotEmpty()) {
|
||||||
lasted.removeAll { target -> target.originPage.equals(it.originPage) }
|
lasted.removeAll { target -> target.originPage.equals(it.originPage) }
|
||||||
|
}
|
||||||
|
}
|
||||||
appendReadCount(it, 1, false)
|
appendReadCount(it, 1, false)
|
||||||
Blog.LOGE("removeFirst >>> ${Gson().toJson(it)}")
|
Blog.LOGE("removeFirst >>> ${Gson().toJson(it)}")
|
||||||
binding.layoutRssSummary.title.tag = it
|
binding.layoutRssSummary.title.tag = it
|
||||||
@ -477,7 +483,8 @@ internal class RssHome : Fragment() {
|
|||||||
if (binding.geckoWeb.isVisible) {
|
if (binding.geckoWeb.isVisible) {
|
||||||
WorkersDb.getRealm().apply {
|
WorkersDb.getRealm().apply {
|
||||||
writeBlocking {
|
writeBlocking {
|
||||||
val result = query<RssData>().query("originPage == $0", rssId).find()
|
currentRss?.originPage?.let {
|
||||||
|
val result = query<RssData>().query("originPage == $0", it).find()
|
||||||
if (result.size > 0) {
|
if (result.size > 0) {
|
||||||
result.forEach {
|
result.forEach {
|
||||||
if (it.vote) {
|
if (it.vote) {
|
||||||
@ -487,6 +494,7 @@ internal class RssHome : Fragment() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
doNextPage()
|
doNextPage()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -552,12 +560,13 @@ internal class RssHome : Fragment() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
fun vote() {
|
fun vote() {
|
||||||
|
currentRss?.originPage.let {
|
||||||
Blog.LOGE("Arrow Center Click")
|
Blog.LOGE("Arrow Center Click")
|
||||||
WorkersDb.getRealm().apply {
|
WorkersDb.getRealm().apply {
|
||||||
writeBlocking {
|
writeBlocking {
|
||||||
val result = query<RssData>().query(
|
val result = query<RssData>().query(
|
||||||
if (imageView) "thumbnail == $0" else "originPage == $0",
|
if (imageView) "thumbnail == $0" else "originPage == $0",
|
||||||
rssId
|
it
|
||||||
).find()
|
).find()
|
||||||
if (result.size > 0) {
|
if (result.size > 0) {
|
||||||
result.forEach { it.vote = true }
|
result.forEach { it.vote = true }
|
||||||
@ -566,31 +575,25 @@ internal class RssHome : Fragment() {
|
|||||||
}
|
}
|
||||||
doNextPage()
|
doNextPage()
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
@SuppressLint("NewApi")
|
@SuppressLint("NewApi")
|
||||||
fun doNextPage() {
|
fun doNextPage() {
|
||||||
|
currentRss?.originPage.let {
|
||||||
WorkersDb.getRealm().apply {
|
WorkersDb.getRealm().apply {
|
||||||
writeBlocking {
|
writeBlocking {
|
||||||
val result = query<RssData>().query(
|
val result = query<RssData>().query(
|
||||||
if (imageView) "thumbnail == $0" else "originPage == $0",
|
if (imageView) "thumbnail == $0" else "originPage == $0",
|
||||||
rssId
|
it
|
||||||
).find()
|
).find()
|
||||||
if (result.size > 0) {
|
if (result.size > 0) {
|
||||||
result.forEach {
|
result.forEach { it.read = it.read + nomoreShowCount }
|
||||||
it.read = it.read + nomoreShowCount
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
targetList.removeAll { it.equals(rssId) }
|
openGecko(randomOrNull())
|
||||||
if (targetList.size > 0) {
|
|
||||||
rssId = targetList.removeFirst()
|
|
||||||
binding.geckoWeb.loadUrl(rssId)
|
|
||||||
} else {
|
|
||||||
Toast.makeText(requireContext(), "없어 끄자", Toast.LENGTH_LONG).show()
|
|
||||||
binding.geckoWeb.visibility = View.GONE
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
fun clearJob(job: Job?) {
|
fun clearJob(job: Job?) {
|
||||||
@ -616,7 +619,7 @@ internal class RssHome : Fragment() {
|
|||||||
.query(
|
.query(
|
||||||
"category != $0 AND category != $1 ",
|
"category != $0 AND category != $1 ",
|
||||||
RssDataType.PRIVATE.name,
|
RssDataType.PRIVATE.name,
|
||||||
RssDataType.REDDIT_NSFW.name
|
RssDataType.TORRENT.name
|
||||||
)
|
)
|
||||||
.query("vote != $0", true).find()
|
.query("vote != $0", true).find()
|
||||||
)
|
)
|
||||||
@ -634,12 +637,14 @@ internal class RssHome : Fragment() {
|
|||||||
flow.collect { changes: ResultsChange<RssData> ->
|
flow.collect { changes: ResultsChange<RssData> ->
|
||||||
// when (changes) {
|
// when (changes) {
|
||||||
// is InitialResults -> {
|
// is InitialResults -> {
|
||||||
|
synchronized(lasted) {
|
||||||
commandHandler.removeCallbacks(infoUpdate)
|
commandHandler.removeCallbacks(infoUpdate)
|
||||||
WorkersDb.getRealm().apply {
|
WorkersDb.getRealm().apply {
|
||||||
lasted.clear()
|
lasted.clear()
|
||||||
lasted.addAll(copyFromRealm(changes.list))
|
lasted.addAll(copyFromRealm(changes.list))
|
||||||
}
|
}
|
||||||
commandHandler.post(infoUpdate)
|
commandHandler.post(infoUpdate)
|
||||||
|
}
|
||||||
// }
|
// }
|
||||||
//
|
//
|
||||||
// is UpdatedResults -> {
|
// is UpdatedResults -> {
|
||||||
@ -714,9 +719,13 @@ internal class RssHome : Fragment() {
|
|||||||
|
|
||||||
fun queryInfos(
|
fun queryInfos(
|
||||||
keywords: List<String>,
|
keywords: List<String>,
|
||||||
|
includeVote : Boolean = false,
|
||||||
|
includeRead : Boolean = false
|
||||||
) {
|
) {
|
||||||
beforeQuery()
|
beforeQuery()
|
||||||
var rQ = getRealm().query<RssData>().sort("pubDate", Sort.DESCENDING)
|
var rQ = getRealm().query<RssData>().sort("read", Sort.ASCENDING)
|
||||||
|
if (!includeRead) { rQ = rQ.query("read == $0", 0)}
|
||||||
|
if (!includeVote) { rQ = rQ.query("vote != $0", true)}
|
||||||
// 사용 예시
|
// 사용 예시
|
||||||
val (queryStr, queryArgs) = buildMultiFieldOrQuery(
|
val (queryStr, queryArgs) = buildMultiFieldOrQuery(
|
||||||
listOf("title", "description"),
|
listOf("title", "description"),
|
||||||
|
|||||||
@ -61,7 +61,7 @@ internal class RssItemAdapter (
|
|||||||
@SuppressLint("SimpleDateFormat")
|
@SuppressLint("SimpleDateFormat")
|
||||||
val dateFormat = SimpleDateFormat("a HH:mm / yy - MM - dd")
|
val dateFormat = SimpleDateFormat("a HH:mm / yy - MM - dd")
|
||||||
val emptyDate = " - "
|
val emptyDate = " - "
|
||||||
var rssList: ArrayList<String> = ArrayList()
|
// var rssList: ArrayList<String> = ArrayList()
|
||||||
val webViewListener = object : WebViewListener() {
|
val webViewListener = object : WebViewListener() {
|
||||||
override fun onCustomMenuClick(menuCode: String?) {
|
override fun onCustomMenuClick(menuCode: String?) {
|
||||||
super.onCustomMenuClick(menuCode)
|
super.onCustomMenuClick(menuCode)
|
||||||
@ -188,6 +188,7 @@ internal class RssItemAdapter (
|
|||||||
|
|
||||||
@SuppressLint("SetTextI18n", "ClickableViewAccessibility")
|
@SuppressLint("SetTextI18n", "ClickableViewAccessibility")
|
||||||
override fun onBindViewHolder(holder: RssHolder, position: Int) {
|
override fun onBindViewHolder(holder: RssHolder, position: Int) {
|
||||||
|
if (rssDataItemLis.isNotEmpty() && rssDataItemLis.size > position) {
|
||||||
val rssData = rssDataItemLis[position]
|
val rssData = rssDataItemLis[position]
|
||||||
if (rssData.pubDate() > 1000L) {
|
if (rssData.pubDate() > 1000L) {
|
||||||
holder.view.date.text = dateFormat.format(Date(rssData.pubDate()))
|
holder.view.date.text = dateFormat.format(Date(rssData.pubDate()))
|
||||||
@ -196,16 +197,19 @@ internal class RssItemAdapter (
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
holder.view.title.text = "".plus(if(rssData.vote) " * " else "").plus(rssData.title().plus("[R:${rssData.read}]"))
|
holder.view.title.text = "".plus(if (rssData.vote) " * " else "")
|
||||||
|
.plus(rssData.title().plus("[R:${rssData.read}]"))
|
||||||
holder.view.desc.text = rssData.description()
|
holder.view.desc.text = rssData.description()
|
||||||
|
|
||||||
var param = holder.view.circlePreview.layoutParams
|
var param = holder.view.circlePreview.layoutParams
|
||||||
holder.view.circlePreview.layoutParams = ConstraintLayout.LayoutParams(rssData.category().defaultImgSize(), param.height)
|
holder.view.circlePreview.layoutParams =
|
||||||
|
ConstraintLayout.LayoutParams(rssData.category().defaultImgSize(), param.height)
|
||||||
holder.view.circlePreview.visibility = rssData.category().getDefaultVisibiliy()
|
holder.view.circlePreview.visibility = rssData.category().getDefaultVisibiliy()
|
||||||
Picasso.get().cancelRequest(holder.view.circlePreview)
|
Picasso.get().cancelRequest(holder.view.circlePreview)
|
||||||
|
|
||||||
if (rssData.thumbnailUrl()?.length ?: 0 > 6) {
|
if (rssData.thumbnailUrl()?.length ?: 0 > 6) {
|
||||||
Picasso.get().load(rssData.thumbnailUrl().replace("&","&").toUri()).into(holder.view.circlePreview)
|
Picasso.get().load(rssData.thumbnailUrl().replace("&", "&").toUri())
|
||||||
|
.into(holder.view.circlePreview)
|
||||||
} else if (rssData.category().getResId() > 0) {
|
} else if (rssData.category().getResId() > 0) {
|
||||||
holder.view.circlePreview.setImageResource(rssData.category().getResId())
|
holder.view.circlePreview.setImageResource(rssData.category().getResId())
|
||||||
} else {
|
} else {
|
||||||
@ -219,7 +223,11 @@ internal class RssItemAdapter (
|
|||||||
v: View,
|
v: View,
|
||||||
event: MotionEvent
|
event: MotionEvent
|
||||||
): Boolean {
|
): Boolean {
|
||||||
if (event.device != null && event.device.name != null && (event.device.name?.contains("JX-12",true) == true|| event.device.name?.equals("J06",true) == true)) {
|
if (event.device != null && event.device.name != null && (event.device.name?.contains(
|
||||||
|
"JX-12",
|
||||||
|
true
|
||||||
|
) == true || event.device.name?.equals("J06", true) == true)
|
||||||
|
) {
|
||||||
Blog.LOGE("event.device.name >>> ${event.device.name}")
|
Blog.LOGE("event.device.name >>> ${event.device.name}")
|
||||||
return true//mSimpleFingerGestures.onTouch(v,event)
|
return true//mSimpleFingerGestures.onTouch(v,event)
|
||||||
} else {
|
} else {
|
||||||
@ -234,6 +242,7 @@ internal class RssItemAdapter (
|
|||||||
// }
|
// }
|
||||||
holder.itemView.setOnLongClickListener(mLongClickListener)
|
holder.itemView.setOnLongClickListener(mLongClickListener)
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
var layoutManager : LinearLayoutManager? = null
|
var layoutManager : LinearLayoutManager? = null
|
||||||
var recyclerView: RecyclerView? = null
|
var recyclerView: RecyclerView? = null
|
||||||
@ -242,24 +251,29 @@ internal class RssItemAdapter (
|
|||||||
this.recyclerView = recyclerView
|
this.recyclerView = recyclerView
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@SuppressLint("NotifyDataSetChanged")
|
||||||
fun updateData(newList: List<RssData>) {
|
fun updateData(newList: List<RssData>) {
|
||||||
try {
|
try {
|
||||||
DiffUtil.calculateDiff(RssItemDiffUtil(rssDataItemLis, newList)).apply {
|
// DiffUtil.calculateDiff(RssItemDiffUtil(rssDataItemLis, newList)).apply {
|
||||||
|
//
|
||||||
}.dispatchUpdatesTo(this).apply {
|
// }.dispatchUpdatesTo(this).apply {
|
||||||
val visibleItemCount = (layoutManager?.findLastVisibleItemPosition() ?: 0) - (layoutManager?.findFirstVisibleItemPosition() ?: 0)
|
// val visibleItemCount = (layoutManager?.findLastVisibleItemPosition() ?: 0) - (layoutManager?.findFirstVisibleItemPosition() ?: 0)
|
||||||
val first = layoutManager?.findLastVisibleItemPosition() ?: 0
|
// val first = layoutManager?.findLastVisibleItemPosition() ?: 0
|
||||||
if (visibleItemCount > 0) {
|
// if (visibleItemCount > 0) {
|
||||||
this@RssItemAdapter.notifyItemRangeChanged(first, visibleItemCount)
|
// this@RssItemAdapter.notifyItemRangeChanged(first, visibleItemCount)
|
||||||
// recyclerView?.scrollToPosition(0)
|
//// recyclerView?.scrollToPosition(0)
|
||||||
}
|
// }
|
||||||
}
|
// }
|
||||||
|
synchronized(rssDataItemLis) {
|
||||||
rssDataItemLis.clear()
|
rssDataItemLis.clear()
|
||||||
rssDataItemLis.addAll(newList)
|
rssDataItemLis.addAll(newList)
|
||||||
CoroutineScope(Dispatchers.IO).launch {
|
|
||||||
rssList.clear()
|
|
||||||
rssList.addAll(newList.map { it.originPage() })
|
|
||||||
}
|
}
|
||||||
|
notifyDataSetChanged()
|
||||||
|
|
||||||
|
// CoroutineScope(Dispatchers.IO).launch {
|
||||||
|
// rssList.clear()
|
||||||
|
// rssList.addAll(newList.map { it.originPage() })
|
||||||
|
// }
|
||||||
} catch (e: Exception) {
|
} catch (e: Exception) {
|
||||||
e.printStackTrace()
|
e.printStackTrace()
|
||||||
}
|
}
|
||||||
|
|||||||
@ -7,10 +7,9 @@ import bums.lunatic.launcher.helpers.PrefHelper
|
|||||||
enum class RssDataType {
|
enum class RssDataType {
|
||||||
NO_DATA,
|
NO_DATA,
|
||||||
PRIVATE,
|
PRIVATE,
|
||||||
|
TORRENT,
|
||||||
YOUTUBE,
|
YOUTUBE,
|
||||||
NEWSFEED,
|
NEWSFEED,
|
||||||
// GURU,
|
|
||||||
// MOST,
|
|
||||||
TAGS,
|
TAGS,
|
||||||
REDDIT,
|
REDDIT,
|
||||||
REDDIT_NSFW,
|
REDDIT_NSFW,
|
||||||
|
|||||||
@ -54,9 +54,11 @@ import bums.lunatic.launcher.tokiz.view.JxEvent
|
|||||||
import bums.lunatic.launcher.tokiz.view.PagedTextLayout
|
import bums.lunatic.launcher.tokiz.view.PagedTextLayout
|
||||||
import bums.lunatic.launcher.tokiz.view.PagedTextViewInterface
|
import bums.lunatic.launcher.tokiz.view.PagedTextViewInterface
|
||||||
import bums.lunatic.launcher.databinding.BooktokiBinding
|
import bums.lunatic.launcher.databinding.BooktokiBinding
|
||||||
|
import bums.lunatic.launcher.home.toast
|
||||||
import bums.lunatic.launcher.tokiz.data.model.FakeSession
|
import bums.lunatic.launcher.tokiz.data.model.FakeSession
|
||||||
import bums.lunatic.launcher.tokiz.data.model.FakeSessions
|
import bums.lunatic.launcher.tokiz.data.model.FakeSessions
|
||||||
import bums.lunatic.launcher.utils.Blog
|
import bums.lunatic.launcher.utils.Blog
|
||||||
|
import bums.lunatic.launcher.workers.WorkersDb
|
||||||
import com.google.gson.Gson
|
import com.google.gson.Gson
|
||||||
import io.realm.kotlin.Realm
|
import io.realm.kotlin.Realm
|
||||||
import io.realm.kotlin.UpdatePolicy
|
import io.realm.kotlin.UpdatePolicy
|
||||||
@ -130,7 +132,7 @@ abstract class BaseToki : Fragment(), PagedTextViewInterface {
|
|||||||
abstract var lastNumber : Int
|
abstract var lastNumber : Int
|
||||||
abstract val webcontentsName : String
|
abstract val webcontentsName : String
|
||||||
abstract val afterDot : String
|
abstract val afterDot : String
|
||||||
fun getLastedDoamin(): String {
|
open fun getLastedDoamin(): String {
|
||||||
return String.format("https://%s%d.%s", webcontentsName , lastNumber, afterDot)
|
return String.format("https://%s%d.%s", webcontentsName , lastNumber, afterDot)
|
||||||
}
|
}
|
||||||
val OnTouchListener = object : OnTouchListener {
|
val OnTouchListener = object : OnTouchListener {
|
||||||
@ -454,6 +456,12 @@ abstract class BaseToki : Fragment(), PagedTextViewInterface {
|
|||||||
"SHOWVIEWER" -> {
|
"SHOWVIEWER" -> {
|
||||||
binding.progress.visibility = GONE
|
binding.progress.visibility = GONE
|
||||||
}
|
}
|
||||||
|
"PRIVATES"->{
|
||||||
|
lPortMessage.privates?.let {
|
||||||
|
requireContext().toast("Received Msg privates form ${lPortMessage.currentPage} data => ${it?.size ?: 0}")
|
||||||
|
WorkersDb.insertBulkData(it)
|
||||||
|
}
|
||||||
|
}
|
||||||
else -> {
|
else -> {
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
185
app/src/main/kotlin/bums/lunatic/launcher/tokiz/Twitter.kt
Normal file
185
app/src/main/kotlin/bums/lunatic/launcher/tokiz/Twitter.kt
Normal file
@ -0,0 +1,185 @@
|
|||||||
|
package bums.lunatic.launcher.tokiz
|
||||||
|
|
||||||
|
import android.content.DialogInterface
|
||||||
|
import android.content.Intent
|
||||||
|
import android.content.pm.ActivityInfo
|
||||||
|
import android.content.res.Configuration
|
||||||
|
import android.graphics.Bitmap
|
||||||
|
import android.graphics.Color
|
||||||
|
import android.net.Uri
|
||||||
|
import android.os.Bundle
|
||||||
|
import android.os.Handler
|
||||||
|
import android.os.Looper
|
||||||
|
import android.os.Message
|
||||||
|
import android.text.InputType
|
||||||
|
import android.text.SpannableStringBuilder
|
||||||
|
import android.text.style.RelativeSizeSpan
|
||||||
|
import android.util.Log
|
||||||
|
import android.view.LayoutInflater
|
||||||
|
import android.view.MotionEvent
|
||||||
|
import android.view.View
|
||||||
|
import android.view.View.GONE
|
||||||
|
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.TextView
|
||||||
|
import android.widget.Toast
|
||||||
|
import androidx.appcompat.app.AlertDialog
|
||||||
|
import androidx.constraintlayout.widget.ConstraintLayout
|
||||||
|
import androidx.core.net.toUri
|
||||||
|
import androidx.core.view.isVisible
|
||||||
|
import androidx.fragment.app.Fragment
|
||||||
|
import bums.lunatic.launcher.LauncherActivity.Companion.getRuntime
|
||||||
|
import bums.lunatic.launcher.R
|
||||||
|
import bums.lunatic.launcher.tokiz.common.PairArray
|
||||||
|
import bums.lunatic.launcher.tokiz.common.TouchArea
|
||||||
|
import bums.lunatic.launcher.tokiz.common.colorz
|
||||||
|
import bums.lunatic.launcher.tokiz.common.getIndex
|
||||||
|
import bums.lunatic.launcher.tokiz.common.typesfacez
|
||||||
|
import bums.lunatic.launcher.tokiz.data.HistoryManager
|
||||||
|
import bums.lunatic.launcher.tokiz.data.model.ContentsPageInfo
|
||||||
|
import bums.lunatic.launcher.tokiz.data.model.ContentsCollection
|
||||||
|
import bums.lunatic.launcher.tokiz.data.model.PageInfosJ
|
||||||
|
import bums.lunatic.launcher.tokiz.data.model.HistoryItem
|
||||||
|
import bums.lunatic.launcher.tokiz.data.model.LastInfo
|
||||||
|
import bums.lunatic.launcher.tokiz.data.model.PortMessage
|
||||||
|
import bums.lunatic.launcher.tokiz.data.model.ReaderConfig
|
||||||
|
import bums.lunatic.launcher.tokiz.dialog.DefaultList
|
||||||
|
import bums.lunatic.launcher.tokiz.view.JxEvent
|
||||||
|
import bums.lunatic.launcher.tokiz.view.PagedTextLayout
|
||||||
|
import bums.lunatic.launcher.tokiz.view.PagedTextViewInterface
|
||||||
|
import bums.lunatic.launcher.databinding.BooktokiBinding
|
||||||
|
import bums.lunatic.launcher.utils.Blog
|
||||||
|
import com.google.gson.Gson
|
||||||
|
import io.realm.kotlin.Realm
|
||||||
|
import io.realm.kotlin.UpdatePolicy
|
||||||
|
import io.realm.kotlin.ext.copyFromRealm
|
||||||
|
import io.realm.kotlin.ext.query
|
||||||
|
import org.json.JSONException
|
||||||
|
import org.json.JSONObject
|
||||||
|
import org.mozilla.gecko.util.ThreadUtils
|
||||||
|
import org.mozilla.geckoview.GeckoResult
|
||||||
|
import org.mozilla.geckoview.GeckoSession
|
||||||
|
import org.mozilla.geckoview.MediaSession
|
||||||
|
import org.mozilla.geckoview.WebExtension
|
||||||
|
import org.mozilla.geckoview.WebExtension.MessageDelegate
|
||||||
|
import org.mozilla.geckoview.WebExtension.PortDelegate
|
||||||
|
import org.mozilla.geckoview.WebExtensionController.AddonManagerDelegate
|
||||||
|
import org.mozilla.geckoview.WebRequestError
|
||||||
|
import java.lang.System.currentTimeMillis
|
||||||
|
import java.text.SimpleDateFormat
|
||||||
|
import java.util.Date
|
||||||
|
import kotlin.collections.ArrayList
|
||||||
|
import kotlin.collections.List
|
||||||
|
import kotlin.collections.MutableList
|
||||||
|
import kotlin.collections.arrayListOf
|
||||||
|
import kotlin.collections.first
|
||||||
|
import kotlin.collections.isNotEmpty
|
||||||
|
import kotlin.collections.last
|
||||||
|
import kotlin.collections.sortBy
|
||||||
|
import kotlin.random.Random
|
||||||
|
import kotlin.text.contains
|
||||||
|
import kotlin.text.endsWith
|
||||||
|
import kotlin.text.equals
|
||||||
|
import kotlin.text.replace
|
||||||
|
import kotlin.text.split
|
||||||
|
import kotlin.text.startsWith
|
||||||
|
import kotlin.text.toInt
|
||||||
|
import kotlin.text.toRegex
|
||||||
|
import kotlin.text.trim
|
||||||
|
|
||||||
|
|
||||||
|
class Twitter : BaseToki(), PagedTextViewInterface {
|
||||||
|
|
||||||
|
override val contentsType = "twitter"
|
||||||
|
override var lastNumber : Int = 143
|
||||||
|
override val webcontentsName : String = "twitter"
|
||||||
|
override val afterDot = "com"
|
||||||
|
override fun getLastedDoamin(): String {
|
||||||
|
return String.format("https://%s.%s", webcontentsName, afterDot)
|
||||||
|
}
|
||||||
|
override fun onCreateView(
|
||||||
|
inflater: LayoutInflater,
|
||||||
|
container: ViewGroup?,
|
||||||
|
savedInstanceState: Bundle?
|
||||||
|
): View {
|
||||||
|
super.onCreateView(inflater, container, savedInstanceState)
|
||||||
|
return binding.root
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun onStart() {
|
||||||
|
super.onStart()
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun onResume() {
|
||||||
|
super.onResume()
|
||||||
|
loadLastInfo()
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun onTouch(touchArea: TouchArea) {
|
||||||
|
Blog.LOGD(log = "onTouch ${touchArea}")
|
||||||
|
when (touchArea) {
|
||||||
|
TouchArea.Center -> {
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
TouchArea.Right -> {
|
||||||
|
actionNextEvent()
|
||||||
|
}
|
||||||
|
|
||||||
|
TouchArea.Left -> {
|
||||||
|
actionPrevEvent()
|
||||||
|
}
|
||||||
|
|
||||||
|
TouchArea.DoubleRight -> {
|
||||||
|
actionNextEvent(true)
|
||||||
|
}
|
||||||
|
|
||||||
|
TouchArea.DoubleLeft -> {
|
||||||
|
actionPrevEvent(true)
|
||||||
|
}
|
||||||
|
else -> {
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun onLongClick() {
|
||||||
|
Blog.LOGD(log = "onLongClick")
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun onSwipeLeft(count: Int) {
|
||||||
|
Blog.LOGD(log = "onSwipeLeft ${count}")
|
||||||
|
actionNextEvent(count > 1)
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun onSwipeRight(count: Int) {
|
||||||
|
Blog.LOGD(log = "onSwipeRight ${count}")
|
||||||
|
actionPrevEvent(count > 1)
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun onSwipeUp(touchCount: Int) {
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun onSwipeDown(touchCount: Int) {
|
||||||
|
if (touchCount == 2) {
|
||||||
|
if (binding.pagedLayer.isVisible) {
|
||||||
|
binding.pagedLayer.visibility = GONE
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun onTimeoverTouch() {
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
182
app/src/main/kotlin/bums/lunatic/launcher/tokiz/Zota.kt
Normal file
182
app/src/main/kotlin/bums/lunatic/launcher/tokiz/Zota.kt
Normal file
@ -0,0 +1,182 @@
|
|||||||
|
package bums.lunatic.launcher.tokiz
|
||||||
|
|
||||||
|
import android.content.DialogInterface
|
||||||
|
import android.content.Intent
|
||||||
|
import android.content.pm.ActivityInfo
|
||||||
|
import android.content.res.Configuration
|
||||||
|
import android.graphics.Bitmap
|
||||||
|
import android.graphics.Color
|
||||||
|
import android.net.Uri
|
||||||
|
import android.os.Bundle
|
||||||
|
import android.os.Handler
|
||||||
|
import android.os.Looper
|
||||||
|
import android.os.Message
|
||||||
|
import android.text.InputType
|
||||||
|
import android.text.SpannableStringBuilder
|
||||||
|
import android.text.style.RelativeSizeSpan
|
||||||
|
import android.util.Log
|
||||||
|
import android.view.LayoutInflater
|
||||||
|
import android.view.MotionEvent
|
||||||
|
import android.view.View
|
||||||
|
import android.view.View.GONE
|
||||||
|
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.TextView
|
||||||
|
import android.widget.Toast
|
||||||
|
import androidx.appcompat.app.AlertDialog
|
||||||
|
import androidx.constraintlayout.widget.ConstraintLayout
|
||||||
|
import androidx.core.net.toUri
|
||||||
|
import androidx.core.view.isVisible
|
||||||
|
import androidx.fragment.app.Fragment
|
||||||
|
import bums.lunatic.launcher.LauncherActivity.Companion.getRuntime
|
||||||
|
import bums.lunatic.launcher.R
|
||||||
|
import bums.lunatic.launcher.tokiz.common.PairArray
|
||||||
|
import bums.lunatic.launcher.tokiz.common.TouchArea
|
||||||
|
import bums.lunatic.launcher.tokiz.common.colorz
|
||||||
|
import bums.lunatic.launcher.tokiz.common.getIndex
|
||||||
|
import bums.lunatic.launcher.tokiz.common.typesfacez
|
||||||
|
import bums.lunatic.launcher.tokiz.data.HistoryManager
|
||||||
|
import bums.lunatic.launcher.tokiz.data.model.ContentsPageInfo
|
||||||
|
import bums.lunatic.launcher.tokiz.data.model.ContentsCollection
|
||||||
|
import bums.lunatic.launcher.tokiz.data.model.PageInfosJ
|
||||||
|
import bums.lunatic.launcher.tokiz.data.model.HistoryItem
|
||||||
|
import bums.lunatic.launcher.tokiz.data.model.LastInfo
|
||||||
|
import bums.lunatic.launcher.tokiz.data.model.PortMessage
|
||||||
|
import bums.lunatic.launcher.tokiz.data.model.ReaderConfig
|
||||||
|
import bums.lunatic.launcher.tokiz.dialog.DefaultList
|
||||||
|
import bums.lunatic.launcher.tokiz.view.JxEvent
|
||||||
|
import bums.lunatic.launcher.tokiz.view.PagedTextLayout
|
||||||
|
import bums.lunatic.launcher.tokiz.view.PagedTextViewInterface
|
||||||
|
import bums.lunatic.launcher.databinding.BooktokiBinding
|
||||||
|
import bums.lunatic.launcher.utils.Blog
|
||||||
|
import com.google.gson.Gson
|
||||||
|
import io.realm.kotlin.Realm
|
||||||
|
import io.realm.kotlin.UpdatePolicy
|
||||||
|
import io.realm.kotlin.ext.copyFromRealm
|
||||||
|
import io.realm.kotlin.ext.query
|
||||||
|
import org.json.JSONException
|
||||||
|
import org.json.JSONObject
|
||||||
|
import org.mozilla.gecko.util.ThreadUtils
|
||||||
|
import org.mozilla.geckoview.GeckoResult
|
||||||
|
import org.mozilla.geckoview.GeckoSession
|
||||||
|
import org.mozilla.geckoview.MediaSession
|
||||||
|
import org.mozilla.geckoview.WebExtension
|
||||||
|
import org.mozilla.geckoview.WebExtension.MessageDelegate
|
||||||
|
import org.mozilla.geckoview.WebExtension.PortDelegate
|
||||||
|
import org.mozilla.geckoview.WebExtensionController.AddonManagerDelegate
|
||||||
|
import org.mozilla.geckoview.WebRequestError
|
||||||
|
import java.lang.System.currentTimeMillis
|
||||||
|
import java.text.SimpleDateFormat
|
||||||
|
import java.util.Date
|
||||||
|
import kotlin.collections.ArrayList
|
||||||
|
import kotlin.collections.List
|
||||||
|
import kotlin.collections.MutableList
|
||||||
|
import kotlin.collections.arrayListOf
|
||||||
|
import kotlin.collections.first
|
||||||
|
import kotlin.collections.isNotEmpty
|
||||||
|
import kotlin.collections.last
|
||||||
|
import kotlin.collections.sortBy
|
||||||
|
import kotlin.random.Random
|
||||||
|
import kotlin.text.contains
|
||||||
|
import kotlin.text.endsWith
|
||||||
|
import kotlin.text.equals
|
||||||
|
import kotlin.text.replace
|
||||||
|
import kotlin.text.split
|
||||||
|
import kotlin.text.startsWith
|
||||||
|
import kotlin.text.toInt
|
||||||
|
import kotlin.text.toRegex
|
||||||
|
import kotlin.text.trim
|
||||||
|
|
||||||
|
|
||||||
|
class Zota : BaseToki(), PagedTextViewInterface {
|
||||||
|
|
||||||
|
override val contentsType = "Torrent"
|
||||||
|
override var lastNumber : Int = 143
|
||||||
|
override val webcontentsName : String = "torrentzota"
|
||||||
|
override val afterDot = "com"
|
||||||
|
override fun onCreateView(
|
||||||
|
inflater: LayoutInflater,
|
||||||
|
container: ViewGroup?,
|
||||||
|
savedInstanceState: Bundle?
|
||||||
|
): View {
|
||||||
|
super.onCreateView(inflater, container, savedInstanceState)
|
||||||
|
return binding.root
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun onStart() {
|
||||||
|
super.onStart()
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun onResume() {
|
||||||
|
super.onResume()
|
||||||
|
loadLastInfo()
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun onTouch(touchArea: TouchArea) {
|
||||||
|
Blog.LOGD(log = "onTouch ${touchArea}")
|
||||||
|
when (touchArea) {
|
||||||
|
TouchArea.Center -> {
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
TouchArea.Right -> {
|
||||||
|
actionNextEvent()
|
||||||
|
}
|
||||||
|
|
||||||
|
TouchArea.Left -> {
|
||||||
|
actionPrevEvent()
|
||||||
|
}
|
||||||
|
|
||||||
|
TouchArea.DoubleRight -> {
|
||||||
|
actionNextEvent(true)
|
||||||
|
}
|
||||||
|
|
||||||
|
TouchArea.DoubleLeft -> {
|
||||||
|
actionPrevEvent(true)
|
||||||
|
}
|
||||||
|
else -> {
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun onLongClick() {
|
||||||
|
Blog.LOGD(log = "onLongClick")
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun onSwipeLeft(count: Int) {
|
||||||
|
Blog.LOGD(log = "onSwipeLeft ${count}")
|
||||||
|
actionNextEvent(count > 1)
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun onSwipeRight(count: Int) {
|
||||||
|
Blog.LOGD(log = "onSwipeRight ${count}")
|
||||||
|
actionPrevEvent(count > 1)
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun onSwipeUp(touchCount: Int) {
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun onSwipeDown(touchCount: Int) {
|
||||||
|
if (touchCount == 2) {
|
||||||
|
if (binding.pagedLayer.isVisible) {
|
||||||
|
binding.pagedLayer.visibility = GONE
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun onTimeoverTouch() {
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -6,6 +6,8 @@ import android.graphics.Color
|
|||||||
import android.graphics.Paint
|
import android.graphics.Paint
|
||||||
import android.graphics.RectF
|
import android.graphics.RectF
|
||||||
import android.media.MediaCodec
|
import android.media.MediaCodec
|
||||||
|
import android.media.MediaCodecInfo.CodecCapabilities.COLOR_FormatYUV420Planar
|
||||||
|
import android.media.MediaCodecInfo.CodecCapabilities.COLOR_FormatYUV420SemiPlanar
|
||||||
import android.media.MediaExtractor
|
import android.media.MediaExtractor
|
||||||
import android.media.MediaFormat
|
import android.media.MediaFormat
|
||||||
import android.renderscript.Allocation
|
import android.renderscript.Allocation
|
||||||
@ -18,6 +20,8 @@ import android.util.DisplayMetrics
|
|||||||
import android.view.SurfaceHolder
|
import android.view.SurfaceHolder
|
||||||
import android.view.WindowManager
|
import android.view.WindowManager
|
||||||
import bums.lunatic.launcher.R
|
import bums.lunatic.launcher.R
|
||||||
|
import bums.lunatic.launcher.utils.Blog
|
||||||
|
import java.nio.ByteBuffer
|
||||||
|
|
||||||
|
|
||||||
class MyWallpaperService : WallpaperService() {
|
class MyWallpaperService : WallpaperService() {
|
||||||
@ -51,6 +55,8 @@ class MyWallpaperService : WallpaperService() {
|
|||||||
screenWidth = metrics.widthPixels
|
screenWidth = metrics.widthPixels
|
||||||
screenHeight = metrics.heightPixels
|
screenHeight = metrics.heightPixels
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun onSurfaceCreated(holder: SurfaceHolder) {
|
override fun onSurfaceCreated(holder: SurfaceHolder) {
|
||||||
@ -98,6 +104,7 @@ class RenderThread(
|
|||||||
private var renderStartY = 0f
|
private var renderStartY = 0f
|
||||||
private var maxOffset = 0f
|
private var maxOffset = 0f
|
||||||
private var moveXAxis = false
|
private var moveXAxis = false
|
||||||
|
private var keyFrameRate = 60
|
||||||
|
|
||||||
override fun run() {
|
override fun run() {
|
||||||
try {
|
try {
|
||||||
@ -110,9 +117,16 @@ class RenderThread(
|
|||||||
for (i in 0 until trackCount) {
|
for (i in 0 until trackCount) {
|
||||||
val format = getTrackFormat(i)
|
val format = getTrackFormat(i)
|
||||||
val mime = format.getString(MediaFormat.KEY_MIME) ?: ""
|
val mime = format.getString(MediaFormat.KEY_MIME) ?: ""
|
||||||
|
|
||||||
|
if (format.containsKey(MediaFormat.KEY_FRAME_RATE)) {
|
||||||
|
keyFrameRate = format.getInteger(MediaFormat.KEY_FRAME_RATE)
|
||||||
|
} else {
|
||||||
|
keyFrameRate = 60
|
||||||
|
}
|
||||||
if (mime.startsWith("video/")) {
|
if (mime.startsWith("video/")) {
|
||||||
videoTrackIndex = i
|
videoTrackIndex = i
|
||||||
selectTrack(i)
|
selectTrack(i)
|
||||||
|
|
||||||
videoWidth = format.getInteger(MediaFormat.KEY_WIDTH)
|
videoWidth = format.getInteger(MediaFormat.KEY_WIDTH)
|
||||||
videoHeight = format.getInteger(MediaFormat.KEY_HEIGHT)
|
videoHeight = format.getInteger(MediaFormat.KEY_HEIGHT)
|
||||||
break
|
break
|
||||||
@ -144,8 +158,8 @@ class RenderThread(
|
|||||||
}
|
}
|
||||||
renderWidth = videoWidth * scale
|
renderWidth = videoWidth * scale
|
||||||
renderHeight = videoHeight * scale
|
renderHeight = videoHeight * scale
|
||||||
renderStartX = (screenWidth - renderWidth) / 2f
|
renderStartX = 0f;//(screenWidth - renderWidth) / 2f
|
||||||
renderStartY = (screenHeight - renderHeight) / 2f
|
renderStartY = 0f;//(screenHeight - renderHeight) / 2f
|
||||||
|
|
||||||
moveXAxis = renderWidth > screenWidth
|
moveXAxis = renderWidth > screenWidth
|
||||||
maxOffset = if (moveXAxis) renderWidth - screenWidth else if (renderHeight > screenHeight) renderHeight - screenHeight else 0f
|
maxOffset = if (moveXAxis) renderWidth - screenWidth else if (renderHeight > screenHeight) renderHeight - screenHeight else 0f
|
||||||
@ -161,9 +175,12 @@ class RenderThread(
|
|||||||
if (inputBuffer != null) {
|
if (inputBuffer != null) {
|
||||||
val sampleSize = extractor?.readSampleData(inputBuffer, 0) ?: -1
|
val sampleSize = extractor?.readSampleData(inputBuffer, 0) ?: -1
|
||||||
if (sampleSize < 0) {
|
if (sampleSize < 0) {
|
||||||
codec?.queueInputBuffer(
|
// codec?.queueInputBuffer(
|
||||||
inputBufferIndex, 0, 0, 0, MediaCodec.BUFFER_FLAG_END_OF_STREAM)
|
// inputBufferIndex, 0, 0, 0, MediaCodec.BUFFER_FLAG_END_OF_STREAM)
|
||||||
isEOS = true
|
// isEOS = true
|
||||||
|
extractor?.seekTo(0, MediaExtractor.SEEK_TO_CLOSEST_SYNC)
|
||||||
|
isEOS = false // false로 재설정해서 계속 받게
|
||||||
|
continue
|
||||||
} else {
|
} else {
|
||||||
val pts = extractor?.sampleTime ?: 0L
|
val pts = extractor?.sampleTime ?: 0L
|
||||||
codec?.queueInputBuffer(inputBufferIndex, 0, sampleSize, pts, 0)
|
codec?.queueInputBuffer(inputBufferIndex, 0, sampleSize, pts, 0)
|
||||||
@ -176,13 +193,35 @@ class RenderThread(
|
|||||||
val outputBufferIndex = codec?.dequeueOutputBuffer(bufferInfo, 10000) ?: -1
|
val outputBufferIndex = codec?.dequeueOutputBuffer(bufferInfo, 10000) ?: -1
|
||||||
if (outputBufferIndex >= 0) {
|
if (outputBufferIndex >= 0) {
|
||||||
val outputBuffer = codec?.getOutputBuffer(outputBufferIndex)
|
val outputBuffer = codec?.getOutputBuffer(outputBufferIndex)
|
||||||
|
Blog.LOGE("codec.outputFormat >>> ${codec?.outputFormat}")
|
||||||
if (bufferInfo.size > 0 && outputBuffer != null) {
|
if (bufferInfo.size > 0 && outputBuffer != null) {
|
||||||
val yuvData = ByteArray(bufferInfo.size)
|
val format = codec?.outputFormat
|
||||||
outputBuffer.get(yuvData)
|
|
||||||
|
|
||||||
val bitmap = convertYUVToBitmap(yuvData, videoWidth, videoHeight)
|
val colorFormat = format?.getInteger(MediaFormat.KEY_COLOR_FORMAT) ?: /*기본값*/0
|
||||||
|
val stride = format?.getInteger(MediaFormat.KEY_STRIDE) ?: videoWidth
|
||||||
|
val sliceHeight = format?.getInteger(MediaFormat.KEY_SLICE_HEIGHT) ?: videoHeight
|
||||||
|
// outputBuffer.get(yuvData)
|
||||||
|
val expectedSize = videoWidth * videoHeight * 3 / 2
|
||||||
|
val yuvData = ByteArray(expectedSize)
|
||||||
|
val rawYUV = ByteArray(bufferInfo.size)
|
||||||
|
outputBuffer.get(rawYUV)
|
||||||
|
outputBuffer.position(0)
|
||||||
|
|
||||||
|
// 포맷별 변환
|
||||||
|
val nv21Data = when (colorFormat) {
|
||||||
|
COLOR_FormatYUV420SemiPlanar -> nv12ToNv21(rawYUV, videoWidth, videoHeight)
|
||||||
|
COLOR_FormatYUV420Planar -> i420ToNv21(rawYUV, videoWidth, videoHeight)
|
||||||
|
else -> rawYUV // 이미 NV21 등
|
||||||
|
}
|
||||||
|
|
||||||
|
// NV21 데이터 → Bitmap
|
||||||
|
val bitmap = convertYUVToBitmap(nv21Data, videoWidth, videoHeight)
|
||||||
|
// outputBuffer.get(yuvData, 0, minOf(bufferInfo.size, expectedSize))
|
||||||
|
// getYUVDataWithStride(outputBuffer, videoWidth, videoHeight, stride, height)
|
||||||
|
// val bitmap = convertYUVToBitmap(yuvData, videoWidth, videoHeight)
|
||||||
|
|
||||||
// 6. 왕복 이동 애니메이션 offset 계산
|
// 6. 왕복 이동 애니메이션 offset 계산
|
||||||
|
// Blog.LOGE("maxOffset >>> $maxOffset , offset >>> $offset , direction >> $direction , keyFrameRate >>> $keyFrameRate")
|
||||||
if (maxOffset > 0f) {
|
if (maxOffset > 0f) {
|
||||||
offset += direction * speed
|
offset += direction * speed
|
||||||
if (offset < 0f) { offset = 0f; direction = 1 }
|
if (offset < 0f) { offset = 0f; direction = 1 }
|
||||||
@ -215,7 +254,7 @@ class RenderThread(
|
|||||||
} else if (outputBufferIndex == MediaCodec.INFO_OUTPUT_FORMAT_CHANGED) {
|
} else if (outputBufferIndex == MediaCodec.INFO_OUTPUT_FORMAT_CHANGED) {
|
||||||
// 필요하다면 포맷 변경 처리
|
// 필요하다면 포맷 변경 처리
|
||||||
}
|
}
|
||||||
sleep(1000L/45L) // 약 30fps
|
sleep(1000L / keyFrameRate) // 약 30fps
|
||||||
}
|
}
|
||||||
} catch (e: Exception) {
|
} catch (e: Exception) {
|
||||||
e.printStackTrace()
|
e.printStackTrace()
|
||||||
@ -229,13 +268,17 @@ class RenderThread(
|
|||||||
}
|
}
|
||||||
|
|
||||||
private fun convertYUVToBitmap(yuvByteArray: ByteArray, width: Int, height: Int): Bitmap {
|
private fun convertYUVToBitmap(yuvByteArray: ByteArray, width: Int, height: Int): Bitmap {
|
||||||
val yuvType = Type.Builder(rs, Element.U8(rs)).setX(yuvByteArray.size)
|
// YUV420の場合, 바이트 수는 width * height * 3 / 2 여야 함
|
||||||
|
val minSize = width * height * 3 / 2
|
||||||
|
val realData = if (yuvByteArray.size >= minSize) yuvByteArray.copyOf(minSize) else yuvByteArray
|
||||||
|
|
||||||
|
val yuvType = Type.Builder(rs, Element.U8(rs)).setX(minSize)
|
||||||
val inAllocation = Allocation.createTyped(rs, yuvType.create(), Allocation.USAGE_SCRIPT)
|
val inAllocation = Allocation.createTyped(rs, yuvType.create(), Allocation.USAGE_SCRIPT)
|
||||||
|
|
||||||
val rgbaType = Type.Builder(rs, Element.RGBA_8888(rs)).setX(width).setY(height)
|
val rgbaType = Type.Builder(rs, Element.RGBA_8888(rs)).setX(width).setY(height)
|
||||||
val outAllocation = Allocation.createTyped(rs, rgbaType.create(), Allocation.USAGE_SCRIPT)
|
val outAllocation = Allocation.createTyped(rs, rgbaType.create(), Allocation.USAGE_SCRIPT)
|
||||||
|
|
||||||
inAllocation.copyFrom(yuvByteArray)
|
inAllocation.copyFrom(realData)
|
||||||
yuvToRgb?.setInput(inAllocation)
|
yuvToRgb?.setInput(inAllocation)
|
||||||
yuvToRgb?.forEach(outAllocation)
|
yuvToRgb?.forEach(outAllocation)
|
||||||
|
|
||||||
@ -247,4 +290,91 @@ class RenderThread(
|
|||||||
|
|
||||||
return bitmap
|
return bitmap
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private fun getYUVDataWithStride(
|
||||||
|
buffer: ByteBuffer,
|
||||||
|
width: Int,
|
||||||
|
height: Int,
|
||||||
|
stride: Int,
|
||||||
|
sliceHeight: Int
|
||||||
|
): ByteArray {
|
||||||
|
val yuvData = ByteArray(width * height * 3 / 2)
|
||||||
|
// Y plane 복사
|
||||||
|
for (y in 0 until height) {
|
||||||
|
buffer.position(y * stride)
|
||||||
|
buffer.get(yuvData, y * width, width)
|
||||||
|
}
|
||||||
|
// UV plane... (NV21 등 포맷 따라 별도 구현 필요)
|
||||||
|
// 이 영역은 포맷에 따라 다름, 기본은 Y만 참고!
|
||||||
|
return yuvData
|
||||||
|
}
|
||||||
|
|
||||||
|
// NV12 to NV21 변환
|
||||||
|
fun nv12ToNv21(nv12: ByteArray, width: Int, height: Int): ByteArray {
|
||||||
|
val frameSize = width * height
|
||||||
|
val nv21 = ByteArray(frameSize * 3 / 2)
|
||||||
|
|
||||||
|
// Y는 그대로 복사
|
||||||
|
System.arraycopy(nv12, 0, nv21, 0, frameSize)
|
||||||
|
|
||||||
|
// UV를 VU로 뒤집어서 복사
|
||||||
|
var i = 0
|
||||||
|
while (i < frameSize / 2 - 1) {
|
||||||
|
nv21[frameSize + i] = nv12[frameSize + i + 1]
|
||||||
|
nv21[frameSize + i + 1] = nv12[frameSize + i]
|
||||||
|
i += 2
|
||||||
|
}
|
||||||
|
return nv21
|
||||||
|
}
|
||||||
|
|
||||||
|
// I420(YUV420Planar) to NV21 변환
|
||||||
|
fun i420ToNv21(i420: ByteArray, width: Int, height: Int): ByteArray {
|
||||||
|
val frameSize = width * height
|
||||||
|
val qFrameSize = frameSize / 4
|
||||||
|
val nv21 = ByteArray(frameSize * 3 / 2)
|
||||||
|
|
||||||
|
// Y 복사
|
||||||
|
System.arraycopy(i420, 0, nv21, 0, frameSize)
|
||||||
|
|
||||||
|
// VU interleave
|
||||||
|
val u = frameSize
|
||||||
|
val v = frameSize + qFrameSize
|
||||||
|
|
||||||
|
for (i in 0 until qFrameSize) {
|
||||||
|
nv21[frameSize + i * 2] = i420[v + i] // V
|
||||||
|
nv21[frameSize + i * 2 + 1] = i420[u + i] // U
|
||||||
|
}
|
||||||
|
return nv21
|
||||||
|
}
|
||||||
|
fun i420ToNv21WithStride(src: ByteBuffer, width: Int, height: Int, stride: Int, sliceHeight: Int): ByteArray {
|
||||||
|
val frameSize = width * height
|
||||||
|
val qFrameSize = frameSize / 4
|
||||||
|
val nv21 = ByteArray(frameSize * 3 / 2)
|
||||||
|
|
||||||
|
// 1. Y plane 복사
|
||||||
|
for (y in 0 until height) {
|
||||||
|
src.position(y * stride)
|
||||||
|
src.get(nv21, y * width, width)
|
||||||
|
}
|
||||||
|
|
||||||
|
// 2. U/V plane 복사, 각각 stride/2씩 적용
|
||||||
|
val uOffsetBuf = sliceHeight * stride
|
||||||
|
val vOffsetBuf = uOffsetBuf + (sliceHeight / 2) * (stride / 2)
|
||||||
|
|
||||||
|
for (y in 0 until height/2) {
|
||||||
|
src.position(uOffsetBuf + y * (stride / 2))
|
||||||
|
src.get(nv21, frameSize + y * width, width/2) // 임시: U만
|
||||||
|
|
||||||
|
src.position(vOffsetBuf + y * (stride / 2))
|
||||||
|
for (x in 0 until width/2) {
|
||||||
|
// NV21 순서: V, U
|
||||||
|
val v = src.get()
|
||||||
|
val u = nv21[frameSize + y * width + x] // U
|
||||||
|
nv21[frameSize + y * width + x*2] = v
|
||||||
|
nv21[frameSize + y * width + x*2 + 1] = u
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return nv21
|
||||||
|
}
|
||||||
}
|
}
|
||||||
@ -77,12 +77,12 @@ class DCGetter : BaseGetter {
|
|||||||
Blog.LOGE("realWork() ${this::class.simpleName}")
|
Blog.LOGE("realWork() ${this::class.simpleName}")
|
||||||
temp.clear()
|
temp.clear()
|
||||||
// https://m.dcinside.com/board/singlebungle1472
|
// https://m.dcinside.com/board/singlebungle1472
|
||||||
|
//"https://m.dcinside.com/board/programming",
|
||||||
|
//"https://m.dcinside.com/board/reading",
|
||||||
var urls = arrayListOf(
|
var urls = arrayListOf(
|
||||||
"https://m.dcinside.com",
|
"https://m.dcinside.com",
|
||||||
"https://m.dcinside.com/board/singlebungle1472",
|
"https://m.dcinside.com/board/singlebungle1472",
|
||||||
"https://m.dcinside.com/board/programming",
|
|
||||||
"https://m.dcinside.com/board/cartoon",
|
"https://m.dcinside.com/board/cartoon",
|
||||||
"https://m.dcinside.com/board/reading",
|
|
||||||
"https://m.dcinside.com/board/hit",
|
"https://m.dcinside.com/board/hit",
|
||||||
"https://m.dcinside.com/board/dcbest"
|
"https://m.dcinside.com/board/dcbest"
|
||||||
)
|
)
|
||||||
|
|||||||
BIN
app/src/main/res/drawable/ic_b.png
Normal file
BIN
app/src/main/res/drawable/ic_b.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 565 B |
@ -59,6 +59,17 @@
|
|||||||
android:id="@+id/comics"
|
android:id="@+id/comics"
|
||||||
style="@style/tabItem"
|
style="@style/tabItem"
|
||||||
android:layout_height="match_parent"/>
|
android:layout_height="match_parent"/>
|
||||||
|
<androidx.appcompat.widget.AppCompatRadioButton
|
||||||
|
android:text="zota"
|
||||||
|
android:id="@+id/zota"
|
||||||
|
style="@style/tabItem"
|
||||||
|
android:layout_height="match_parent"/>
|
||||||
|
<androidx.appcompat.widget.AppCompatRadioButton
|
||||||
|
android:text="twitter"
|
||||||
|
android:visibility="gone"
|
||||||
|
android:id="@+id/twitter"
|
||||||
|
style="@style/tabItem"
|
||||||
|
android:layout_height="match_parent"/>
|
||||||
<Button
|
<Button
|
||||||
android:text="hidden"
|
android:text="hidden"
|
||||||
android:id="@+id/hidden"
|
android:id="@+id/hidden"
|
||||||
|
|||||||
@ -1,5 +1,6 @@
|
|||||||
<?xml version="1.0" encoding="utf-8"?>
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
<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_width="match_parent"
|
||||||
android:layout_height="match_parent"
|
android:layout_height="match_parent"
|
||||||
xmlns:app="http://schemas.android.com/apk/res-auto">
|
xmlns:app="http://schemas.android.com/apk/res-auto">
|
||||||
@ -14,8 +15,33 @@
|
|||||||
app:endIconMode="clear_text"
|
app:endIconMode="clear_text"
|
||||||
android:gravity="right"
|
android:gravity="right"
|
||||||
app:layout_constraintEnd_toEndOf="parent"
|
app:layout_constraintEnd_toEndOf="parent"
|
||||||
app:layout_constraintStart_toStartOf="parent">
|
app:layout_constraintStart_toStartOf="parent"
|
||||||
|
tools:ignore="MissingConstraints">
|
||||||
|
<LinearLayout
|
||||||
|
android:orientation="horizontal"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="match_parent">
|
||||||
|
<CheckBox
|
||||||
|
android:padding="0dp"
|
||||||
|
android:text="add Vote"
|
||||||
|
android:textColor="@color/black"
|
||||||
|
app:layout_constraintLeft_toLeftOf="parent"
|
||||||
|
app:layout_constraintRight_toRightOf="parent"
|
||||||
|
android:id="@+id/add_vote"
|
||||||
|
android:checked="false"
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="wrap_content"/>
|
||||||
|
<CheckBox
|
||||||
|
android:padding="0dp"
|
||||||
|
android:text="Add Read"
|
||||||
|
android:textColor="@color/black"
|
||||||
|
app:layout_constraintLeft_toLeftOf="parent"
|
||||||
|
app:layout_constraintRight_toRightOf="parent"
|
||||||
|
android:id="@+id/add_read"
|
||||||
|
android:checked="false"
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="wrap_content"/>
|
||||||
|
</LinearLayout>
|
||||||
<com.google.android.material.textfield.TextInputEditText
|
<com.google.android.material.textfield.TextInputEditText
|
||||||
android:id="@+id/input"
|
android:id="@+id/input"
|
||||||
android:layout_width="match_parent"
|
android:layout_width="match_parent"
|
||||||
@ -24,8 +50,8 @@
|
|||||||
android:inputType="text" />
|
android:inputType="text" />
|
||||||
<CheckBox
|
<CheckBox
|
||||||
android:padding="0dp"
|
android:padding="0dp"
|
||||||
android:text="PRIVATE MODE"
|
android:text="PRIVATE"
|
||||||
android:textColor="@color/white"
|
android:textColor="@color/black"
|
||||||
app:layout_constraintLeft_toLeftOf="parent"
|
app:layout_constraintLeft_toLeftOf="parent"
|
||||||
app:layout_constraintRight_toRightOf="parent"
|
app:layout_constraintRight_toRightOf="parent"
|
||||||
android:id="@+id/parivate_mode"
|
android:id="@+id/parivate_mode"
|
||||||
|
|||||||
BIN
app/src/main/res/raw/sm2.mp4
Normal file
BIN
app/src/main/res/raw/sm2.mp4
Normal file
Binary file not shown.
Loading…
x
Reference in New Issue
Block a user