diff --git a/AndroidCompat/getAndroid.sh b/AndroidCompat/getAndroid.sh index f1136ef9..97de7772 100755 --- a/AndroidCompat/getAndroid.sh +++ b/AndroidCompat/getAndroid.sh @@ -13,7 +13,7 @@ do which $dep >/dev/null 2>&1 || { echo >&2 "Error: This script needs $dep installed."; abort=yes; } done -if [ $abort = yes ]; then +if [ "$abort" = yes ]; then echo "Some of the dependencies didn't exist. Aborting." exit 1 fi diff --git a/AndroidCompat/src/main/java/android/widget/Toast.java b/AndroidCompat/src/main/java/android/widget/Toast.java new file mode 100644 index 00000000..603efb9b --- /dev/null +++ b/AndroidCompat/src/main/java/android/widget/Toast.java @@ -0,0 +1,91 @@ +package android.widget; + +/* + * Copyright (C) Contributors to the Suwayomi project + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at https://mozilla.org/MPL/2.0/. */ + +public class Toast { + public static final int LENGTH_LONG = 1; + public static final int LENGTH_SHORT = 0; + + private CharSequence text; + + private Toast(CharSequence text) { + this.text = text; + } + + public Toast(android.content.Context context) { + throw new RuntimeException("Stub!"); + } + + public void show() { + System.out.printf("made a Toast: \"%s\"\n", text.toString()); + } + + public void cancel() { + throw new RuntimeException("Stub!"); + } + + public void setView(android.view.View view) { + throw new RuntimeException("Stub!"); + } + + public android.view.View getView() { + throw new RuntimeException("Stub!"); + } + + public void setDuration(int duration) { + throw new RuntimeException("Stub!"); + } + + public int getDuration() { + throw new RuntimeException("Stub!"); + } + + public void setMargin(float horizontalMargin, float verticalMargin) { + throw new RuntimeException("Stub!"); + } + + public float getHorizontalMargin() { + throw new RuntimeException("Stub!"); + } + + public float getVerticalMargin() { + throw new RuntimeException("Stub!"); + } + + public void setGravity(int gravity, int xOffset, int yOffset) { + throw new RuntimeException("Stub!"); + } + + public int getGravity() { + throw new RuntimeException("Stub!"); + } + + public int getXOffset() { + throw new RuntimeException("Stub!"); + } + + public int getYOffset() { + throw new RuntimeException("Stub!"); + } + + public static Toast makeText(android.content.Context context, java.lang.CharSequence text, int duration) { + return new Toast(text); + } + + public static android.widget.Toast makeText(android.content.Context context, int resId, int duration) throws android.content.res.Resources.NotFoundException { + throw new RuntimeException("Stub!"); + } + + public void setText(int resId) { + throw new RuntimeException("Stub!"); + } + + public void setText(java.lang.CharSequence s) { + throw new RuntimeException("Stub!"); + } +} \ No newline at end of file diff --git a/AndroidCompat/src/main/java/androidx/preference/EditTextPreference.java b/AndroidCompat/src/main/java/androidx/preference/EditTextPreference.java new file mode 100644 index 00000000..088f8392 --- /dev/null +++ b/AndroidCompat/src/main/java/androidx/preference/EditTextPreference.java @@ -0,0 +1,46 @@ +package androidx.preference; + +import android.content.Context; + +public class EditTextPreference extends Preference { + private String title; + private CharSequence summary; + private CharSequence dialogTitle; + private CharSequence dialogMessage; + + public EditTextPreference(Context context) { + super(context); + } + + public String getTitle() { + return title; + } + + public void setTitle(CharSequence title) { + this.title = (String) title; + } + + public CharSequence getSummary() { + return summary; + } + + public void setSummary(CharSequence summary) { + this.summary = summary; + } + + public CharSequence getDialogTitle() { + return dialogTitle; + } + + public void setDialogTitle(CharSequence dialogTitle) { + this.dialogTitle = dialogTitle; + } + + public CharSequence getDialogMessage() { + return dialogMessage; + } + + public void setDialogMessage(CharSequence dialogMessage) { + this.dialogMessage = dialogMessage; + } +} diff --git a/AndroidCompat/src/main/java/androidx/preference/Preference.java b/AndroidCompat/src/main/java/androidx/preference/Preference.java new file mode 100644 index 00000000..9a619dd1 --- /dev/null +++ b/AndroidCompat/src/main/java/androidx/preference/Preference.java @@ -0,0 +1,68 @@ +package androidx.preference; + +/* + * Copyright (C) Contributors to the Suwayomi project + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at https://mozilla.org/MPL/2.0/. */ + +import android.content.Context; +import com.fasterxml.jackson.annotation.JsonIgnore; + +/** A minimal implementation of androidx.preference.Preference */ +public class Preference { + // reference: https://android.googlesource.com/platform/frameworks/support/+/996971f962fcd554339a7cb2859cef9ca89dbcb7/preference/preference/src/main/java/androidx/preference/Preference.java + // Note: `Preference` doesn't actually hold or persist the value, `OnPreferenceChangeListener` is called and it's up to the extension to persist it. + + @JsonIgnore + protected Context context; + + private String key; + private CharSequence title; + private Object defaultValue; + + @JsonIgnore + public OnPreferenceChangeListener onChangeListener; + + public Preference(Context context) { + this.context = context; + } + + public Context getContext() { + return context; + } + + public String getKey() { + return key; + } + + public void setKey(String key) { + this.key = key; + } + + public void setDefaultValue(Object defaultValue) { + this.defaultValue = defaultValue; + } + + public CharSequence getTitle() { + return title; + } + + public void setOnPreferenceChangeListener(OnPreferenceChangeListener onPreferenceChangeListener) { + this.onChangeListener = onPreferenceChangeListener; + } + + public boolean callChangeListener(Object newValue) { + return onChangeListener == null || onChangeListener.onPreferenceChange(this, newValue); + } + + public Object getDefaultValue() { + return defaultValue; + } + + public interface OnPreferenceChangeListener { + boolean onPreferenceChange(Preference preference, Object newValue); + } + +} diff --git a/AndroidCompat/src/main/java/androidx/preference/PreferenceScreen.java b/AndroidCompat/src/main/java/androidx/preference/PreferenceScreen.java index cf1832e0..0b91501c 100644 --- a/AndroidCompat/src/main/java/androidx/preference/PreferenceScreen.java +++ b/AndroidCompat/src/main/java/androidx/preference/PreferenceScreen.java @@ -1,4 +1,32 @@ package androidx.preference; -public class PreferenceScreen { +/* + * Copyright (C) Contributors to the Suwayomi project + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at https://mozilla.org/MPL/2.0/. */ + +import android.content.Context; + +import java.util.LinkedList; +import java.util.List; + +public class PreferenceScreen extends Preference { + private List preferences = new LinkedList<>(); + + + public PreferenceScreen(Context context) { + super(context); + } + + public boolean addPreference(Preference preference) { + preferences.add(preference); + + return true; + } + + public List getPreferences(){ + return preferences; + } } diff --git a/AndroidCompat/src/main/java/xyz/nulldev/androidcompat/androidimpl/CustomContext.java b/AndroidCompat/src/main/java/xyz/nulldev/androidcompat/androidimpl/CustomContext.java index 617a6f5a..8c136d21 100644 --- a/AndroidCompat/src/main/java/xyz/nulldev/androidcompat/androidimpl/CustomContext.java +++ b/AndroidCompat/src/main/java/xyz/nulldev/androidcompat/androidimpl/CustomContext.java @@ -50,10 +50,9 @@ import java.util.Map; /** * Custom context implementation. * - * TODO Deal with packagemanager for extension sources */ public class CustomContext extends Context implements DIAware { - private DI kodein; + private final DI kodein; public CustomContext() { this(KodeinGlobalHelper.kodein()); } @@ -734,4 +733,3 @@ public class CustomContext extends Context implements DIAware { } } - diff --git a/AndroidCompat/src/main/java/xyz/nulldev/androidcompat/io/AndroidFiles.kt b/AndroidCompat/src/main/java/xyz/nulldev/androidcompat/io/AndroidFiles.kt index dafa70ea..ea55b497 100644 --- a/AndroidCompat/src/main/java/xyz/nulldev/androidcompat/io/AndroidFiles.kt +++ b/AndroidCompat/src/main/java/xyz/nulldev/androidcompat/io/AndroidFiles.kt @@ -26,6 +26,8 @@ class AndroidFiles(val configManager: ConfigManager = GlobalConfigManager) { val downloadCacheDir: File get() = registerFile(filesConfig.downloadCacheDir) val databasesDir: File get() = registerFile(filesConfig.databasesDir) + val prefsDir: File get() = registerFile(filesConfig.prefsDir) + val packagesDir: File get() = registerFile(filesConfig.packageDir) fun registerFile(file: String): File { diff --git a/AndroidCompat/src/main/java/xyz/nulldev/androidcompat/io/sharedprefs/JavaSharedPreferences.kt b/AndroidCompat/src/main/java/xyz/nulldev/androidcompat/io/sharedprefs/JavaSharedPreferences.kt index 1c7f3ea8..a0c132f0 100644 --- a/AndroidCompat/src/main/java/xyz/nulldev/androidcompat/io/sharedprefs/JavaSharedPreferences.kt +++ b/AndroidCompat/src/main/java/xyz/nulldev/androidcompat/io/sharedprefs/JavaSharedPreferences.kt @@ -1,5 +1,12 @@ package xyz.nulldev.androidcompat.io.sharedprefs +/* + * Copyright (C) Contributors to the Suwayomi project + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at https://mozilla.org/MPL/2.0/. */ + import android.content.SharedPreferences import com.russhwolf.settings.ExperimentalSettingsApi import com.russhwolf.settings.ExperimentalSettingsImplementation diff --git a/AndroidCompat/src/main/java/xyz/nulldev/androidcompat/io/sharedprefs/JsonSharedPreferences.java b/AndroidCompat/src/main/java/xyz/nulldev/androidcompat/io/sharedprefs/JsonSharedPreferences.java index 9b04c7b0..90703bb0 100644 --- a/AndroidCompat/src/main/java/xyz/nulldev/androidcompat/io/sharedprefs/JsonSharedPreferences.java +++ b/AndroidCompat/src/main/java/xyz/nulldev/androidcompat/io/sharedprefs/JsonSharedPreferences.java @@ -233,7 +233,7 @@ public class JsonSharedPreferences implements SharedPreferences { private JsonSharedPreferencesEditor() { } - private void recordChange(String key) { + private void recordChange(String key) { if (!affectedKeys.contains(key)) { affectedKeys.add(key); } diff --git a/build.gradle.kts b/build.gradle.kts index be658d61..9697908b 100644 --- a/build.gradle.kts +++ b/build.gradle.kts @@ -84,5 +84,8 @@ configure(projects) { // APK parser implementation("net.dongliu:apk-parser:2.6.10") + + // Jackson + implementation("com.fasterxml.jackson.core:jackson-annotations:2.10.3") } } \ No newline at end of file diff --git a/server/src/main/kotlin/suwayomi/tachidesk/manga/TachideskAPI.kt b/server/src/main/kotlin/suwayomi/tachidesk/manga/TachideskAPI.kt index 88421c6b..e70ce519 100644 --- a/server/src/main/kotlin/suwayomi/tachidesk/manga/TachideskAPI.kt +++ b/server/src/main/kotlin/suwayomi/tachidesk/manga/TachideskAPI.kt @@ -30,6 +30,7 @@ import suwayomi.tachidesk.manga.impl.Search.sourceGlobalSearch import suwayomi.tachidesk.manga.impl.Search.sourceSearch import suwayomi.tachidesk.manga.impl.Source.getSource import suwayomi.tachidesk.manga.impl.Source.getSourceList +import suwayomi.tachidesk.manga.impl.Source.getSourcePreferences import suwayomi.tachidesk.manga.impl.backup.BackupFlags import suwayomi.tachidesk.manga.impl.backup.legacy.LegacyBackupExport.createLegacyBackup import suwayomi.tachidesk.manga.impl.backup.legacy.LegacyBackupImport.restoreLegacyBackup @@ -109,6 +110,12 @@ object TachideskAPI { ctx.json(getSource(sourceId)) } + // fetch preferences of source with id `sourceId` + app.get("/api/v1/source/:sourceId/preference-screen") { ctx -> + val sourceId = ctx.pathParam("sourceId").toLong() + ctx.json(getSourcePreferences(sourceId)) + } + // popular mangas from source with id `sourceId` app.get("/api/v1/source/:sourceId/popular/:pageNum") { ctx -> val sourceId = ctx.pathParam("sourceId").toLong() diff --git a/server/src/main/kotlin/suwayomi/tachidesk/manga/impl/Source.kt b/server/src/main/kotlin/suwayomi/tachidesk/manga/impl/Source.kt index 7f8373d5..b4bc4f36 100644 --- a/server/src/main/kotlin/suwayomi/tachidesk/manga/impl/Source.kt +++ b/server/src/main/kotlin/suwayomi/tachidesk/manga/impl/Source.kt @@ -7,15 +7,21 @@ package suwayomi.tachidesk.manga.impl * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at https://mozilla.org/MPL/2.0/. */ +import androidx.preference.PreferenceScreen +import eu.kanade.tachiyomi.source.ConfigurableSource import mu.KotlinLogging import org.jetbrains.exposed.sql.select import org.jetbrains.exposed.sql.selectAll import org.jetbrains.exposed.sql.transactions.transaction +import org.kodein.di.DI +import org.kodein.di.conf.global +import org.kodein.di.instance import suwayomi.tachidesk.manga.impl.extension.Extension.getExtensionIconUrl import suwayomi.tachidesk.manga.impl.util.GetHttpSource.getHttpSource import suwayomi.tachidesk.manga.model.dataclass.SourceDataClass import suwayomi.tachidesk.manga.model.table.ExtensionTable import suwayomi.tachidesk.manga.model.table.SourceTable +import xyz.nulldev.androidcompat.androidimpl.CustomContext object Source { private val logger = KotlinLogging.logger {} @@ -28,7 +34,8 @@ object Source { it[SourceTable.name], it[SourceTable.lang], getExtensionIconUrl(ExtensionTable.select { ExtensionTable.id eq it[SourceTable.extension] }.first()[ExtensionTable.apkName]), - getHttpSource(it[SourceTable.id].value).supportsLatest + getHttpSource(it[SourceTable.id].value).supportsLatest, + getHttpSource(it[SourceTable.id].value) is ConfigurableSource ) } } @@ -43,8 +50,36 @@ object Source { source?.get(SourceTable.name), source?.get(SourceTable.lang), source?.let { ExtensionTable.select { ExtensionTable.id eq source[SourceTable.extension] }.first()[ExtensionTable.iconUrl] }, - source?.let { getHttpSource(sourceId).supportsLatest } + source?.let { getHttpSource(sourceId).supportsLatest }, + source?.let { getHttpSource(sourceId) is ConfigurableSource }, ) } } + + private val context by DI.global.instance() + + data class PreferenceObject( + val type: String, + val props: Any + ) + + var lastPreferenceScreen: PreferenceScreen? = null + + fun getSourcePreferences(sourceId: Long): List { + val source = getHttpSource(sourceId) + + if (source is ConfigurableSource) { + val screen = PreferenceScreen(context) + lastPreferenceScreen = screen + + source.setupPreferenceScreen(screen) + + screen.preferences.first().callChangeListener("yo") + + return screen.preferences.map { + PreferenceObject(it::class.java.name, it) + } + } + return emptyList() + } } diff --git a/server/src/main/kotlin/suwayomi/tachidesk/manga/model/dataclass/SourceDataClass.kt b/server/src/main/kotlin/suwayomi/tachidesk/manga/model/dataclass/SourceDataClass.kt index 939a356a..022356cc 100644 --- a/server/src/main/kotlin/suwayomi/tachidesk/manga/model/dataclass/SourceDataClass.kt +++ b/server/src/main/kotlin/suwayomi/tachidesk/manga/model/dataclass/SourceDataClass.kt @@ -12,5 +12,6 @@ data class SourceDataClass( val name: String?, val lang: String?, val iconUrl: String?, - val supportsLatest: Boolean? + val supportsLatest: Boolean?, + val isConfigurable: Boolean? ) diff --git a/server/src/main/kotlin/suwayomi/tachidesk/server/JavalinSetup.kt b/server/src/main/kotlin/suwayomi/tachidesk/server/JavalinSetup.kt index abe53b60..1a6ca2e8 100644 --- a/server/src/main/kotlin/suwayomi/tachidesk/server/JavalinSetup.kt +++ b/server/src/main/kotlin/suwayomi/tachidesk/server/JavalinSetup.kt @@ -1,5 +1,12 @@ package suwayomi.tachidesk.server +/* + * Copyright (C) Contributors to the Suwayomi project + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at https://mozilla.org/MPL/2.0/. */ + import io.javalin.Javalin import kotlinx.coroutines.CoroutineScope import kotlinx.coroutines.Dispatchers @@ -13,13 +20,6 @@ import java.io.IOException import java.util.concurrent.CompletableFuture import kotlin.concurrent.thread -/* - * Copyright (C) Contributors to the Suwayomi project - * - * This Source Code Form is subject to the terms of the Mozilla Public - * License, v. 2.0. If a copy of the MPL was not distributed with this - * file, You can obtain one at https://mozilla.org/MPL/2.0/. */ - object JavalinSetup { private val logger = KotlinLogging.logger {}