mirror of
https://github.com/tachiyomiorg/tachiyomi-extensions-inspector.git
synced 2024-12-25 16:21:50 +01:00
finished Update support: webUI side
This commit is contained in:
parent
077bbc3c38
commit
bc3ad75328
@ -168,17 +168,20 @@ private fun downloadAPKFile(url: String, apkPath: String) {
|
|||||||
sink.close()
|
sink.close()
|
||||||
}
|
}
|
||||||
|
|
||||||
fun removeExtension(pkgName: String) {
|
fun uninstallExtension(pkgName: String) {
|
||||||
logger.debug("Uninstalling $pkgName")
|
logger.debug("Uninstalling $pkgName")
|
||||||
|
|
||||||
val extensionRecord = extensionTableAsDataClass().first { it.pkgName == pkgName }
|
val extensionRecord = transaction { ExtensionTable.select { ExtensionTable.pkgName eq pkgName }.firstOrNull()!! }
|
||||||
val fileNameWithoutType = extensionRecord.apkName.substringBefore(".apk")
|
val fileNameWithoutType = extensionRecord[ExtensionTable.apkName].substringBefore(".apk")
|
||||||
val jarPath = "${applicationDirs.extensionsRoot}/$fileNameWithoutType.jar"
|
val jarPath = "${applicationDirs.extensionsRoot}/$fileNameWithoutType.jar"
|
||||||
transaction {
|
transaction {
|
||||||
val extensionId = ExtensionTable.select { ExtensionTable.name eq extensionRecord.name }.first()[ExtensionTable.id]
|
val extensionId = extensionRecord[ExtensionTable.id].value
|
||||||
|
|
||||||
SourceTable.deleteWhere { SourceTable.extension eq extensionId }
|
SourceTable.deleteWhere { SourceTable.extension eq extensionId }
|
||||||
ExtensionTable.update({ ExtensionTable.name eq extensionRecord.name }) {
|
if (extensionRecord[ExtensionTable.isObsolete])
|
||||||
|
ExtensionTable.deleteWhere { ExtensionTable.pkgName eq pkgName }
|
||||||
|
else
|
||||||
|
ExtensionTable.update({ ExtensionTable.pkgName eq pkgName }) {
|
||||||
it[isInstalled] = false
|
it[isInstalled] = false
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -190,7 +193,7 @@ fun removeExtension(pkgName: String) {
|
|||||||
|
|
||||||
fun updateExtension(pkgName: String): Int {
|
fun updateExtension(pkgName: String): Int {
|
||||||
val targetExtension = ExtensionListData.updateMap.remove(pkgName)!!
|
val targetExtension = ExtensionListData.updateMap.remove(pkgName)!!
|
||||||
removeExtension(pkgName)
|
uninstallExtension(pkgName)
|
||||||
transaction {
|
transaction {
|
||||||
ExtensionTable.update({ ExtensionTable.pkgName eq pkgName }) {
|
ExtensionTable.update({ ExtensionTable.pkgName eq pkgName }) {
|
||||||
it[name] = targetExtension.name
|
it[name] = targetExtension.name
|
||||||
|
@ -28,9 +28,11 @@ object ExtensionListData {
|
|||||||
var updateMap = ConcurrentHashMap<String, Extension.Available>()
|
var updateMap = ConcurrentHashMap<String, Extension.Available>()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const val ExtensionUpdateDelayTime = 0 // 60 seconds
|
||||||
|
|
||||||
fun getExtensionList(): List<ExtensionDataClass> {
|
fun getExtensionList(): List<ExtensionDataClass> {
|
||||||
// update if 60 seconds has passed or requested offline and database is empty
|
// update if {ExtensionUpdateDelayTime} seconds has passed or requested offline and database is empty
|
||||||
if (ExtensionListData.lastUpdateCheck + 60 * 1000 < System.currentTimeMillis()) {
|
if (ExtensionListData.lastUpdateCheck + ExtensionUpdateDelayTime < System.currentTimeMillis()) {
|
||||||
logger.debug("Getting extensions list from the internet")
|
logger.debug("Getting extensions list from the internet")
|
||||||
ExtensionListData.lastUpdateCheck = System.currentTimeMillis()
|
ExtensionListData.lastUpdateCheck = System.currentTimeMillis()
|
||||||
runBlocking {
|
runBlocking {
|
||||||
|
@ -16,7 +16,7 @@ data class ExtensionDataClass(
|
|||||||
val isNsfw: Boolean,
|
val isNsfw: Boolean,
|
||||||
val apkName: String,
|
val apkName: String,
|
||||||
val iconUrl: String,
|
val iconUrl: String,
|
||||||
val isInstalled: Boolean,
|
val installed: Boolean,
|
||||||
val hasUpdate: Boolean,
|
val hasUpdate: Boolean,
|
||||||
val isObsolete: Boolean,
|
val obsolete: Boolean,
|
||||||
)
|
)
|
||||||
|
@ -21,13 +21,13 @@ import ir.armor.tachidesk.impl.getSourceList
|
|||||||
import ir.armor.tachidesk.impl.getThumbnail
|
import ir.armor.tachidesk.impl.getThumbnail
|
||||||
import ir.armor.tachidesk.impl.installExtension
|
import ir.armor.tachidesk.impl.installExtension
|
||||||
import ir.armor.tachidesk.impl.removeCategory
|
import ir.armor.tachidesk.impl.removeCategory
|
||||||
import ir.armor.tachidesk.impl.removeExtension
|
|
||||||
import ir.armor.tachidesk.impl.removeMangaFromCategory
|
import ir.armor.tachidesk.impl.removeMangaFromCategory
|
||||||
import ir.armor.tachidesk.impl.removeMangaFromLibrary
|
import ir.armor.tachidesk.impl.removeMangaFromLibrary
|
||||||
import ir.armor.tachidesk.impl.reorderCategory
|
import ir.armor.tachidesk.impl.reorderCategory
|
||||||
import ir.armor.tachidesk.impl.sourceFilters
|
import ir.armor.tachidesk.impl.sourceFilters
|
||||||
import ir.armor.tachidesk.impl.sourceGlobalSearch
|
import ir.armor.tachidesk.impl.sourceGlobalSearch
|
||||||
import ir.armor.tachidesk.impl.sourceSearch
|
import ir.armor.tachidesk.impl.sourceSearch
|
||||||
|
import ir.armor.tachidesk.impl.uninstallExtension
|
||||||
import ir.armor.tachidesk.impl.updateCategory
|
import ir.armor.tachidesk.impl.updateCategory
|
||||||
import ir.armor.tachidesk.impl.updateExtension
|
import ir.armor.tachidesk.impl.updateExtension
|
||||||
import ir.armor.tachidesk.server.util.openInBrowser
|
import ir.armor.tachidesk.server.util.openInBrowser
|
||||||
@ -89,7 +89,7 @@ fun javalinSetup() {
|
|||||||
app.get("/api/v1/extension/uninstall/:pkgName") { ctx ->
|
app.get("/api/v1/extension/uninstall/:pkgName") { ctx ->
|
||||||
val pkgName = ctx.pathParam("pkgName")
|
val pkgName = ctx.pathParam("pkgName")
|
||||||
|
|
||||||
removeExtension(pkgName)
|
uninstallExtension(pkgName)
|
||||||
ctx.status(200)
|
ctx.status(200)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -49,11 +49,17 @@ interface IProps {
|
|||||||
export default function ExtensionCard(props: IProps) {
|
export default function ExtensionCard(props: IProps) {
|
||||||
const {
|
const {
|
||||||
extension: {
|
extension: {
|
||||||
name, lang, versionName, installed, pkgName, iconUrl,
|
name, lang, versionName, installed, hasUpdate, obsolete, pkgName, iconUrl,
|
||||||
},
|
},
|
||||||
notifyInstall,
|
notifyInstall,
|
||||||
} = props;
|
} = props;
|
||||||
const [installedState, setInstalledState] = useState<string>((installed ? 'uninstall' : 'install'));
|
const [installedState, setInstalledState] = useState<string>(
|
||||||
|
() => {
|
||||||
|
if (obsolete) { return 'obsolete'; }
|
||||||
|
if (hasUpdate) { return 'update'; }
|
||||||
|
return (installed ? 'uninstall' : 'install');
|
||||||
|
},
|
||||||
|
);
|
||||||
|
|
||||||
const [serverAddress] = useLocalStorage<String>('serverBaseURL', '');
|
const [serverAddress] = useLocalStorage<String>('serverBaseURL', '');
|
||||||
|
|
||||||
@ -69,6 +75,15 @@ export default function ExtensionCard(props: IProps) {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function update() {
|
||||||
|
setInstalledState('updating');
|
||||||
|
client.get(`/api/v1/extension/update/${pkgName}`)
|
||||||
|
.then(() => {
|
||||||
|
setInstalledState('uninstall');
|
||||||
|
notifyInstall();
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
function uninstall() {
|
function uninstall() {
|
||||||
setInstalledState('uninstalling');
|
setInstalledState('uninstalling');
|
||||||
client.get(`/api/v1/extension/uninstall/${pkgName}`)
|
client.get(`/api/v1/extension/uninstall/${pkgName}`)
|
||||||
@ -79,10 +94,22 @@ export default function ExtensionCard(props: IProps) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
function handleButtonClick() {
|
function handleButtonClick() {
|
||||||
if (installedState === 'install') {
|
switch (installedState) {
|
||||||
|
case 'install':
|
||||||
install();
|
install();
|
||||||
} else {
|
break;
|
||||||
|
case 'update':
|
||||||
|
update();
|
||||||
|
break;
|
||||||
|
case 'obsolete':
|
||||||
uninstall();
|
uninstall();
|
||||||
|
setTimeout(() => window.location.reload(), 3000);
|
||||||
|
break;
|
||||||
|
case 'uninstall':
|
||||||
|
uninstall();
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -108,7 +135,14 @@ export default function ExtensionCard(props: IProps) {
|
|||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<Button variant="outlined" onClick={() => handleButtonClick()}>{installedState}</Button>
|
<Button
|
||||||
|
variant="outlined"
|
||||||
|
style={{ color: installedState === 'obsolete' ? 'red' : 'inherit' }}
|
||||||
|
onClick={() => handleButtonClick()}
|
||||||
|
>
|
||||||
|
{installedState}
|
||||||
|
|
||||||
|
</Button>
|
||||||
</CardContent>
|
</CardContent>
|
||||||
</Card>
|
</Card>
|
||||||
);
|
);
|
||||||
|
@ -17,7 +17,7 @@ const allLangs: string[] = [];
|
|||||||
|
|
||||||
function groupExtensions(extensions: IExtension[]) {
|
function groupExtensions(extensions: IExtension[]) {
|
||||||
allLangs.length = 0; // empty the array
|
allLangs.length = 0; // empty the array
|
||||||
const result = { installed: [] } as any;
|
const result = { installed: [], 'updates pending': [] } as any;
|
||||||
extensions.sort((a, b) => ((a.apkName > b.apkName) ? 1 : -1));
|
extensions.sort((a, b) => ((a.apkName > b.apkName) ? 1 : -1));
|
||||||
|
|
||||||
extensions.forEach((extension) => {
|
extensions.forEach((extension) => {
|
||||||
@ -26,7 +26,11 @@ function groupExtensions(extensions: IExtension[]) {
|
|||||||
if (extension.lang !== 'all') { allLangs.push(extension.lang); }
|
if (extension.lang !== 'all') { allLangs.push(extension.lang); }
|
||||||
}
|
}
|
||||||
if (extension.installed) {
|
if (extension.installed) {
|
||||||
|
if (extension.hasUpdate) {
|
||||||
|
result['updates pending'].push(extension);
|
||||||
|
} else {
|
||||||
result.installed.push(extension);
|
result.installed.push(extension);
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
result[extension.lang].push(extension);
|
result[extension.lang].push(extension);
|
||||||
}
|
}
|
||||||
@ -79,11 +83,12 @@ export default function Extensions() {
|
|||||||
if (Object.entries(extensions).length === 0) {
|
if (Object.entries(extensions).length === 0) {
|
||||||
return <h3>loading...</h3>;
|
return <h3>loading...</h3>;
|
||||||
}
|
}
|
||||||
|
const groupsToShow = ['updates pending', 'installed', ...shownLangs];
|
||||||
return (
|
return (
|
||||||
<>
|
<>
|
||||||
{
|
{
|
||||||
Object.entries(extensions).map(([lang, list]) => (
|
Object.entries(extensions).map(([lang, list]) => (
|
||||||
((['installed', ...shownLangs].indexOf(lang) !== -1 && (list as []).length > 0)
|
((groupsToShow.indexOf(lang) !== -1 && (list as []).length > 0)
|
||||||
&& (
|
&& (
|
||||||
<React.Fragment key={lang}>
|
<React.Fragment key={lang}>
|
||||||
<h1 key={lang} style={{ marginLeft: 25 }}>
|
<h1 key={lang} style={{ marginLeft: 25 }}>
|
||||||
|
4
webUI/react/src/typings.d.ts
vendored
4
webUI/react/src/typings.d.ts
vendored
@ -14,9 +14,9 @@ interface IExtension {
|
|||||||
isNsfw: boolean
|
isNsfw: boolean
|
||||||
apkName: string
|
apkName: string
|
||||||
iconUrl: string
|
iconUrl: string
|
||||||
isInstalled: boolean
|
installed: boolean
|
||||||
hasUpdate: boolean
|
hasUpdate: boolean
|
||||||
isObsolete: boolean
|
obsolete: boolean
|
||||||
}
|
}
|
||||||
|
|
||||||
interface ISource {
|
interface ISource {
|
||||||
|
@ -8,6 +8,7 @@
|
|||||||
export const ISOLanguages = [
|
export const ISOLanguages = [
|
||||||
{ code: 'all', name: 'All', nativeName: 'All' },
|
{ code: 'all', name: 'All', nativeName: 'All' },
|
||||||
{ code: 'installed', name: 'Installed', nativeName: 'Installed' },
|
{ code: 'installed', name: 'Installed', nativeName: 'Installed' },
|
||||||
|
{ code: 'updates pending', name: 'Updates pending', nativeName: 'Updates pending' },
|
||||||
|
|
||||||
// full list: https://github.com/meikidd/iso-639-1/blob/master/src/data.js
|
// full list: https://github.com/meikidd/iso-639-1/blob/master/src/data.js
|
||||||
{ code: 'en', name: 'English', nativeName: 'English' },
|
{ code: 'en', name: 'English', nativeName: 'English' },
|
||||||
|
Loading…
Reference in New Issue
Block a user