From 91d191f01bb6f86fb1b0ee0b0e68bd483416d692 Mon Sep 17 00:00:00 2001 From: Niko Diamadis Date: Mon, 26 Dec 2022 18:37:38 +0100 Subject: [PATCH] Rewrite root directory files to Kotlin --- .../com/github/gotify/MarkwonFactory.java | 130 ------------------ .../java/com/github/gotify/MarkwonFactory.kt | 96 +++++++++++++ .../com/github/gotify/MissedMessageUtil.java | 77 ----------- .../com/github/gotify/MissedMessageUtil.kt | 63 +++++++++ .../github/gotify/NotificationSupport.java | 107 -------------- .../com/github/gotify/NotificationSupport.kt | 106 ++++++++++++++ .../java/com/github/gotify/SSLSettings.java | 11 -- .../java/com/github/gotify/SSLSettings.kt | 3 + .../main/java/com/github/gotify/Settings.java | 82 ----------- .../main/java/com/github/gotify/Settings.kt | 56 ++++++++ .../main/java/com/github/gotify/Utils.java | 110 --------------- app/src/main/java/com/github/gotify/Utils.kt | 101 ++++++++++++++ 12 files changed, 425 insertions(+), 517 deletions(-) delete mode 100644 app/src/main/java/com/github/gotify/MarkwonFactory.java create mode 100644 app/src/main/java/com/github/gotify/MarkwonFactory.kt delete mode 100644 app/src/main/java/com/github/gotify/MissedMessageUtil.java create mode 100644 app/src/main/java/com/github/gotify/MissedMessageUtil.kt delete mode 100644 app/src/main/java/com/github/gotify/NotificationSupport.java create mode 100644 app/src/main/java/com/github/gotify/NotificationSupport.kt delete mode 100644 app/src/main/java/com/github/gotify/SSLSettings.java create mode 100644 app/src/main/java/com/github/gotify/SSLSettings.kt delete mode 100644 app/src/main/java/com/github/gotify/Settings.java create mode 100644 app/src/main/java/com/github/gotify/Settings.kt delete mode 100644 app/src/main/java/com/github/gotify/Utils.java create mode 100644 app/src/main/java/com/github/gotify/Utils.kt diff --git a/app/src/main/java/com/github/gotify/MarkwonFactory.java b/app/src/main/java/com/github/gotify/MarkwonFactory.java deleted file mode 100644 index 877e0b9..0000000 --- a/app/src/main/java/com/github/gotify/MarkwonFactory.java +++ /dev/null @@ -1,130 +0,0 @@ -package com.github.gotify; - -import android.content.Context; -import android.graphics.Color; -import android.graphics.Typeface; -import android.text.style.BackgroundColorSpan; -import android.text.style.BulletSpan; -import android.text.style.QuoteSpan; -import android.text.style.RelativeSizeSpan; -import android.text.style.StyleSpan; -import android.text.style.TypefaceSpan; -import androidx.annotation.NonNull; -import androidx.core.content.ContextCompat; -import com.squareup.picasso.Picasso; -import io.noties.markwon.AbstractMarkwonPlugin; -import io.noties.markwon.Markwon; -import io.noties.markwon.MarkwonSpansFactory; -import io.noties.markwon.MarkwonVisitor; -import io.noties.markwon.core.CorePlugin; -import io.noties.markwon.core.CoreProps; -import io.noties.markwon.core.MarkwonTheme; -import io.noties.markwon.ext.strikethrough.StrikethroughPlugin; -import io.noties.markwon.ext.tables.TableAwareMovementMethod; -import io.noties.markwon.ext.tables.TablePlugin; -import io.noties.markwon.image.picasso.PicassoImagesPlugin; -import io.noties.markwon.movement.MovementMethodPlugin; -import java.util.Collections; -import org.commonmark.ext.gfm.tables.TableCell; -import org.commonmark.ext.gfm.tables.TablesExtension; -import org.commonmark.node.BlockQuote; -import org.commonmark.node.Code; -import org.commonmark.node.Emphasis; -import org.commonmark.node.Heading; -import org.commonmark.node.Link; -import org.commonmark.node.ListItem; -import org.commonmark.node.StrongEmphasis; -import org.commonmark.parser.Parser; - -public class MarkwonFactory { - public static Markwon createForMessage(Context context, Picasso picasso) { - return Markwon.builder(context) - .usePlugin(CorePlugin.create()) - .usePlugin(MovementMethodPlugin.create(TableAwareMovementMethod.create())) - .usePlugin(PicassoImagesPlugin.create(picasso)) - .usePlugin(StrikethroughPlugin.create()) - .usePlugin(TablePlugin.create(context)) - .usePlugin( - new AbstractMarkwonPlugin() { - @Override - public void configureTheme(@NonNull MarkwonTheme.Builder builder) { - builder.linkColor( - ContextCompat.getColor(context, R.color.hyperLink)) - .isLinkUnderlined(true); - } - }) - .build(); - } - - public static Markwon createForNotification(Context context, Picasso picasso) { - final float[] headingSizes = { - 2.F, 1.5F, 1.17F, 1.F, .83F, .67F, - }; - - final int bulletGapWidth = - (int) (8 * context.getResources().getDisplayMetrics().density + 0.5F); - - return Markwon.builder(context) - .usePlugin(CorePlugin.create()) - .usePlugin(PicassoImagesPlugin.create(picasso)) - .usePlugin(StrikethroughPlugin.create()) - .usePlugin( - new AbstractMarkwonPlugin() { - @Override - public void configureSpansFactory( - @NonNull MarkwonSpansFactory.Builder builder) { - builder.setFactory( - Heading.class, - (configuration, props) -> - new Object[] { - new RelativeSizeSpan( - headingSizes[ - CoreProps.HEADING_LEVEL - .require( - props) - - 1]), - new StyleSpan(Typeface.BOLD) - }) - .setFactory( - Emphasis.class, - (configuration, props) -> - new StyleSpan(Typeface.ITALIC)) - .setFactory( - StrongEmphasis.class, - (configuration, props) -> - new StyleSpan(Typeface.BOLD)) - .setFactory( - BlockQuote.class, - (configuration, props) -> new QuoteSpan()) - .setFactory( - Code.class, - (configuration, props) -> - new Object[] { - new BackgroundColorSpan(Color.LTGRAY), - new TypefaceSpan("monospace") - }) - .setFactory( - ListItem.class, - (configuration, props) -> - new BulletSpan(bulletGapWidth)) - .setFactory(Link.class, ((configuration, props) -> null)); - } - - @Override - public void configureParser(@NonNull Parser.Builder builder) { - builder.extensions(Collections.singleton(TablesExtension.create())); - } - - @Override - public void configureVisitor(@NonNull MarkwonVisitor.Builder builder) { - builder.on( - TableCell.class, - (visitor, node) -> { - visitor.visitChildren(node); - visitor.builder().append(' '); - }); - } - }) - .build(); - } -} diff --git a/app/src/main/java/com/github/gotify/MarkwonFactory.kt b/app/src/main/java/com/github/gotify/MarkwonFactory.kt new file mode 100644 index 0000000..3692d91 --- /dev/null +++ b/app/src/main/java/com/github/gotify/MarkwonFactory.kt @@ -0,0 +1,96 @@ +package com.github.gotify + +import android.content.Context +import android.graphics.Color +import android.graphics.Typeface +import android.text.style.* +import androidx.core.content.ContextCompat +import com.squareup.picasso.Picasso +import io.noties.markwon.* +import io.noties.markwon.core.CorePlugin +import io.noties.markwon.core.CoreProps +import io.noties.markwon.core.MarkwonTheme +import io.noties.markwon.ext.strikethrough.StrikethroughPlugin +import io.noties.markwon.ext.tables.TableAwareMovementMethod +import io.noties.markwon.ext.tables.TablePlugin +import io.noties.markwon.image.picasso.PicassoImagesPlugin +import io.noties.markwon.movement.MovementMethodPlugin +import org.commonmark.ext.gfm.tables.TableCell +import org.commonmark.ext.gfm.tables.TablesExtension +import org.commonmark.node.* +import org.commonmark.parser.Parser + +object MarkwonFactory { + fun createForMessage(context: Context, picasso: Picasso): Markwon { + return Markwon.builder(context) + .usePlugin(CorePlugin.create()) + .usePlugin(MovementMethodPlugin.create(TableAwareMovementMethod.create())) + .usePlugin(PicassoImagesPlugin.create(picasso)) + .usePlugin(StrikethroughPlugin.create()) + .usePlugin(TablePlugin.create(context)) + .usePlugin( + object : AbstractMarkwonPlugin() { + override fun configureTheme(builder: MarkwonTheme.Builder) { + builder.linkColor(ContextCompat.getColor(context, R.color.hyperLink)) + .isLinkUnderlined(true) + } + }) + .build() + } + + fun createForNotification(context: Context, picasso: Picasso): Markwon { + val headingSizes = floatArrayOf( + 2f, 1.5f, 1.17f, 1f, .83f, .67f + ) + val bulletGapWidth = (8 * context.resources.displayMetrics.density + 0.5f).toInt() + + return Markwon.builder(context) + .usePlugin(CorePlugin.create()) + .usePlugin(PicassoImagesPlugin.create(picasso)) + .usePlugin(StrikethroughPlugin.create()) + .usePlugin( + object : AbstractMarkwonPlugin() { + override fun configureSpansFactory(builder: MarkwonSpansFactory.Builder) { + builder.setFactory(Heading::class.java) { _, props: RenderProps? -> + arrayOf( + RelativeSizeSpan( + headingSizes[CoreProps.HEADING_LEVEL.require(props!!) - 1] + ), + StyleSpan(Typeface.BOLD) + ) + } + .setFactory(Emphasis::class.java) { _, _ -> + StyleSpan(Typeface.ITALIC) + } + .setFactory(StrongEmphasis::class.java) { _, _ -> + StyleSpan(Typeface.BOLD) + } + .setFactory(BlockQuote::class.java) { _, _ -> QuoteSpan() } + .setFactory(Code::class.java) { _, _ -> + arrayOf( + BackgroundColorSpan(Color.LTGRAY), + TypefaceSpan("monospace") + ) + } + .setFactory(ListItem::class.java) { _, _ -> + BulletSpan(bulletGapWidth) + } + .setFactory(Link::class.java) { _, _ -> null } + } + + override fun configureParser(builder: Parser.Builder) { + builder.extensions(setOf(TablesExtension.create())) + } + + override fun configureVisitor(builder: MarkwonVisitor.Builder) { + builder.on( + TableCell::class.java + ) { visitor: MarkwonVisitor, node: TableCell? -> + visitor.visitChildren(node!!) + visitor.builder().append(' ') + } + } + }) + .build() + } +} diff --git a/app/src/main/java/com/github/gotify/MissedMessageUtil.java b/app/src/main/java/com/github/gotify/MissedMessageUtil.java deleted file mode 100644 index d197830..0000000 --- a/app/src/main/java/com/github/gotify/MissedMessageUtil.java +++ /dev/null @@ -1,77 +0,0 @@ -package com.github.gotify; - -import com.github.gotify.api.Api; -import com.github.gotify.api.ApiException; -import com.github.gotify.api.Callback; -import com.github.gotify.client.api.MessageApi; -import com.github.gotify.client.model.Message; -import com.github.gotify.client.model.PagedMessages; -import com.github.gotify.log.Log; -import java.util.ArrayList; -import java.util.Collections; -import java.util.List; - -import static com.github.gotify.api.Callback.call; - -public class MissedMessageUtil { - static final long NO_MESSAGES = 0; - - private final MessageApi api; - - public MissedMessageUtil(MessageApi api) { - this.api = api; - } - - public void lastReceivedMessage(Callback.SuccessCallback successCallback) { - api.getMessages(1, 0L) - .enqueue( - call( - (messages) -> { - if (messages.getMessages().size() == 1) { - successCallback.onSuccess( - messages.getMessages().get(0).getId()); - } else { - successCallback.onSuccess(NO_MESSAGES); - } - }, - (e) -> {})); - } - - public List missingMessages(long till) { - List result = new ArrayList<>(); - try { - - Long since = null; - while (true) { - PagedMessages pagedMessages = Api.execute(api.getMessages(10, since)); - List messages = pagedMessages.getMessages(); - List filtered = filter(messages, till); - result.addAll(filtered); - if (messages.size() != filtered.size() - || messages.size() == 0 - || pagedMessages.getPaging().getNext() == null) { - break; - } - since = pagedMessages.getPaging().getSince(); - } - } catch (ApiException e) { - Log.e("cannot retrieve missing messages", e); - } - Collections.reverse(result); - return result; - } - - private List filter(List messages, long till) { - List result = new ArrayList<>(); - - for (Message message : messages) { - if (message.getId() > till) { - result.add(message); - } else { - break; - } - } - - return result; - } -} diff --git a/app/src/main/java/com/github/gotify/MissedMessageUtil.kt b/app/src/main/java/com/github/gotify/MissedMessageUtil.kt new file mode 100644 index 0000000..aa598f5 --- /dev/null +++ b/app/src/main/java/com/github/gotify/MissedMessageUtil.kt @@ -0,0 +1,63 @@ +package com.github.gotify + +import com.github.gotify.api.Api +import com.github.gotify.api.ApiException +import com.github.gotify.api.Callback +import com.github.gotify.api.Callback.SuccessCallback +import com.github.gotify.client.api.MessageApi +import com.github.gotify.client.model.Message +import com.github.gotify.client.model.PagedMessages +import com.github.gotify.log.Log + +class MissedMessageUtil(private val api: MessageApi) { + fun lastReceivedMessage(successCallback: SuccessCallback) { + api.getMessages(1, 0L).enqueue( + Callback.call({ messages: PagedMessages? -> + if (messages!!.messages.size == 1) { + successCallback.onSuccess(messages.messages[0].id) + } else { + successCallback.onSuccess(NO_MESSAGES) + } + } + ) {} + ) + } + + fun missingMessages(till: Long): List { + val result = mutableListOf() + try { + var since: Long? = null + while (true) { + val pagedMessages = Api.execute(api.getMessages(10, since)) + val messages = pagedMessages!!.messages + val filtered = filter(messages, till) + result.addAll(filtered) + if (messages.size != filtered.size + || messages.size == 0 + || pagedMessages.paging.next == null) { + break + } + since = pagedMessages.paging.since + } + } catch (e: ApiException) { + Log.e("cannot retrieve missing messages", e) + } + return result.reversed() + } + + private fun filter(messages: List, till: Long): List { + val result = mutableListOf() + for (message in messages) { + if (message.id > till) { + result.add(message) + } else { + break + } + } + return result + } + + companion object { + const val NO_MESSAGES = 0L + } +} diff --git a/app/src/main/java/com/github/gotify/NotificationSupport.java b/app/src/main/java/com/github/gotify/NotificationSupport.java deleted file mode 100644 index 694f31f..0000000 --- a/app/src/main/java/com/github/gotify/NotificationSupport.java +++ /dev/null @@ -1,107 +0,0 @@ -package com.github.gotify; - -import android.app.NotificationChannel; -import android.app.NotificationManager; -import android.graphics.Color; -import android.os.Build; -import androidx.annotation.RequiresApi; -import com.github.gotify.log.Log; - -public class NotificationSupport { - public static final class Group { - public static final String MESSAGES = "GOTIFY_GROUP_MESSAGES"; - } - - public static final class Channel { - public static final String FOREGROUND = "gotify_foreground"; - public static final String MESSAGES_IMPORTANCE_MIN = "gotify_messages_min_importance"; - public static final String MESSAGES_IMPORTANCE_LOW = "gotify_messages_low_importance"; - public static final String MESSAGES_IMPORTANCE_DEFAULT = - "gotify_messages_default_importance"; - public static final String MESSAGES_IMPORTANCE_HIGH = "gotify_messages_high_importance"; - } - - public static final class ID { - public static final int FOREGROUND = -1; - public static final int GROUPED = -2; - } - - @RequiresApi(Build.VERSION_CODES.O) - public static void createChannels(NotificationManager notificationManager) { - try { - // Low importance so that persistent notification can be sorted towards bottom of - // notification shade. Also prevents vibrations caused by persistent notification - NotificationChannel foreground = - new NotificationChannel( - Channel.FOREGROUND, - "Gotify foreground notification", - NotificationManager.IMPORTANCE_LOW); - foreground.setShowBadge(false); - - NotificationChannel messagesImportanceMin = - new NotificationChannel( - Channel.MESSAGES_IMPORTANCE_MIN, - "Min priority messages (<1)", - NotificationManager.IMPORTANCE_MIN); - - NotificationChannel messagesImportanceLow = - new NotificationChannel( - Channel.MESSAGES_IMPORTANCE_LOW, - "Low priority messages (1-3)", - NotificationManager.IMPORTANCE_LOW); - - NotificationChannel messagesImportanceDefault = - new NotificationChannel( - Channel.MESSAGES_IMPORTANCE_DEFAULT, - "Normal priority messages (4-7)", - NotificationManager.IMPORTANCE_DEFAULT); - messagesImportanceDefault.enableLights(true); - messagesImportanceDefault.setLightColor(Color.CYAN); - messagesImportanceDefault.enableVibration(true); - - NotificationChannel messagesImportanceHigh = - new NotificationChannel( - Channel.MESSAGES_IMPORTANCE_HIGH, - "High priority messages (>7)", - NotificationManager.IMPORTANCE_HIGH); - messagesImportanceHigh.enableLights(true); - messagesImportanceHigh.setLightColor(Color.CYAN); - messagesImportanceHigh.enableVibration(true); - - notificationManager.createNotificationChannel(foreground); - notificationManager.createNotificationChannel(messagesImportanceMin); - notificationManager.createNotificationChannel(messagesImportanceLow); - notificationManager.createNotificationChannel(messagesImportanceDefault); - notificationManager.createNotificationChannel(messagesImportanceHigh); - } catch (Exception e) { - Log.e("Could not create channel", e); - } - } - - /** - * Map {@link com.github.gotify.client.model.Message#getPriority() Gotify message priorities to - * Android channels. - * - *
-     * Gotify Priority  | Android Importance
-     * <= 0             | min
-     * 1-3              | low
-     * 4-7              | default
-     * >= 8             | high
-     * 
- * - * @param priority the Gotify priority to convert to a notification channel as a long. - * @return the identifier of the notification channel as a String. - */ - public static String convertPriorityToChannel(long priority) { - if (priority < 1) { - return Channel.MESSAGES_IMPORTANCE_MIN; - } else if (priority < 4) { - return Channel.MESSAGES_IMPORTANCE_LOW; - } else if (priority < 8) { - return Channel.MESSAGES_IMPORTANCE_DEFAULT; - } else { - return Channel.MESSAGES_IMPORTANCE_HIGH; - } - } -} diff --git a/app/src/main/java/com/github/gotify/NotificationSupport.kt b/app/src/main/java/com/github/gotify/NotificationSupport.kt new file mode 100644 index 0000000..548cc2f --- /dev/null +++ b/app/src/main/java/com/github/gotify/NotificationSupport.kt @@ -0,0 +1,106 @@ +package com.github.gotify + +import android.app.NotificationChannel +import android.app.NotificationManager +import android.graphics.Color +import android.os.Build +import androidx.annotation.RequiresApi +import com.github.gotify.log.Log + +object NotificationSupport { + @RequiresApi(Build.VERSION_CODES.O) + fun createChannels(notificationManager: NotificationManager) { + try { + // Low importance so that persistent notification can be sorted towards bottom of + // notification shade. Also prevents vibrations caused by persistent notification + val foreground = NotificationChannel( + Channel.FOREGROUND, + "Gotify foreground notification", + NotificationManager.IMPORTANCE_LOW + ) + foreground.setShowBadge(false) + + val messagesImportanceMin = NotificationChannel( + Channel.MESSAGES_IMPORTANCE_MIN, + "Min priority messages (<1)", + NotificationManager.IMPORTANCE_MIN + ) + + val messagesImportanceLow = NotificationChannel( + Channel.MESSAGES_IMPORTANCE_LOW, + "Low priority messages (1-3)", + NotificationManager.IMPORTANCE_LOW + ) + + val messagesImportanceDefault = NotificationChannel( + Channel.MESSAGES_IMPORTANCE_DEFAULT, + "Normal priority messages (4-7)", + NotificationManager.IMPORTANCE_DEFAULT + ) + messagesImportanceDefault.enableLights(true) + messagesImportanceDefault.lightColor = Color.CYAN + messagesImportanceDefault.enableVibration(true) + + val messagesImportanceHigh = NotificationChannel( + Channel.MESSAGES_IMPORTANCE_HIGH, + "High priority messages (>7)", + NotificationManager.IMPORTANCE_HIGH + ) + messagesImportanceHigh.enableLights(true) + messagesImportanceHigh.lightColor = Color.CYAN + messagesImportanceHigh.enableVibration(true) + + notificationManager.createNotificationChannel(foreground) + notificationManager.createNotificationChannel(messagesImportanceMin) + notificationManager.createNotificationChannel(messagesImportanceLow) + notificationManager.createNotificationChannel(messagesImportanceDefault) + notificationManager.createNotificationChannel(messagesImportanceHigh) + } catch (e: Exception) { + Log.e("Could not create channel", e) + } + } + + /** + * Map {@link com.github.gotify.client.model.Message#getPriority() Gotify message priorities to + * Android channels. + * + *
+     * Gotify Priority  | Android Importance
+     * <= 0             | min
+     * 1-3              | low
+     * 4-7              | default
+     * >= 8             | high
+     * 
+ * + * @param priority the Gotify priority to convert to a notification channel as a long. + * @return the identifier of the notification channel as a String. + */ + fun convertPriorityToChannel(priority: Long): String { + return if (priority < 1) { + Channel.MESSAGES_IMPORTANCE_MIN + } else if (priority < 4) { + Channel.MESSAGES_IMPORTANCE_LOW + } else if (priority < 8) { + Channel.MESSAGES_IMPORTANCE_DEFAULT + } else { + Channel.MESSAGES_IMPORTANCE_HIGH + } + } + + object Group { + const val MESSAGES = "GOTIFY_GROUP_MESSAGES" + } + + object Channel { + const val FOREGROUND = "gotify_foreground" + const val MESSAGES_IMPORTANCE_MIN = "gotify_messages_min_importance" + const val MESSAGES_IMPORTANCE_LOW = "gotify_messages_low_importance" + const val MESSAGES_IMPORTANCE_DEFAULT = "gotify_messages_default_importance" + const val MESSAGES_IMPORTANCE_HIGH = "gotify_messages_high_importance" + } + + object ID { + const val FOREGROUND = -1 + const val GROUPED = -2 + } +} diff --git a/app/src/main/java/com/github/gotify/SSLSettings.java b/app/src/main/java/com/github/gotify/SSLSettings.java deleted file mode 100644 index cb8c4a6..0000000 --- a/app/src/main/java/com/github/gotify/SSLSettings.java +++ /dev/null @@ -1,11 +0,0 @@ -package com.github.gotify; - -public class SSLSettings { - public boolean validateSSL; - public String cert; - - public SSLSettings(boolean validateSSL, String cert) { - this.validateSSL = validateSSL; - this.cert = cert; - } -} diff --git a/app/src/main/java/com/github/gotify/SSLSettings.kt b/app/src/main/java/com/github/gotify/SSLSettings.kt new file mode 100644 index 0000000..297bcf1 --- /dev/null +++ b/app/src/main/java/com/github/gotify/SSLSettings.kt @@ -0,0 +1,3 @@ +package com.github.gotify + +class SSLSettings(val validateSSL: Boolean, val cert: String) diff --git a/app/src/main/java/com/github/gotify/Settings.java b/app/src/main/java/com/github/gotify/Settings.java deleted file mode 100644 index 14139ff..0000000 --- a/app/src/main/java/com/github/gotify/Settings.java +++ /dev/null @@ -1,82 +0,0 @@ -package com.github.gotify; - -import android.content.Context; -import android.content.SharedPreferences; -import com.github.gotify.client.model.User; - -public class Settings { - private final SharedPreferences sharedPreferences; - - public Settings(Context context) { - sharedPreferences = context.getSharedPreferences("gotify", Context.MODE_PRIVATE); - } - - public void url(String url) { - sharedPreferences.edit().putString("url", url).apply(); - } - - public String url() { - return sharedPreferences.getString("url", null); - } - - public boolean tokenExists() { - return token() != null; - } - - public String token() { - return sharedPreferences.getString("token", null); - } - - public void token(String token) { - sharedPreferences.edit().putString("token", token).apply(); - } - - public void clear() { - url(null); - token(null); - validateSSL(true); - cert(null); - } - - public void user(String name, boolean admin) { - sharedPreferences.edit().putString("username", name).putBoolean("admin", admin).apply(); - } - - public User user() { - String username = sharedPreferences.getString("username", null); - boolean admin = sharedPreferences.getBoolean("admin", false); - if (username != null) { - return new User().name(username).admin(admin); - } else { - return new User().name("UNKNOWN").admin(false); - } - } - - public String serverVersion() { - return sharedPreferences.getString("version", "UNKNOWN"); - } - - public void serverVersion(String version) { - sharedPreferences.edit().putString("version", version).apply(); - } - - private boolean validateSSL() { - return sharedPreferences.getBoolean("validateSSL", true); - } - - public void validateSSL(boolean validateSSL) { - sharedPreferences.edit().putBoolean("validateSSL", validateSSL).apply(); - } - - private String cert() { - return sharedPreferences.getString("cert", null); - } - - public void cert(String cert) { - sharedPreferences.edit().putString("cert", cert).apply(); - } - - public SSLSettings sslSettings() { - return new SSLSettings(validateSSL(), cert()); - } -} diff --git a/app/src/main/java/com/github/gotify/Settings.kt b/app/src/main/java/com/github/gotify/Settings.kt new file mode 100644 index 0000000..e68d48e --- /dev/null +++ b/app/src/main/java/com/github/gotify/Settings.kt @@ -0,0 +1,56 @@ +package com.github.gotify + +import android.content.Context +import android.content.SharedPreferences +import com.github.gotify.client.model.User + +class Settings(context: Context) { + private val sharedPreferences: SharedPreferences + var url: String + get() = sharedPreferences.getString("url", "")!! + set(value) = sharedPreferences.edit().putString("url", value).apply() + var token: String + get() = sharedPreferences.getString("token", "")!! + set(value) = sharedPreferences.edit().putString("token", value).apply() + var user: User? = null + get() { + val username = sharedPreferences.getString("username", null) + val admin = sharedPreferences.getBoolean("admin", false) + return if (username != null) { + User().name(username).admin(admin) + } else { + User().name("UNKNOWN").admin(false) + } + } + private set + var serverVersion: String + get() = sharedPreferences.getString("version", "UNKNOWN")!! + set(value) = sharedPreferences.edit().putString("version", value).apply() + var cert: String + get() = sharedPreferences.getString("cert", "")!! + set(value) = sharedPreferences.edit().putString("cert", value).apply() + var validateSSL: Boolean + get() = sharedPreferences.getBoolean("validateSSL", true) + set(value) = sharedPreferences.edit().putBoolean("validateSSL", value).apply() + + init { + sharedPreferences = context.getSharedPreferences("gotify", Context.MODE_PRIVATE) + } + + fun tokenExists(): Boolean = token.isNotEmpty() + + fun clear() { + url = "" + token = "" + validateSSL = true + cert = "" + } + + fun setUser(name: String?, admin: Boolean) { + sharedPreferences.edit().putString("username", name).putBoolean("admin", admin).apply() + } + + fun sslSettings(): SSLSettings { + return SSLSettings(validateSSL, cert) + } +} diff --git a/app/src/main/java/com/github/gotify/Utils.java b/app/src/main/java/com/github/gotify/Utils.java deleted file mode 100644 index 2a3dd48..0000000 --- a/app/src/main/java/com/github/gotify/Utils.java +++ /dev/null @@ -1,110 +0,0 @@ -package com.github.gotify; - -import android.app.Activity; -import android.content.res.Resources; -import android.graphics.Bitmap; -import android.graphics.drawable.BitmapDrawable; -import android.graphics.drawable.Drawable; -import android.text.format.DateUtils; -import android.view.View; -import androidx.annotation.NonNull; -import com.github.gotify.client.JSON; -import com.github.gotify.log.Log; -import com.google.android.material.snackbar.Snackbar; -import com.google.gson.Gson; -import com.squareup.picasso.Picasso; -import com.squareup.picasso.Target; -import java.io.BufferedReader; -import java.io.IOException; -import java.io.InputStream; -import java.io.InputStreamReader; -import java.net.MalformedURLException; -import java.net.URI; -import java.net.URISyntaxException; -import java.net.URL; -import okio.Buffer; -import org.threeten.bp.OffsetDateTime; - -public class Utils { - public static final Gson JSON = new JSON().getGson(); - - public static void showSnackBar(Activity activity, String message) { - View rootView = activity.getWindow().getDecorView().findViewById(android.R.id.content); - Snackbar.make(rootView, message, Snackbar.LENGTH_SHORT).show(); - } - - public static int longToInt(long value) { - return (int) (value % Integer.MAX_VALUE); - } - - public static String dateToRelative(OffsetDateTime data) { - long time = data.toInstant().toEpochMilli(); - long now = System.currentTimeMillis(); - return DateUtils.getRelativeTimeSpanString(time, now, DateUtils.MINUTE_IN_MILLIS) - .toString(); - } - - public static String resolveAbsoluteUrl(String baseURL, String target) { - if (target == null) { - return null; - } - try { - URI targetUri = new URI(target); - if (targetUri.isAbsolute()) { - return target; - } - return new URL(new URL(baseURL), target).toString(); - } catch (MalformedURLException | URISyntaxException e) { - Log.e("Could not resolve absolute url", e); - return target; - } - } - - public static Target toDrawable(Resources resources, DrawableReceiver drawableReceiver) { - return new Target() { - @Override - public void onBitmapLoaded(Bitmap bitmap, Picasso.LoadedFrom from) { - drawableReceiver.loaded(new BitmapDrawable(resources, bitmap)); - } - - @Override - public void onBitmapFailed(Exception e, Drawable errorDrawable) { - Log.e("Bitmap failed", e); - } - - @Override - public void onPrepareLoad(Drawable placeHolderDrawable) {} - }; - } - - public static String readFileFromStream(@NonNull InputStream inputStream) { - StringBuilder sb = new StringBuilder(); - String currentLine; - - try (BufferedReader reader = new BufferedReader(new InputStreamReader(inputStream))) { - while ((currentLine = reader.readLine()) != null) { - sb.append(currentLine).append("\n"); - } - } catch (IOException e) { - throw new IllegalArgumentException("failed to read input"); - } - - return sb.toString(); - } - - public interface DrawableReceiver { - void loaded(Drawable drawable); - } - - public static InputStream stringToInputStream(String str) { - if (str == null) return null; - return new Buffer().writeUtf8(str).inputStream(); - } - - public static T first(T[] data) { - if (data.length != 1) { - throw new IllegalArgumentException("must be one element"); - } - return data[0]; - } -} diff --git a/app/src/main/java/com/github/gotify/Utils.kt b/app/src/main/java/com/github/gotify/Utils.kt new file mode 100644 index 0000000..a6e9e10 --- /dev/null +++ b/app/src/main/java/com/github/gotify/Utils.kt @@ -0,0 +1,101 @@ +package com.github.gotify + +import android.app.Activity +import android.content.res.Resources +import android.graphics.Bitmap +import android.graphics.drawable.BitmapDrawable +import android.graphics.drawable.Drawable +import android.text.format.DateUtils +import android.view.View +import com.github.gotify.client.JSON +import com.github.gotify.log.Log +import com.google.android.material.snackbar.Snackbar +import com.google.gson.Gson +import com.squareup.picasso.Picasso.LoadedFrom +import com.squareup.picasso.Target +import okio.Buffer +import org.threeten.bp.OffsetDateTime +import java.io.BufferedReader +import java.io.IOException +import java.io.InputStream +import java.io.InputStreamReader +import java.net.MalformedURLException +import java.net.URI +import java.net.URISyntaxException +import java.net.URL + +object Utils { + val JSON: Gson = JSON().gson + + fun showSnackBar(activity: Activity, message: String?) { + val rootView = activity.window.decorView.findViewById(R.id.content) + Snackbar.make(rootView, message!!, Snackbar.LENGTH_SHORT).show() + } + + fun longToInt(value: Long): Int { + return (value % Int.MAX_VALUE).toInt() + } + + fun dateToRelative(data: OffsetDateTime): String { + val time = data.toInstant().toEpochMilli() + val now = System.currentTimeMillis() + return DateUtils.getRelativeTimeSpanString(time, now, DateUtils.MINUTE_IN_MILLIS) + .toString() + } + + fun resolveAbsoluteUrl(baseURL: String?, target: String?): String? { + return if (target == null) { + null + } else try { + val targetUri = URI(target) + if (targetUri.isAbsolute) { + target + } else URL(URL(baseURL), target).toString() + } catch (e: MalformedURLException) { + Log.e("Could not resolve absolute url", e) + target + } catch (e: URISyntaxException) { + Log.e("Could not resolve absolute url", e) + target + } + } + + fun toDrawable(resources: Resources?, drawableReceiver: DrawableReceiver): Target { + return object : Target { + override fun onBitmapLoaded(bitmap: Bitmap, from: LoadedFrom) { + drawableReceiver.loaded(BitmapDrawable(resources, bitmap)) + } + + override fun onBitmapFailed(e: Exception, errorDrawable: Drawable) { + Log.e("Bitmap failed", e) + } + + override fun onPrepareLoad(placeHolderDrawable: Drawable) {} + } + } + + fun readFileFromStream(inputStream: InputStream): String { + val sb = StringBuilder() + var currentLine: String? + try { + BufferedReader(InputStreamReader(inputStream)).use { reader -> + while (reader.readLine().also { + currentLine = it + } != null) { + sb.append(currentLine).append("\n") + } + } + } catch (e: IOException) { + throw IllegalArgumentException("failed to read input") + } + return sb.toString() + } + + fun stringToInputStream(str: String?): InputStream? { + return if (str == null) null else Buffer().writeUtf8(str).inputStream() + } + + fun interface DrawableReceiver { + fun loaded(drawable: Drawable?) + } +}