Export themes with hex colors by default. Read either int colors or hex colors on import. (#1289)

This commit is contained in:
cmp 2023-03-10 23:00:58 -06:00 committed by GitHub
parent 34cb71f707
commit abb9acb4d8
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
2 changed files with 94 additions and 7 deletions

View File

@ -1,7 +1,5 @@
package ml.docilealligator.infinityforreddit.activities;
import static android.content.ClipDescription.MIMETYPE_TEXT_PLAIN;
import android.content.ClipData;
import android.content.ClipboardManager;
import android.content.Context;
@ -27,8 +25,7 @@ import com.google.android.material.appbar.CollapsingToolbarLayout;
import com.google.android.material.dialog.MaterialAlertDialogBuilder;
import com.google.android.material.floatingactionbutton.FloatingActionButton;
import com.google.android.material.snackbar.Snackbar;
import com.google.gson.Gson;
import com.google.gson.JsonSyntaxException;
import com.google.gson.JsonParseException;
import org.greenrobot.eventbus.EventBus;
import org.greenrobot.eventbus.Subscribe;
@ -272,9 +269,9 @@ public class CustomThemeListingActivity extends BaseActivity implements
String json = item.coerceToText(this.getApplicationContext()).toString();
if (!TextUtils.isEmpty(json)) {
try {
CustomTheme customTheme = new Gson().fromJson(json, CustomTheme.class);
CustomTheme customTheme = CustomTheme.fromJson(json);
checkDuplicateAndImportTheme(customTheme, true);
} catch (JsonSyntaxException e) {
} catch (JsonParseException e) {
Snackbar.make(coordinatorLayout, R.string.parse_theme_failed, Snackbar.LENGTH_SHORT).show();
}
} else {

View File

@ -1,13 +1,26 @@
package ml.docilealligator.infinityforreddit.customtheme;
import android.graphics.Color;
import androidx.annotation.NonNull;
import androidx.room.ColumnInfo;
import androidx.room.Entity;
import androidx.room.PrimaryKey;
import com.google.gson.Gson;
import com.google.gson.GsonBuilder;
import com.google.gson.JsonDeserializationContext;
import com.google.gson.JsonDeserializer;
import com.google.gson.JsonElement;
import com.google.gson.JsonObject;
import com.google.gson.JsonParseException;
import com.google.gson.JsonSerializationContext;
import com.google.gson.JsonSerializer;
import java.lang.reflect.Field;
import java.lang.reflect.Type;
import java.util.ArrayList;
import java.util.Map;
@Entity(tableName = "custom_themes")
public class CustomTheme {
@ -197,10 +210,22 @@ public class CustomTheme {
}
public String getJSONModel() {
Gson gson = new Gson();
Gson gson = getGsonBuilder().create();
return gson.toJson(this);
}
private static GsonBuilder getGsonBuilder() {
GsonBuilder builder = new GsonBuilder();
builder.registerTypeAdapter(CustomTheme.class, new CustomThemeSerializer());
builder.registerTypeAdapter(CustomTheme.class, new CustomThemeDeserializer());
return builder;
}
public static CustomTheme fromJson(String json) throws JsonParseException {
Gson gson = getGsonBuilder().create();
return gson.fromJson(json, CustomTheme.class);
}
public static CustomTheme convertSettingsItemsToCustomTheme(ArrayList<CustomThemeSettingsItem> customThemeSettingsItems, String themeName) {
CustomTheme customTheme = new CustomTheme(themeName);
@ -298,4 +323,69 @@ public class CustomTheme {
return customTheme;
}
private static class CustomThemeSerializer implements JsonSerializer<CustomTheme> {
@Override
public JsonElement serialize(CustomTheme src, Type typeofSrc, JsonSerializationContext context) {
JsonObject obj = new JsonObject();
for (Field field : src.getClass().getDeclaredFields()) {
try {
if (field.getType() == int.class) {
obj.addProperty(field.getName(), String.format("#%08X", field.getInt(src)));
} else {
obj.add(field.getName(), context.serialize(field.get(src)));
}
} catch (IllegalAccessException ignored) {
}
}
return obj;
}
}
private static class CustomThemeDeserializer implements JsonDeserializer<CustomTheme> {
@Override
public CustomTheme deserialize(JsonElement json, Type typeOfT, JsonDeserializationContext context) throws JsonParseException {
CustomTheme customTheme = new CustomTheme();
JsonObject obj = json.getAsJsonObject();
for (Map.Entry<String, JsonElement> entry : obj.entrySet()) {
Field field;
try {
field = customTheme.getClass().getDeclaredField(entry.getKey());
} catch (NoSuchFieldException e) {
// Field not found, skip
continue;
}
JsonElement value = entry.getValue();
try {
Class<?> type = field.getType();
if (int.class.equals(type)) {
if (value.getAsJsonPrimitive().isString()) {
// Hex or text color string
field.set(customTheme, Color.parseColor(value.getAsString()));
} else {
// Int color
field.set(customTheme, value.getAsInt());
}
} else if (String.class.equals(type)) {
field.set(customTheme, value.getAsString());
} else if (boolean.class.equals(type)) {
field.set(customTheme, value.getAsBoolean());
}
} catch (IllegalAccessException e) {
throw new JsonParseException("Failed to access theme field.");
} catch (IllegalArgumentException e) {
throw new JsonParseException("Invalid color string.");
}
}
return customTheme;
}
}
}