Refactor wp (#944)
* Extract couple filters to separate classes * Move ImageEffects to separate file * Refactor effects to use bitmap * Reformat code, extract last batch of effects to classes * Shitty intermediate refactor * Still intermediate sh**, buildable btw * More refactoring, still looks disgusting, but a bit better) * Add fixme about order * Remove unused stuff * Remove unused code, prevent re-creating of drawable * Refactor img effects to native * Add native lib sources * Implement Dim, Mosaic and Blur in native * Add pre-built libs * Get rid of filter abstraction * Include native build * Force rust toolchains * Fix typos * Comment not used smali * Simplify wallpapers handling * Fixes after main merge * Minor fixes, add prebuilt lib, disable auto re-builds for native * Fix missed copyscpec for native builds * Fix entry for dim effect * Fix resizing to respect current image dimensions * Wtf? who stole NDK from actions * Learning GH actions I don't want to read the docs * Revert "Learning GH actions" This reverts commitf6f9a97d10. * Revert "Wtf? who stole NDK from actions" This reverts commit1d0f1b8879. * Try out latest LTS just why not --------- Co-authored-by: saoq <wfmfe@ya.ru>
This commit is contained in:
@@ -37,6 +37,8 @@ jobs:
|
||||
sudo apt install zipalign
|
||||
chmod +x scripts/apktool.jar
|
||||
chmod +x scripts/apksigner.jar
|
||||
rustup target add armv7-linux-androideabi
|
||||
rustup target add aarch64-linux-android
|
||||
|
||||
- name: Build VTLite
|
||||
run: |
|
||||
|
||||
+23
-1
@@ -7,6 +7,16 @@ import java.util.zip.ZipInputStream
|
||||
plugins {
|
||||
id 'com.android.application'
|
||||
id 'net.nemerosa.versioning' version '2.15.1'
|
||||
id 'org.mozilla.rust-android-gradle.rust-android'
|
||||
}
|
||||
|
||||
cargo {
|
||||
profile = 'release'
|
||||
module = '../native-effects'
|
||||
libname = 'native-effects'
|
||||
targets = ["arm", "arm64"]
|
||||
prebuiltToolchains = true
|
||||
pythonCommand = "python3"
|
||||
}
|
||||
|
||||
def smaliFolder = projectDir.toPath().resolve("../smali").normalize()
|
||||
@@ -100,6 +110,7 @@ android {
|
||||
targetCompatibility JavaVersion.VERSION_14
|
||||
}
|
||||
namespace 'ru.vtosters.lite'
|
||||
ndkVersion '25.2.9519653'
|
||||
}
|
||||
|
||||
dependencies {
|
||||
@@ -112,6 +123,8 @@ dependencies {
|
||||
|
||||
task prepareDexForMerge(type: Copy) {
|
||||
dependsOn('exportDex')
|
||||
// Remove comment for native lib build
|
||||
dependsOn('cargoBuild')
|
||||
into smaliFolder.toString()
|
||||
from(projectDir) {
|
||||
include 'classes6.dex'
|
||||
@@ -119,7 +132,16 @@ task prepareDexForMerge(type: Copy) {
|
||||
}
|
||||
from(projectDir) {
|
||||
include 'version.properties'
|
||||
into("assets")
|
||||
into 'assets'
|
||||
}
|
||||
// Remove comment for native lib build
|
||||
from('../native-effects/target/aarch64-linux-android/release'){
|
||||
include 'libnative_effects.so'
|
||||
into 'lib/arm64-v8a'
|
||||
}
|
||||
from('../native-effects/target/armv7-linux-androideabi/release'){
|
||||
include 'libnative_effects.so'
|
||||
into 'lib/armeabi-v7a'
|
||||
}
|
||||
doLast {
|
||||
new File(projectDir, "classes6.dex").delete()
|
||||
|
||||
@@ -0,0 +1,245 @@
|
||||
package ru.vtosters.lite.ui.wallpapers;
|
||||
|
||||
import androidx.annotation.NonNull;
|
||||
import androidx.annotation.Nullable;
|
||||
import com.vtosters.lite.R;
|
||||
import ru.vtosters.lite.utils.AndroidUtils;
|
||||
|
||||
import java.nio.ByteBuffer;
|
||||
|
||||
import static ru.vtosters.lite.utils.AndroidUtils.getGlobalContext;
|
||||
import static ru.vtosters.lite.utils.AndroidUtils.getPreferences;
|
||||
|
||||
enum ImageEffects {
|
||||
Blur(true,
|
||||
AndroidUtils.getArray(R.array.filter_types),
|
||||
new String[]{"disabled", "low", "med", "high"},
|
||||
getGlobalContext().getString(R.string.filter_blur)
|
||||
) {
|
||||
@Override
|
||||
public void applyEffect(ByteBuffer bitmap, int height, int width) {
|
||||
int radius;
|
||||
switch (getPreferences().getString(ImageEffects.Blur.toString(), "disabled")) {
|
||||
case "low":
|
||||
radius = 8;
|
||||
break;
|
||||
case "med":
|
||||
radius = 14;
|
||||
break;
|
||||
case "high":
|
||||
radius = 20;
|
||||
break;
|
||||
default:
|
||||
return;
|
||||
}
|
||||
NativeEffects.gaussian(bitmap, height, width, radius);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getSummary() {
|
||||
switch (getPreferences().getString(ImageEffects.Blur.toString(), "disabled")) {
|
||||
case "low":
|
||||
return AndroidUtils.getString(R.string.wallpapers_low);
|
||||
case "med":
|
||||
return AndroidUtils.getString(R.string.wallpapers_med);
|
||||
case "high":
|
||||
return AndroidUtils.getString(R.string.wallpapers_high);
|
||||
default:
|
||||
return AndroidUtils.getString(R.string.wallpapers_disabled);
|
||||
}
|
||||
}
|
||||
},
|
||||
Dim(true,
|
||||
AndroidUtils.getArray(R.array.filter_dim_types),
|
||||
new String[]{"disabled", "dim_black", "dim_white"},
|
||||
getGlobalContext().getString(R.string.filter_dim)) {
|
||||
@Override
|
||||
public void applyEffect(ByteBuffer bitmap, int height, int width) {
|
||||
var delta = 0;
|
||||
switch (getPreferences().getString(ImageEffects.Dim.toString(), "disabled")) {
|
||||
case "dim_black":
|
||||
delta = -50; break;
|
||||
case "dim_white":
|
||||
delta = 50; break;
|
||||
default:
|
||||
return;
|
||||
}
|
||||
NativeEffects.dim(bitmap, height, width, delta);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getSummary() {
|
||||
switch (getPreferences().getString(ImageEffects.Dim.toString(), "disabled")) {
|
||||
case "dim_black":
|
||||
return AndroidUtils.getString(R.string.wallpapers_dim_black);
|
||||
case "dim_white":
|
||||
return AndroidUtils.getString(R.string.wallpapers_dim_white);
|
||||
default:
|
||||
return AndroidUtils.getString(R.string.wallpapers_disabled);
|
||||
}
|
||||
}
|
||||
},
|
||||
Mosaic(true,
|
||||
AndroidUtils.getArray(R.array.filter_types),
|
||||
new String[]{"disabled", "low", "med", "high"},
|
||||
getGlobalContext().getString(R.string.filter_mosaic)) {
|
||||
@Override
|
||||
public void applyEffect(ByteBuffer bitmap, int height, int width) {
|
||||
var scale = 0;
|
||||
switch (getPreferences().getString(ImageEffects.Mosaic.toString(), "disabled")) {
|
||||
case "high":
|
||||
scale = 50; break;
|
||||
case "med":
|
||||
scale = 25; break;
|
||||
case "low":
|
||||
scale = 10; break;
|
||||
default:
|
||||
return;
|
||||
}
|
||||
NativeEffects.mosaic(bitmap, height, width, scale);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getSummary() {
|
||||
switch (getPreferences().getString(ImageEffects.Mosaic.toString(), "disabled")) {
|
||||
case "low":
|
||||
return AndroidUtils.getString(R.string.wallpapers_low);
|
||||
case "med":
|
||||
return AndroidUtils.getString(R.string.wallpapers_med);
|
||||
case "high":
|
||||
return AndroidUtils.getString(R.string.wallpapers_high);
|
||||
default:
|
||||
return AndroidUtils.getString(R.string.wallpapers_disabled);
|
||||
}
|
||||
}
|
||||
},
|
||||
Monochrome(false, null, null,
|
||||
getGlobalContext().getString(R.string.filter_monochrome)) {
|
||||
@Override
|
||||
public void applyEffect(ByteBuffer bitmap, int height, int width) {
|
||||
if (isApplied()) {
|
||||
NativeEffects.monochrome(bitmap);
|
||||
}
|
||||
}
|
||||
},
|
||||
Invert(false, null, null,
|
||||
getGlobalContext().getString(R.string.filter_invert_colors)) {
|
||||
@Override
|
||||
public void applyEffect(ByteBuffer bitmap, int height, int width) {
|
||||
if (isApplied()) {
|
||||
NativeEffects.invert(bitmap);
|
||||
}
|
||||
}
|
||||
},
|
||||
Sepia(false, null, null,
|
||||
getGlobalContext().getString(R.string.filter_sepia)) {
|
||||
@Override
|
||||
public void applyEffect(ByteBuffer bitmap, int height, int width) {
|
||||
if (isApplied()) {
|
||||
NativeEffects.sepia(bitmap);
|
||||
}
|
||||
}
|
||||
},
|
||||
Emboss(false, null, null,
|
||||
getGlobalContext().getString(R.string.filter_emboss)) {
|
||||
@Override
|
||||
public String getSummary() {
|
||||
return getGlobalContext().getString(R.string.filter_maybe_lag);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void applyEffect(ByteBuffer bitmap, int height, int width) {
|
||||
if (isApplied()) {
|
||||
NativeEffects.emboss(bitmap, height, width);
|
||||
}
|
||||
}
|
||||
},
|
||||
Engrave(false, null, null,
|
||||
getGlobalContext().getString(R.string.filter_engrave)) {
|
||||
@Override
|
||||
public String getSummary() {
|
||||
return getGlobalContext().getString(R.string.filter_maybe_lag);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void applyEffect(ByteBuffer bitmap, int height, int width) {
|
||||
if (isApplied()) {
|
||||
NativeEffects.engrave(bitmap, height, width);
|
||||
}
|
||||
}
|
||||
},
|
||||
Flea(false, null, null,
|
||||
getGlobalContext().getString(R.string.filter_flea)) {
|
||||
@Override
|
||||
public void applyEffect(ByteBuffer bitmap, int height, int width) {
|
||||
if (isApplied()) {
|
||||
NativeEffects.flea(bitmap);
|
||||
}
|
||||
}
|
||||
},
|
||||
Snow(false, null, null,
|
||||
getGlobalContext().getString(R.string.filter_snow)) {
|
||||
@Override
|
||||
public void applyEffect(ByteBuffer bitmap, int height, int width) {
|
||||
if (isApplied()){
|
||||
NativeEffects.snow(bitmap);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
private final boolean free;
|
||||
private final String title;
|
||||
@Nullable
|
||||
private final String[] entryValues;
|
||||
@Nullable
|
||||
private final String[] entries;
|
||||
|
||||
ImageEffects(boolean free, @Nullable String[] entries, @Nullable String[] entryValues, String title) {
|
||||
this.free = free;
|
||||
this.entries = entries;
|
||||
this.entryValues = entryValues;
|
||||
this.title = title;
|
||||
}
|
||||
|
||||
public String getTitle() {
|
||||
return title;
|
||||
}
|
||||
|
||||
public Boolean isSwitch() {
|
||||
return entryValues == null || entryValues.length == 0;
|
||||
}
|
||||
|
||||
public Boolean isList() {
|
||||
return entryValues != null && entryValues.length > 0;
|
||||
}
|
||||
|
||||
public boolean isFree() {
|
||||
return free;
|
||||
}
|
||||
|
||||
@Nullable
|
||||
public String[] getEntries() {
|
||||
return entries;
|
||||
}
|
||||
|
||||
@Nullable
|
||||
public String[] getEntryValues() {
|
||||
return entryValues;
|
||||
}
|
||||
|
||||
public String getSummary() {
|
||||
return "";
|
||||
}
|
||||
|
||||
public abstract void applyEffect(ByteBuffer bitmap, int height, int width);
|
||||
|
||||
protected boolean isApplied() {
|
||||
return getPreferences().getBoolean(this.toString(), false);
|
||||
}
|
||||
|
||||
@NonNull
|
||||
@Override
|
||||
public String toString() {
|
||||
return "msg_" + super.toString();
|
||||
}
|
||||
}
|
||||
@@ -1,351 +1,37 @@
|
||||
package ru.vtosters.lite.ui.wallpapers;
|
||||
|
||||
import static ru.vtosters.lite.utils.AndroidUtils.getPreferences;
|
||||
import static ru.vtosters.lite.utils.AndroidUtils.getResources;
|
||||
import static ru.vtosters.lite.utils.Preferences.hasVerification;
|
||||
|
||||
import android.graphics.Bitmap;
|
||||
import android.graphics.Canvas;
|
||||
import android.graphics.Color;
|
||||
import android.graphics.ColorFilter;
|
||||
import android.graphics.LightingColorFilter;
|
||||
import android.graphics.Matrix;
|
||||
import android.graphics.Paint;
|
||||
import android.graphics.drawable.BitmapDrawable;
|
||||
import android.graphics.drawable.Drawable;
|
||||
import android.util.Log;
|
||||
|
||||
import com.vk.medianative.MediaNative;
|
||||
|
||||
import java.util.Random;
|
||||
import java.nio.ByteBuffer;
|
||||
import java.nio.ByteOrder;
|
||||
|
||||
public class ImageFilters {
|
||||
public static final int COLOR_MAX = 0xFF;
|
||||
|
||||
public static Drawable getFilteredDrawable(Drawable orig) {
|
||||
if (orig == null) return null;
|
||||
if (!(orig instanceof BitmapDrawable)) return orig;
|
||||
|
||||
if (!getPreferences().getString("msg_blur_radius", "disabled").equals("disabled")) {
|
||||
orig = getBlurredWallpaper(orig, getRadius());
|
||||
Bitmap bitmap = ((BitmapDrawable) orig).getBitmap();
|
||||
if (bitmap.getConfig() != Bitmap.Config.ARGB_8888) {
|
||||
bitmap = bitmap.copy(Bitmap.Config.ARGB_8888, true);
|
||||
}
|
||||
|
||||
if (!getPreferences().getString("msg_dim", "off").equals("off")) {
|
||||
orig = getDimmed(orig);
|
||||
var directBuff = ByteBuffer.allocateDirect(bitmap.getByteCount());
|
||||
directBuff.order(ByteOrder.nativeOrder());
|
||||
bitmap.copyPixelsToBuffer(directBuff);
|
||||
|
||||
// FIXME: preserve order of filters
|
||||
// e.g. user turned invert first then mosaic then monochrome
|
||||
// invocation here happens regardless of that order
|
||||
for (var type : ImageEffects.values()) {
|
||||
type.applyEffect(directBuff, bitmap.getHeight(), bitmap.getWidth());
|
||||
}
|
||||
|
||||
if (!getPreferences().getString("msg_mosaic", "disabled").equals("disabled")) {
|
||||
orig = getMosaic(orig);
|
||||
}
|
||||
|
||||
if (!hasVerification()) {
|
||||
return orig;
|
||||
}
|
||||
|
||||
if (getPreferences().getBoolean("msg_monochrome", false)) {
|
||||
orig = getMonochrome(orig);
|
||||
}
|
||||
|
||||
Bitmap bm;
|
||||
|
||||
if (orig != null) {
|
||||
bm = ((BitmapDrawable) orig).getBitmap();
|
||||
} else {
|
||||
return null;
|
||||
}
|
||||
|
||||
Bitmap instance = bm.copy(Bitmap.Config.ARGB_8888, true);
|
||||
|
||||
if (getPreferences().getBoolean("msg_invert", false)) {
|
||||
instance = applyInvertEffect(instance);
|
||||
}
|
||||
|
||||
if (getPreferences().getBoolean("msg_sepia", false)) {
|
||||
instance = applySepiaEffect(instance);
|
||||
}
|
||||
|
||||
if (getPreferences().getBoolean("msg_emboss", false)) {
|
||||
instance = applyEmbossEffect(instance);
|
||||
}
|
||||
|
||||
if (getPreferences().getBoolean("msg_engrave", false)) {
|
||||
instance = applyEngraveEffect(instance);
|
||||
}
|
||||
|
||||
if (getPreferences().getBoolean("msg_flea", false)) {
|
||||
instance = applyFleaEffect(instance);
|
||||
}
|
||||
|
||||
if (getPreferences().getBoolean("msg_snow", false)) {
|
||||
instance = applySnowEffect(instance);
|
||||
}
|
||||
|
||||
return new BitmapDrawable(getResources(), instance);
|
||||
}
|
||||
|
||||
private static int getRadius() {
|
||||
String radius = getPreferences().getString("msg_blur_radius", "disabled");
|
||||
return switch (radius) {
|
||||
case "low" -> 8;
|
||||
case "med" -> 14;
|
||||
default -> 20;
|
||||
};
|
||||
}
|
||||
|
||||
public static Drawable getBlurredWallpaper(Drawable orig, int radius) {
|
||||
try {
|
||||
if (orig == null) return null;
|
||||
if (!(orig instanceof BitmapDrawable)) return orig; // we need only BitmapDrawable
|
||||
Bitmap bm = ((BitmapDrawable) orig).getBitmap();
|
||||
|
||||
Bitmap instance = bm.copy(Bitmap.Config.ARGB_8888, true);
|
||||
|
||||
MediaNative.blurBitmap(instance, radius);
|
||||
return new BitmapDrawable(getResources(), instance);
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
return orig;
|
||||
}
|
||||
}
|
||||
|
||||
public static Drawable getMosaic(Drawable orig) {
|
||||
int scale = 100;
|
||||
|
||||
if (orig == null) return null;
|
||||
if (!(orig instanceof BitmapDrawable)) return orig;
|
||||
Bitmap bm = ((BitmapDrawable) orig).getBitmap();
|
||||
|
||||
|
||||
Bitmap instance = bm.copy(Bitmap.Config.ARGB_8888, true);
|
||||
|
||||
|
||||
String radius = getPreferences().getString("msg_mosaic", "disabled");
|
||||
|
||||
switch (radius) {
|
||||
case "high" -> scale = 25;
|
||||
case "med" -> scale = 50;
|
||||
case "low" -> scale = 75;
|
||||
}
|
||||
|
||||
Bitmap temp = Bitmap.createScaledBitmap(instance, scale, scale, false);
|
||||
Bitmap mosaicBitmap = Bitmap.createScaledBitmap(temp, instance.getWidth(), instance.getHeight(), false);
|
||||
|
||||
return new BitmapDrawable(getResources(), mosaicBitmap);
|
||||
}
|
||||
|
||||
public static Drawable getDimmed(Drawable orig) {
|
||||
if (orig == null) return null;
|
||||
if (!(orig instanceof BitmapDrawable)) return orig;
|
||||
Bitmap bm = ((BitmapDrawable) orig).getBitmap();
|
||||
|
||||
Bitmap instance = bm.copy(Bitmap.Config.ARGB_8888, true);
|
||||
|
||||
String radius = getPreferences().getString("msg_dim", "disabled");
|
||||
switch (radius) {
|
||||
case "dim_black":
|
||||
darken(instance);
|
||||
case "dim_white":
|
||||
lighten(instance);
|
||||
}
|
||||
return new BitmapDrawable(getResources(), instance);
|
||||
}
|
||||
|
||||
public static Drawable getMonochrome(Drawable orig) {
|
||||
if (orig == null) return null;
|
||||
if (!(orig instanceof BitmapDrawable)) return orig;
|
||||
Bitmap bm = ((BitmapDrawable) orig).getBitmap();
|
||||
|
||||
Bitmap instance = bm.copy(Bitmap.Config.ARGB_8888, true);
|
||||
|
||||
Bitmap bwBitmap = Bitmap.createBitmap(instance.getWidth(), instance.getHeight(), Bitmap.Config.RGB_565);
|
||||
float[] hsv = new float[3];
|
||||
for (int col = 0; col < instance.getWidth(); col++) {
|
||||
for (int row = 0; row < instance.getHeight(); row++) {
|
||||
Color.colorToHSV(instance.getPixel(col, row), hsv);
|
||||
if (hsv[2] > 0.5f) {
|
||||
bwBitmap.setPixel(col, row, 0xffffffff);
|
||||
} else {
|
||||
bwBitmap.setPixel(col, row, 0xff000000);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return new BitmapDrawable(getResources(), bwBitmap);
|
||||
}
|
||||
|
||||
private static void darken(Bitmap bm) {
|
||||
try {
|
||||
Canvas canvas = new Canvas(bm);
|
||||
Paint p = new Paint(Color.RED);
|
||||
ColorFilter filter = new LightingColorFilter(0xFF7F7F7F, 0x00000000); // darken
|
||||
p.setColorFilter(filter);
|
||||
canvas.drawBitmap(bm, new Matrix(), p);
|
||||
} catch (Exception e) {
|
||||
Log.d("WallpaperD", e.getMessage());
|
||||
}
|
||||
}
|
||||
|
||||
private static void lighten(Bitmap bm) {
|
||||
try {
|
||||
Canvas canvas = new Canvas(bm);
|
||||
Paint p = new Paint(Color.RED);
|
||||
ColorFilter filter = new LightingColorFilter(0xFFFFFFFF, 0x00222222); // lighten
|
||||
p.setColorFilter(filter);
|
||||
canvas.drawBitmap(bm, new Matrix(), p);
|
||||
} catch (Exception e) {
|
||||
Log.d("WallpaperL", e.getMessage());
|
||||
}
|
||||
}
|
||||
|
||||
public static Bitmap applyInvertEffect(Bitmap src) {
|
||||
// create new bitmap with the same settings as source bitmap
|
||||
Bitmap bmOut = Bitmap.createBitmap(src.getWidth(), src.getHeight(), src.getConfig());
|
||||
// color info
|
||||
int A, R, G, B;
|
||||
int pixelColor;
|
||||
// image size
|
||||
int height = src.getHeight();
|
||||
int width = src.getWidth();
|
||||
|
||||
// scan through every pixel
|
||||
for (int y = 0; y < height; y++) {
|
||||
for (int x = 0; x < width; x++) {
|
||||
// get one pixel
|
||||
pixelColor = src.getPixel(x, y);
|
||||
// saving alpha channel
|
||||
A = Color.alpha(pixelColor);
|
||||
// inverting byte for each R/G/B channel
|
||||
R = 255 - Color.red(pixelColor);
|
||||
G = 255 - Color.green(pixelColor);
|
||||
B = 255 - Color.blue(pixelColor);
|
||||
// set newly-inverted pixel to output image
|
||||
bmOut.setPixel(x, y, Color.argb(A, R, G, B));
|
||||
}
|
||||
}
|
||||
|
||||
// return final bitmap
|
||||
return bmOut;
|
||||
}
|
||||
|
||||
public static Bitmap applySepiaEffect(Bitmap src) {
|
||||
// image size
|
||||
int width = src.getWidth();
|
||||
int height = src.getHeight();
|
||||
// create output bitmap
|
||||
Bitmap bmOut = Bitmap.createBitmap(width, height, src.getConfig());
|
||||
// constant grayscale
|
||||
final double GS_RED = 0.3;
|
||||
final double GS_GREEN = 0.59;
|
||||
final double GS_BLUE = 0.11;
|
||||
// color information
|
||||
int A, R, G, B;
|
||||
int pixel;
|
||||
|
||||
// scan through all pixels
|
||||
for (int x = 0; x < width; ++x) {
|
||||
for (int y = 0; y < height; ++y) {
|
||||
// get pixel color
|
||||
pixel = src.getPixel(x, y);
|
||||
// get color on each channel
|
||||
A = Color.alpha(pixel);
|
||||
R = Color.red(pixel);
|
||||
G = Color.green(pixel);
|
||||
B = Color.blue(pixel);
|
||||
// apply grayscale sample
|
||||
B = (int) (GS_RED * R + GS_GREEN * G + GS_BLUE * B);
|
||||
// apply intensity level for sepia tone
|
||||
R = G = B = (int) (B * 0.9);
|
||||
// set new pixel color to output bitmap
|
||||
bmOut.setPixel(x, y, Color.argb(A, R, G, B));
|
||||
}
|
||||
}
|
||||
|
||||
// return final image
|
||||
return bmOut;
|
||||
}
|
||||
|
||||
public static Bitmap applyEmbossEffect(Bitmap src) {
|
||||
double[][] EmbossConfig = new double[][]{
|
||||
{-1, 0, -1},
|
||||
{0, 4, 0},
|
||||
{-1, 0, -1}
|
||||
};
|
||||
ConvolutionMatrix convMatrix = new ConvolutionMatrix(3);
|
||||
convMatrix.applyConfig(EmbossConfig);
|
||||
convMatrix.Factor = 1;
|
||||
convMatrix.Offset = 127;
|
||||
return ConvolutionMatrix.computeConvolution3x3(src, convMatrix);
|
||||
}
|
||||
|
||||
public static Bitmap applyEngraveEffect(Bitmap src) {
|
||||
ConvolutionMatrix convMatrix = new ConvolutionMatrix(3);
|
||||
convMatrix.setAll(0);
|
||||
convMatrix.Matrix[0][0] = -2;
|
||||
convMatrix.Matrix[1][1] = 2;
|
||||
convMatrix.Factor = 1;
|
||||
convMatrix.Offset = 95;
|
||||
return ConvolutionMatrix.computeConvolution3x3(src, convMatrix);
|
||||
}
|
||||
|
||||
public static Bitmap applyFleaEffect(Bitmap source) {
|
||||
// get image size
|
||||
int width = source.getWidth();
|
||||
int height = source.getHeight();
|
||||
int[] pixels = new int[width * height];
|
||||
// get pixel array from source
|
||||
source.getPixels(pixels, 0, width, 0, 0, width, height);
|
||||
// a random object
|
||||
Random random = new Random();
|
||||
|
||||
int index;
|
||||
// iteration through pixels
|
||||
for (int y = 0; y < height; ++y) {
|
||||
for (int x = 0; x < width; ++x) {
|
||||
// get current index in 2D-matrix
|
||||
index = y * width + x;
|
||||
// get random color
|
||||
int randColor = Color.rgb(random.nextInt(COLOR_MAX),
|
||||
random.nextInt(COLOR_MAX), random.nextInt(COLOR_MAX));
|
||||
// OR
|
||||
pixels[index] |= randColor;
|
||||
}
|
||||
}
|
||||
// output bitmap
|
||||
Bitmap bmOut = Bitmap.createBitmap(width, height, source.getConfig());
|
||||
bmOut.setPixels(pixels, 0, width, 0, 0, width, height);
|
||||
return bmOut;
|
||||
}
|
||||
|
||||
public static Bitmap applySnowEffect(Bitmap source) {
|
||||
// get image size
|
||||
int width = source.getWidth();
|
||||
int height = source.getHeight();
|
||||
int[] pixels = new int[width * height];
|
||||
// get pixel array from source
|
||||
source.getPixels(pixels, 0, width, 0, 0, width, height);
|
||||
// random object
|
||||
Random random = new Random();
|
||||
|
||||
int R, G, B, index, thresHold;
|
||||
// iteration through pixels
|
||||
for (int y = 0; y < height; ++y) {
|
||||
for (int x = 0; x < width; ++x) {
|
||||
// get current index in 2D-matrix
|
||||
index = y * width + x;
|
||||
// get color
|
||||
R = Color.red(pixels[index]);
|
||||
G = Color.green(pixels[index]);
|
||||
B = Color.blue(pixels[index]);
|
||||
// generate threshold
|
||||
thresHold = random.nextInt(COLOR_MAX);
|
||||
if (R > thresHold && G > thresHold && B > thresHold) {
|
||||
pixels[index] = Color.rgb(COLOR_MAX, COLOR_MAX, COLOR_MAX);
|
||||
}
|
||||
}
|
||||
}
|
||||
// output bitmap
|
||||
Bitmap bmOut = Bitmap.createBitmap(width, height, Bitmap.Config.RGB_565);
|
||||
bmOut.setPixels(pixels, 0, width, 0, 0, width, height);
|
||||
return bmOut;
|
||||
directBuff.flip();
|
||||
bitmap.copyPixelsFromBuffer(directBuff);
|
||||
return new BitmapDrawable(getResources(), bitmap);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,22 @@
|
||||
package ru.vtosters.lite.ui.wallpapers;
|
||||
|
||||
import java.nio.ByteBuffer;
|
||||
|
||||
public class NativeEffects {
|
||||
|
||||
static {
|
||||
System.loadLibrary("native_effects");
|
||||
}
|
||||
|
||||
public static native String monochrome(ByteBuffer input);
|
||||
public static native String invert(ByteBuffer input);
|
||||
public static native String sepia(ByteBuffer input);
|
||||
public static native String emboss(ByteBuffer input, int height, int width);
|
||||
public static native String engrave(ByteBuffer input, int height, int width);
|
||||
public static native String flea(ByteBuffer input);
|
||||
public static native String snow(ByteBuffer input);
|
||||
// FIXME: slow when comparing with MediaNative.blurBitmap
|
||||
public static native String gaussian(ByteBuffer input, int height, int width, float radius);
|
||||
public static native String dim(ByteBuffer input, int height, int width, int delta);
|
||||
public static native String mosaic(ByteBuffer input, int height, int width, int scale);
|
||||
}
|
||||
@@ -7,17 +7,16 @@ import android.net.Uri;
|
||||
import android.os.Bundle;
|
||||
import android.widget.Toast;
|
||||
import androidx.annotation.Nullable;
|
||||
import androidx.preference.ListPreference;
|
||||
import com.vtosters.lite.R;
|
||||
import com.vtosters.lite.general.fragments.MaterialPreferenceToolbarFragment;
|
||||
import com.vtosters.lite.im.ImEngineProvider;
|
||||
import ru.vtosters.lite.ui.PreferenceFragmentUtils;
|
||||
import ru.vtosters.lite.utils.AndroidUtils;
|
||||
|
||||
import java.io.FileOutputStream;
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.io.OutputStream;
|
||||
import java.util.Arrays;
|
||||
|
||||
import static ru.vtosters.lite.ui.wallpapers.WallpapersHooks.*;
|
||||
import static ru.vtosters.lite.utils.AndroidUtils.edit;
|
||||
@@ -29,7 +28,6 @@ public class WallpaperMenuFragment extends MaterialPreferenceToolbarFragment {
|
||||
private WallpaperPreferences mWPPreviewPref;
|
||||
|
||||
public static void copyStream(InputStream copyFrom, OutputStream copyTo) throws IOException {
|
||||
|
||||
byte[] buffer = new byte[1024];
|
||||
int length;
|
||||
while ((length = copyFrom.read(buffer)) > 0) {
|
||||
@@ -47,146 +45,117 @@ public class WallpaperMenuFragment extends MaterialPreferenceToolbarFragment {
|
||||
|
||||
addPreferencesFromResource(R.xml.empty);
|
||||
|
||||
PreferenceFragmentUtils.addPreferenceCategory(getPreferenceScreen(), requireContext().getString(R.string.vkim_settings_appearance_chat_preview_title));
|
||||
PreferenceFragmentUtils.addPreferenceCategory(
|
||||
getPreferenceScreen(),
|
||||
requireContext().getString(R.string.vkim_settings_appearance_chat_preview_title)
|
||||
);
|
||||
|
||||
mWPPreviewPref = new WallpaperPreferences(getContext());
|
||||
mWPPreviewPref.setIcon(null);
|
||||
mWPPreviewPref.setIconSpaceReserved(false);
|
||||
getPreferenceScreen().addPreference(mWPPreviewPref);
|
||||
|
||||
PreferenceFragmentUtils.addPreference(getPreferenceScreen(), "wp_set", requireContext().getString(R.string.wallpaper_select), requireContext().getString(R.string.wallpaper_from_gallery), R.drawable.ic_picture_outline_28, preference -> {
|
||||
startActivityForResult(new Intent(Intent.ACTION_PICK, android.provider.MediaStore.Images.Media.EXTERNAL_CONTENT_URI), 1488);
|
||||
removeStickCache();
|
||||
return true;
|
||||
});
|
||||
PreferenceFragmentUtils.addPreference(
|
||||
getPreferenceScreen(),
|
||||
"wp_set",
|
||||
requireContext().getString(R.string.wallpaper_select),
|
||||
requireContext().getString(R.string.wallpaper_from_gallery),
|
||||
R.drawable.ic_picture_outline_28,
|
||||
preference -> {
|
||||
startActivityForResult(
|
||||
new Intent(
|
||||
Intent.ACTION_PICK,
|
||||
android.provider.MediaStore.Images.Media.EXTERNAL_CONTENT_URI
|
||||
),
|
||||
1488
|
||||
);
|
||||
removeStickCache();
|
||||
return true;
|
||||
});
|
||||
|
||||
PreferenceFragmentUtils.addPreference(getPreferenceScreen(), "wp_clear", requireContext().getString(R.string.wallpaper_remove), "", R.drawable.ic_delete_outline_28, preference -> {
|
||||
removeWallpaper();
|
||||
requestUpdateWallpaper();
|
||||
mWPPreviewPref.redraw();
|
||||
removeStickCache();
|
||||
return true;
|
||||
});
|
||||
PreferenceFragmentUtils.addPreference(
|
||||
getPreferenceScreen(),
|
||||
"wp_clear",
|
||||
requireContext().getString(R.string.wallpaper_remove),
|
||||
"",
|
||||
R.drawable.ic_delete_outline_28,
|
||||
preference -> {
|
||||
removeWallpaper();
|
||||
requestUpdateWallpaper();
|
||||
mWPPreviewPref.redraw();
|
||||
removeStickCache();
|
||||
return true;
|
||||
});
|
||||
|
||||
PreferenceFragmentUtils.addPreferenceCategory(getPreferenceScreen(), requireContext().getString(R.string.vtlfilters));
|
||||
|
||||
if (!hasVerification() && !getBoolValue("dialogrecomm", false)) {
|
||||
PreferenceFragmentUtils.addPreference(getPreferenceScreen(), "", requireContext().getString(R.string.filters_warning), requireContext().getString(R.string.icons_warning_info), 0, preference -> {
|
||||
requireContext().startActivity(new Intent(Intent.ACTION_VIEW).setData(Uri.parse("https://vtosters.app/donate/")));
|
||||
return false;
|
||||
});
|
||||
PreferenceFragmentUtils.addPreference(
|
||||
getPreferenceScreen(),
|
||||
"",
|
||||
requireContext().getString(R.string.filters_warning),
|
||||
requireContext().getString(R.string.icons_warning_info),
|
||||
0,
|
||||
preference -> {
|
||||
requireContext().startActivity(
|
||||
new Intent(Intent.ACTION_VIEW)
|
||||
.setData(Uri.parse("https://vtosters.app/donate/"))
|
||||
);
|
||||
return false;
|
||||
});
|
||||
}
|
||||
|
||||
PreferenceFragmentUtils.addListPreference(getPreferenceScreen(), "msg_blur_radius", "disabled", requireContext().getString(R.string.filter_blur), AndroidUtils.getArray(R.array.filter_types), new String[]{
|
||||
"disabled", "low", "med", "high"
|
||||
});
|
||||
Arrays.stream(ImageEffects.values())
|
||||
.filter(imageEffects -> imageEffects.isFree() || hasVerification())
|
||||
.forEach(it -> {
|
||||
if (it.isList()) {
|
||||
var pref = PreferenceFragmentUtils.addListPreference(
|
||||
getPreferenceScreen(),
|
||||
it.toString(),
|
||||
"disabled",
|
||||
it.getTitle(),
|
||||
it.getEntries(),
|
||||
it.getEntryValues()
|
||||
);
|
||||
pref.setSummary(it.getSummary());
|
||||
pref.setOnPreferenceChangeListener((preference, o) -> {
|
||||
edit().putString(it.toString(), (String) o).apply();
|
||||
preference.setSummary(it.getSummary());
|
||||
requestUpdateWallpaper();
|
||||
mWPPreviewPref.redraw();
|
||||
return true;
|
||||
});
|
||||
} else if (it.isSwitch()) {
|
||||
PreferenceFragmentUtils.addMaterialSwitchPreference(
|
||||
getPreferenceScreen(),
|
||||
it.toString(),
|
||||
it.getTitle(),
|
||||
it.getSummary(),
|
||||
0,
|
||||
false,
|
||||
(preference, o) -> {
|
||||
edit().putBoolean(it.toString(), (Boolean) o).apply();
|
||||
requestUpdateWallpaper();
|
||||
mWPPreviewPref.redraw();
|
||||
return true;
|
||||
});
|
||||
}
|
||||
});
|
||||
|
||||
PreferenceFragmentUtils.addListPreference(getPreferenceScreen(), "msg_dim", "off", requireContext().getString(R.string.filter_dim), AndroidUtils.getArray(R.array.filter_dim_types), new String[]{
|
||||
"off", "dim_black", "dim_white"
|
||||
});
|
||||
|
||||
|
||||
PreferenceFragmentUtils.addListPreference(getPreferenceScreen(), "msg_mosaic", "disabled", requireContext().getString(R.string.filter_mosaic), AndroidUtils.getArray(R.array.filter_types), new String[]{
|
||||
"disabled", "low", "med", "high"
|
||||
});
|
||||
|
||||
if (hasVerification()) {
|
||||
PreferenceFragmentUtils.addMaterialSwitchPreference(getPreferenceScreen(), "msg_monochrome", requireContext().getString(R.string.filter_monochrome), "", 0, false, (preference, o) -> {
|
||||
boolean value = (boolean) o;
|
||||
edit().putBoolean("msg_monochrome", value).commit();
|
||||
requestUpdateWallpaper();
|
||||
mWPPreviewPref.redraw();
|
||||
return true;
|
||||
});
|
||||
|
||||
PreferenceFragmentUtils.addMaterialSwitchPreference(getPreferenceScreen(), "msg_invert", requireContext().getString(R.string.filter_invert_colors), "", 0, false, (preference, o) -> {
|
||||
boolean value = (boolean) o;
|
||||
edit().putBoolean("msg_invert", value).commit();
|
||||
requestUpdateWallpaper();
|
||||
mWPPreviewPref.redraw();
|
||||
return true;
|
||||
});
|
||||
|
||||
PreferenceFragmentUtils.addMaterialSwitchPreference(getPreferenceScreen(), "msg_sepia", requireContext().getString(R.string.filter_sepia), "", 0, false, (preference, o) -> {
|
||||
boolean value = (boolean) o;
|
||||
edit().putBoolean("msg_sepia", value).commit();
|
||||
requestUpdateWallpaper();
|
||||
mWPPreviewPref.redraw();
|
||||
return true;
|
||||
});
|
||||
|
||||
PreferenceFragmentUtils.addMaterialSwitchPreference(getPreferenceScreen(), "msg_emboss", requireContext().getString(R.string.filter_emboss), requireContext().getString(R.string.filter_maybe_lag), 0, false, (preference, o) -> {
|
||||
boolean value = (boolean) o;
|
||||
edit().putBoolean("msg_emboss", value).commit();
|
||||
requestUpdateWallpaper();
|
||||
mWPPreviewPref.redraw();
|
||||
return true;
|
||||
});
|
||||
|
||||
PreferenceFragmentUtils.addMaterialSwitchPreference(getPreferenceScreen(), "msg_engrave", requireContext().getString(R.string.filter_engrave), requireContext().getString(R.string.filter_maybe_lag), 0, false, (preference, o) -> {
|
||||
boolean value = (boolean) o;
|
||||
edit().putBoolean("msg_engrave", value).commit();
|
||||
requestUpdateWallpaper();
|
||||
mWPPreviewPref.redraw();
|
||||
return true;
|
||||
});
|
||||
|
||||
PreferenceFragmentUtils.addMaterialSwitchPreference(getPreferenceScreen(), "msg_flea", requireContext().getString(R.string.filter_flea), "", 0, false, (preference, o) -> {
|
||||
boolean value = (boolean) o;
|
||||
edit().putBoolean("msg_flea", value).commit();
|
||||
requestUpdateWallpaper();
|
||||
mWPPreviewPref.redraw();
|
||||
return true;
|
||||
});
|
||||
|
||||
PreferenceFragmentUtils.addMaterialSwitchPreference(getPreferenceScreen(), "msg_snow", requireContext().getString(R.string.filter_flea), "", 0, false, (preference, o) -> {
|
||||
boolean value = (boolean) o;
|
||||
edit().putBoolean("msg_snow", value).commit();
|
||||
requestUpdateWallpaper();
|
||||
mWPPreviewPref.redraw();
|
||||
return true;
|
||||
});
|
||||
}
|
||||
|
||||
PreferenceFragmentUtils.addMaterialSwitchPreference(getPreferenceScreen(), "compresswp", requireContext().getString(R.string.compress_wallpaper_title), requireContext().getString(R.string.compress_wallpaper_summ), 0, true, (preference, o) -> {
|
||||
boolean value = (boolean) o;
|
||||
edit().putBoolean("compresswp", value).commit();
|
||||
requestUpdateWallpaper();
|
||||
mWPPreviewPref.redraw();
|
||||
return true;
|
||||
});
|
||||
|
||||
ListPreference blur = (ListPreference) findPreference("msg_blur_radius");
|
||||
ListPreference dim = (ListPreference) findPreference("msg_dim");
|
||||
ListPreference mosaic = (ListPreference) findPreference("msg_mosaic");
|
||||
|
||||
blur.setSummary(getRadiusSummary());
|
||||
dim.setSummary(getDimmingSummary());
|
||||
mosaic.setSummary(getMosaicSummary());
|
||||
|
||||
blur.setOnPreferenceChangeListener((preference, o) -> {
|
||||
edit().putString("msg_blur_radius", (String) o).apply();
|
||||
preference.setSummary(getRadiusSummary());
|
||||
requestUpdateWallpaper();
|
||||
mWPPreviewPref.redraw();
|
||||
return true;
|
||||
});
|
||||
|
||||
dim.setOnPreferenceChangeListener((preference, o) -> {
|
||||
edit().putString("msg_dim", (String) o).apply();
|
||||
preference.setSummary(getDimmingSummary());
|
||||
requestUpdateWallpaper();
|
||||
mWPPreviewPref.redraw();
|
||||
return true;
|
||||
});
|
||||
|
||||
mosaic.setOnPreferenceChangeListener((preference, o) -> {
|
||||
edit().putString("msg_mosaic", (String) o).apply();
|
||||
preference.setSummary(getMosaicSummary());
|
||||
requestUpdateWallpaper();
|
||||
mWPPreviewPref.redraw();
|
||||
return true;
|
||||
});
|
||||
PreferenceFragmentUtils.addMaterialSwitchPreference(
|
||||
getPreferenceScreen(),
|
||||
"compresswp",
|
||||
requireContext().getString(R.string.compress_wallpaper_title),
|
||||
requireContext().getString(R.string.compress_wallpaper_summ),
|
||||
0,
|
||||
true,
|
||||
(preference, o) -> {
|
||||
boolean value = (boolean) o;
|
||||
edit().putBoolean("compresswp", value).commit();
|
||||
requestUpdateWallpaper();
|
||||
mWPPreviewPref.redraw();
|
||||
return true;
|
||||
});
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
@@ -1,7 +1,6 @@
|
||||
package ru.vtosters.lite.ui.wallpapers;
|
||||
|
||||
import static ru.vtosters.lite.ui.wallpapers.WallpapersHooks.getFilteredFile;
|
||||
import static ru.vtosters.lite.ui.wallpapers.WallpapersHooks.getWallpaperFile;
|
||||
import static ru.vtosters.lite.ui.wallpapers.WallpapersHooks.*;
|
||||
import static ru.vtosters.lite.utils.AndroidUtils.dp2px;
|
||||
|
||||
import android.annotation.SuppressLint;
|
||||
@@ -59,12 +58,8 @@ public class WallpaperPreferences extends Preference {
|
||||
}
|
||||
|
||||
private void requestBg() {
|
||||
final Drawable drawable = getFilteredFile();
|
||||
|
||||
if (drawable != null && getWallpaperFile() != null)
|
||||
mChatBackground.setImageDrawable(drawable);
|
||||
else
|
||||
mChatBackground.setImageDrawable(null);
|
||||
final Drawable drawable = getWallpaper();
|
||||
mChatBackground.setImageDrawable(drawable);
|
||||
}
|
||||
|
||||
@SuppressLint("NotifyDataSetChanged")
|
||||
|
||||
@@ -1,78 +1,97 @@
|
||||
package ru.vtosters.lite.ui.wallpapers;
|
||||
|
||||
import static com.vk.im.engine.h.im_bg_chat;
|
||||
import static ru.vtosters.lite.ui.wallpapers.ImageFilters.getFilteredDrawable;
|
||||
import static ru.vtosters.lite.utils.AndroidUtils.getGlobalContext;
|
||||
import static ru.vtosters.lite.utils.AndroidUtils.getPreferences;
|
||||
import static ru.vtosters.lite.utils.AndroidUtils.sendToast;
|
||||
import static ru.vtosters.lite.utils.Preferences.getBoolValue;
|
||||
|
||||
import android.graphics.Bitmap;
|
||||
import android.graphics.BitmapFactory;
|
||||
import android.graphics.drawable.BitmapDrawable;
|
||||
import android.graphics.drawable.Drawable;
|
||||
import android.view.View;
|
||||
import android.widget.ImageView;
|
||||
|
||||
import com.vtosters.lite.R;
|
||||
|
||||
import java.io.ByteArrayOutputStream;
|
||||
import java.io.File;
|
||||
import java.io.FileOutputStream;
|
||||
|
||||
import ru.vtosters.lite.utils.AndroidUtils;
|
||||
import ru.vtosters.lite.utils.ThemesUtils;
|
||||
import vigo.sdk.Log;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.FileOutputStream;
|
||||
import java.util.function.Supplier;
|
||||
|
||||
import static com.vk.im.engine.h.im_bg_chat;
|
||||
import static ru.vtosters.lite.ui.wallpapers.ImageFilters.getFilteredDrawable;
|
||||
import static ru.vtosters.lite.utils.AndroidUtils.getGlobalContext;
|
||||
import static ru.vtosters.lite.utils.AndroidUtils.sendToast;
|
||||
import static ru.vtosters.lite.utils.Preferences.getBoolValue;
|
||||
|
||||
public class WallpapersHooks {
|
||||
private static final boolean compress = getBoolValue("compresswp", true);
|
||||
private static File mWallpaperFile;
|
||||
// TODO: force compress by default not asking user about that?
|
||||
private static final Supplier<Boolean> compress = () -> getBoolValue("compresswp", true);
|
||||
private static final File originalWp = new File(getGlobalContext().getFilesDir(), "wallpaper.jpeg");
|
||||
private static final File compressedWp = new File(getGlobalContext().getFilesDir(), "compressedwp.jpeg");
|
||||
// TODO: cache to file?
|
||||
private static Drawable mWallpaper;
|
||||
private static boolean mUpdateWallpaperRequested = true;
|
||||
private static boolean mUpdateWallpaperFileRequested = true;
|
||||
|
||||
public static File getWallpaperFile() {
|
||||
if (mWallpaperFile == null) {
|
||||
mWallpaperFile = new File(getGlobalContext().getFilesDir(), "wallpaper.webp");
|
||||
// TODO: respect blur, when there is blur/mosaic effect applied these two can be even less, just HD (1280x720) for e.g.
|
||||
private static final int MAX_WP_WIDTH = 1080;
|
||||
private static final int MAX_WP_HEIGHT = 1920;
|
||||
|
||||
|
||||
public static void setBg(View view) {
|
||||
if (hasWallpapers()) {
|
||||
((ImageView) view).setImageDrawable(getWallpaper()); // set picture to background
|
||||
} else {
|
||||
view.setBackgroundColor(ThemesUtils.getColorFromAttr(im_bg_chat)); // set default bg color
|
||||
}
|
||||
|
||||
return mWallpaperFile;
|
||||
}
|
||||
|
||||
public static Drawable getFilteredFile() {
|
||||
File file = null;
|
||||
File wp = mWallpaperFile;
|
||||
String temp = getGlobalContext().getFilesDir() + File.separator + "filteredwp.webp";
|
||||
|
||||
if (wp != null && mUpdateWallpaperFileRequested) {
|
||||
try {
|
||||
file = new File(temp);
|
||||
file.createNewFile();
|
||||
|
||||
ByteArrayOutputStream bos = new ByteArrayOutputStream();
|
||||
((BitmapDrawable) getFilteredDrawable(Drawable.createFromPath(wp.getAbsolutePath()))).getBitmap().compress(Bitmap.CompressFormat.WEBP, (compress ? 80 : 95), bos);
|
||||
byte[] bitmapdata = bos.toByteArray();
|
||||
|
||||
FileOutputStream fos = new FileOutputStream(file);
|
||||
fos.write(bitmapdata);
|
||||
fos.flush();
|
||||
fos.close();
|
||||
|
||||
} catch (Exception e) {
|
||||
Log.d("Wallpapers", e.getMessage());
|
||||
}
|
||||
|
||||
mUpdateWallpaperFileRequested = false;
|
||||
}
|
||||
|
||||
try {
|
||||
return Drawable.createFromPath(temp);
|
||||
} catch (Exception e) {
|
||||
if (file != null) {
|
||||
return Drawable.createFromPath(file.getAbsolutePath());
|
||||
} else {
|
||||
public static Drawable getWallpaper() {
|
||||
if (mWallpaper == null || mUpdateWallpaperRequested) {
|
||||
if (!originalWp.exists()) {
|
||||
return null;
|
||||
}
|
||||
Drawable drawable;
|
||||
if (compress.get()) {
|
||||
if (!compressedWp.exists() && !prepareCompressed()) {
|
||||
return null;
|
||||
}
|
||||
drawable = Drawable.createFromPath(compressedWp.getAbsolutePath());
|
||||
} else {
|
||||
drawable = Drawable.createFromPath(originalWp.getAbsolutePath());
|
||||
}
|
||||
|
||||
if (drawable == null) {
|
||||
return null;
|
||||
}
|
||||
mWallpaper = getFilteredDrawable(drawable);
|
||||
mUpdateWallpaperRequested = false;
|
||||
}
|
||||
|
||||
return mWallpaper;
|
||||
}
|
||||
|
||||
private static boolean prepareCompressed() {
|
||||
// TODO remove this check? with "compress" enabled it should be fine
|
||||
if (!eligibleWallpaperFile(originalWp)) {
|
||||
return false;
|
||||
}
|
||||
try (var f = new FileOutputStream(compressedWp)) {
|
||||
var bitmap = BitmapFactory.decodeFile(originalWp.getAbsolutePath());
|
||||
|
||||
if (bitmap.getHeight() > MAX_WP_HEIGHT || bitmap.getWidth() > MAX_WP_WIDTH) {
|
||||
bitmap = resize(bitmap, MAX_WP_WIDTH, MAX_WP_HEIGHT);
|
||||
}
|
||||
var drawable = new BitmapDrawable(null, bitmap);
|
||||
// TODO: remove duplication without changes when provided image already fits required params
|
||||
drawable.getBitmap().compress(Bitmap.CompressFormat.WEBP, 90, f);
|
||||
} catch (Exception e) {
|
||||
Log.d("Wallpapers", e.getMessage());
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
public static File getWallpaperFile() {
|
||||
return originalWp;
|
||||
}
|
||||
|
||||
private static Boolean eligibleWallpaperFile(File file) {
|
||||
@@ -85,94 +104,40 @@ public class WallpapersHooks {
|
||||
}
|
||||
}
|
||||
|
||||
public static void setBg(View view) {
|
||||
if (hasWallpapers()) {
|
||||
((ImageView) view).setImageDrawable(getFilteredFile()); // set picture to background
|
||||
} else {
|
||||
view.setBackgroundColor(ThemesUtils.getColorFromAttr(im_bg_chat)); // set default bg color
|
||||
}
|
||||
}
|
||||
|
||||
public static String getWallpaperUrl() {
|
||||
var file = getWallpaperFile();
|
||||
|
||||
if (file.exists() && eligibleWallpaperFile(file)) {
|
||||
return file.getAbsolutePath();
|
||||
}
|
||||
|
||||
return "default";
|
||||
}
|
||||
|
||||
public static boolean hasWallpapers() {
|
||||
return getWallpaper() != null;
|
||||
}
|
||||
|
||||
public static Drawable getWallpaper() {
|
||||
if (mWallpaper == null || mUpdateWallpaperRequested) {
|
||||
String url = getWallpaperUrl();
|
||||
|
||||
if (url.equals("default") || url.isEmpty()) {
|
||||
return null;
|
||||
}
|
||||
|
||||
Drawable drawable = Drawable.createFromPath(getWallpaperUrl());
|
||||
|
||||
if (drawable == null) {
|
||||
return null;
|
||||
}
|
||||
|
||||
mWallpaper = drawable;
|
||||
|
||||
mWallpaper = getFilteredDrawable(mWallpaper);
|
||||
|
||||
mUpdateWallpaperRequested = false;
|
||||
}
|
||||
|
||||
return mWallpaper;
|
||||
}
|
||||
|
||||
public static void requestUpdateWallpaper() {
|
||||
mUpdateWallpaperRequested = true;
|
||||
mUpdateWallpaperFileRequested = true;
|
||||
}
|
||||
|
||||
public static String getRadiusSummary() {
|
||||
String radius = getPreferences().getString("msg_blur_radius", "disabled");
|
||||
return switch (radius) {
|
||||
case "low" -> AndroidUtils.getString(R.string.wallpapers_low);
|
||||
case "med" -> AndroidUtils.getString(R.string.wallpapers_med);
|
||||
case "high" -> AndroidUtils.getString(R.string.wallpapers_high);
|
||||
default -> AndroidUtils.getString(R.string.wallpapers_disabled);
|
||||
};
|
||||
}
|
||||
|
||||
public static String getDimmingSummary() {
|
||||
String radius = getPreferences().getString("msg_dim", "disabled");
|
||||
return switch (radius) {
|
||||
case "dim_black" -> AndroidUtils.getString(R.string.wallpapers_dim_black);
|
||||
case "dim_white" -> AndroidUtils.getString(R.string.wallpapers_dim_white);
|
||||
default -> AndroidUtils.getString(R.string.wallpapers_disabled);
|
||||
};
|
||||
}
|
||||
|
||||
public static String getMosaicSummary() {
|
||||
String radius = getPreferences().getString("msg_mosaic", "disabled");
|
||||
return switch (radius) {
|
||||
case "low" -> AndroidUtils.getString(R.string.wallpapers_low);
|
||||
case "med" -> AndroidUtils.getString(R.string.wallpapers_med);
|
||||
case "high" -> AndroidUtils.getString(R.string.wallpapers_high);
|
||||
default -> AndroidUtils.getString(R.string.wallpapers_disabled);
|
||||
};
|
||||
}
|
||||
|
||||
|
||||
public static void removeWallpaper() {
|
||||
try {
|
||||
new File(getGlobalContext().getFilesDir(), "wallpaper.webp").delete();
|
||||
new File(getGlobalContext().getFilesDir(), "filteredwp.webp").delete();
|
||||
mWallpaperFile = null;
|
||||
mWallpaper = null;
|
||||
originalWp.delete();
|
||||
compressedWp.delete();
|
||||
} catch (Exception e) {
|
||||
Log.d("Wallpapers", e.getMessage());
|
||||
}
|
||||
}
|
||||
|
||||
private static Bitmap resize(Bitmap image, int maxWidth, int maxHeight) {
|
||||
if (maxHeight > 0 && maxWidth > 0) {
|
||||
int width = image.getWidth();
|
||||
int height = image.getHeight();
|
||||
float ratioBitmap = (float) width / (float) height;
|
||||
float ratioMax = (float) maxWidth / (float) maxHeight;
|
||||
|
||||
int finalWidth = maxWidth;
|
||||
int finalHeight = maxHeight;
|
||||
if (ratioMax > ratioBitmap) {
|
||||
finalWidth = (int) ((float) maxHeight * ratioBitmap);
|
||||
} else {
|
||||
finalHeight = (int) ((float) maxWidth / ratioBitmap);
|
||||
}
|
||||
image = Bitmap.createScaledBitmap(image, finalWidth, finalHeight, true);
|
||||
}
|
||||
return image;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -3,9 +3,13 @@ buildscript {
|
||||
repositories {
|
||||
google()
|
||||
mavenCentral()
|
||||
maven {
|
||||
url "https://plugins.gradle.org/m2/"
|
||||
}
|
||||
}
|
||||
dependencies {
|
||||
classpath 'com.android.tools.build:gradle:7.3.1'
|
||||
classpath 'org.mozilla.rust-android-gradle:plugin:0.9.3'
|
||||
|
||||
// NOTE: Do not place your application dependencies here; they belong
|
||||
// in the individual module build.gradle files
|
||||
|
||||
@@ -0,0 +1,2 @@
|
||||
/target
|
||||
Cargo.lock
|
||||
@@ -0,0 +1,18 @@
|
||||
[package]
|
||||
name = "native-effects"
|
||||
version = "0.1.0"
|
||||
edition = "2021"
|
||||
|
||||
[profile.release]
|
||||
opt-level = 3
|
||||
strip = true
|
||||
lto = true
|
||||
codegen-units = 1
|
||||
|
||||
[lib]
|
||||
crate-type = ["cdylib"]
|
||||
|
||||
[dependencies]
|
||||
jni = "0.20.0"
|
||||
rand = "0.8.5"
|
||||
image = "0.24.5"
|
||||
@@ -0,0 +1,365 @@
|
||||
use jni::objects::JByteBuffer;
|
||||
use jni::objects::JClass;
|
||||
use jni::sys::jfloat;
|
||||
use jni::sys::jint;
|
||||
use jni::sys::jstring;
|
||||
use jni::JNIEnv;
|
||||
use rand::Rng;
|
||||
use std::cmp::max;
|
||||
|
||||
// We assume that input ByteBuffer is always in ARGB_8888 format
|
||||
#[repr(C)]
|
||||
#[derive(Debug, Clone, Copy)]
|
||||
struct Pixel {
|
||||
r: u8,
|
||||
g: u8,
|
||||
b: u8,
|
||||
a: u8,
|
||||
}
|
||||
|
||||
impl Pixel {
|
||||
fn set_color(&mut self, r: u8, g: u8, b: u8) {
|
||||
self.r = r;
|
||||
self.g = g;
|
||||
self.b = b;
|
||||
}
|
||||
|
||||
fn invert(&mut self) {
|
||||
self.r = 255 - self.r;
|
||||
self.g = 255 - self.g;
|
||||
self.b = 255 - self.b;
|
||||
}
|
||||
}
|
||||
|
||||
fn resolve_pixel_slice<'a>(env: &JNIEnv<'a>, bitmap_buffer: &JByteBuffer<'a>) -> &'a mut [Pixel] {
|
||||
let start = env
|
||||
.get_direct_buffer_address(*bitmap_buffer)
|
||||
.expect("Unable to resolve DirectBuffer address");
|
||||
let capacity = env
|
||||
.get_direct_buffer_capacity(*bitmap_buffer)
|
||||
.expect("Unable to resolve DirectBuffer size");
|
||||
let s = start as *mut Pixel;
|
||||
unsafe { std::slice::from_raw_parts_mut(s, capacity / 4) }
|
||||
}
|
||||
|
||||
#[no_mangle]
|
||||
pub extern "C" fn Java_ru_vtosters_lite_ui_wallpapers_NativeEffects_monochrome(
|
||||
env: JNIEnv,
|
||||
_: JClass,
|
||||
bitmap_buffer: JByteBuffer,
|
||||
) -> jstring {
|
||||
let pixels = resolve_pixel_slice(&env, &bitmap_buffer);
|
||||
pixels.iter_mut().for_each(|p| {
|
||||
// value (V) from HSV
|
||||
let value = max(p.r, max(p.g, p.b));
|
||||
if value > 127 {
|
||||
p.set_color(255, 255, 255);
|
||||
} else {
|
||||
p.set_color(0, 0, 0);
|
||||
}
|
||||
});
|
||||
|
||||
let output = env
|
||||
.new_string("Applied Monochrome effect!")
|
||||
.expect("Couldn't create java string!");
|
||||
return **output;
|
||||
}
|
||||
|
||||
#[no_mangle]
|
||||
pub extern "C" fn Java_ru_vtosters_lite_ui_wallpapers_NativeEffects_invert(
|
||||
env: JNIEnv,
|
||||
_: JClass,
|
||||
bitmap_buffer: JByteBuffer,
|
||||
) -> jstring {
|
||||
let pixels = resolve_pixel_slice(&env, &bitmap_buffer);
|
||||
|
||||
pixels.iter_mut().for_each(|p| p.invert());
|
||||
|
||||
let output = env
|
||||
.new_string("Applied Invert effect!")
|
||||
.expect("Couldn't create java string!");
|
||||
return **output;
|
||||
}
|
||||
|
||||
#[no_mangle]
|
||||
pub extern "C" fn Java_ru_vtosters_lite_ui_wallpapers_NativeEffects_sepia(
|
||||
env: JNIEnv,
|
||||
_: JClass,
|
||||
bitmap_buffer: JByteBuffer,
|
||||
) -> jstring {
|
||||
let pixels = resolve_pixel_slice(&env, &bitmap_buffer);
|
||||
|
||||
pixels.iter_mut().for_each(|p| {
|
||||
let r = p.r as f32;
|
||||
let g = p.g as f32;
|
||||
let b = p.b as f32;
|
||||
|
||||
let new_red = 0.393 * r + 0.769 * g + 0.189 * b;
|
||||
let new_green = 0.349 * r + 0.686 * g + 0.168 * b;
|
||||
let new_blue = 0.272 * r + 0.534 * g + 0.131 * b;
|
||||
|
||||
p.set_color(new_red as u8, new_green as u8, new_blue as u8);
|
||||
});
|
||||
|
||||
let output = env
|
||||
.new_string("Applied Sepia effect!")
|
||||
.expect("Couldn't create java string!");
|
||||
return **output;
|
||||
}
|
||||
|
||||
#[no_mangle]
|
||||
pub extern "C" fn Java_ru_vtosters_lite_ui_wallpapers_NativeEffects_emboss(
|
||||
env: JNIEnv,
|
||||
_: JClass,
|
||||
bitmap_buffer: JByteBuffer,
|
||||
height: jint,
|
||||
width: jint,
|
||||
) -> jstring {
|
||||
let pixels = resolve_pixel_slice(&env, &bitmap_buffer);
|
||||
let kernel = [-1.0, 0.0, -1.0, 0.0, 4.0, 0.0, -1.0, 0.0, -1.0];
|
||||
let out: &mut Vec<Pixel> = &mut Vec::new();
|
||||
for (y, row) in pixels.chunks(width as usize).enumerate() {
|
||||
for (x, pixel) in row.iter().enumerate() {
|
||||
if y == 0 || x == 0 || y == (height - 1) as usize || x == (width - 1) as usize {
|
||||
out.push(*pixel);
|
||||
continue;
|
||||
}
|
||||
let start = y * width as usize + x - 1;
|
||||
let end = start + 3;
|
||||
let matrix = [
|
||||
&pixels[start - width as usize..end - width as usize],
|
||||
&pixels[start..end],
|
||||
&pixels[start + width as usize..end + width as usize],
|
||||
]
|
||||
.concat();
|
||||
let mut acc = [64.0, 64.0, 64.0];
|
||||
for (p, k) in matrix.iter().zip(kernel.iter()) {
|
||||
acc[0] += p.r as f32 * k;
|
||||
acc[1] += p.g as f32 * k;
|
||||
acc[2] += p.b as f32 * k;
|
||||
}
|
||||
|
||||
out.push(Pixel {
|
||||
r: acc[0] as u8,
|
||||
g: acc[1] as u8,
|
||||
b: acc[2] as u8,
|
||||
a: pixel.a,
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
pixels.copy_from_slice(&out);
|
||||
|
||||
let output = env
|
||||
.new_string("Applied Emboss effect!")
|
||||
.expect("Couldn't create java string!");
|
||||
return **output;
|
||||
}
|
||||
|
||||
#[no_mangle]
|
||||
pub extern "C" fn Java_ru_vtosters_lite_ui_wallpapers_NativeEffects_engrave(
|
||||
env: JNIEnv,
|
||||
_: JClass,
|
||||
bitmap_buffer: JByteBuffer,
|
||||
height: jint,
|
||||
width: jint,
|
||||
) -> jstring {
|
||||
let pixels = resolve_pixel_slice(&env, &bitmap_buffer);
|
||||
let kernel = [-2.0, 0.0, 0.0, 0.0, 2.0, 0.0, 0.0, 0.0, 0.0];
|
||||
let out: &mut Vec<Pixel> = &mut Vec::new();
|
||||
for (y, row) in pixels.chunks(width as usize).enumerate() {
|
||||
for (x, pixel) in row.iter().enumerate() {
|
||||
if y == 0 || x == 0 || y == (height - 1) as usize || x == (width - 1) as usize {
|
||||
out.push(*pixel);
|
||||
continue;
|
||||
}
|
||||
let start = y * width as usize + x - 1;
|
||||
let end = start + 3;
|
||||
let matrix = [
|
||||
&pixels[start - width as usize..end - width as usize],
|
||||
&pixels[start..end],
|
||||
&pixels[start + width as usize..end + width as usize],
|
||||
]
|
||||
.concat();
|
||||
let mut acc = [95.0, 95.0, 95.0];
|
||||
for (p, k) in matrix.iter().zip(kernel.iter()) {
|
||||
acc[0] += p.r as f32 * k;
|
||||
acc[1] += p.g as f32 * k;
|
||||
acc[2] += p.b as f32 * k;
|
||||
}
|
||||
|
||||
out.push(Pixel {
|
||||
r: acc[0] as u8,
|
||||
g: acc[1] as u8,
|
||||
b: acc[2] as u8,
|
||||
a: pixel.a,
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
pixels.copy_from_slice(&out);
|
||||
|
||||
let output = env
|
||||
.new_string("Applied Engrave effect!")
|
||||
.expect("Couldn't create java string!");
|
||||
return **output;
|
||||
}
|
||||
|
||||
#[no_mangle]
|
||||
pub extern "C" fn Java_ru_vtosters_lite_ui_wallpapers_NativeEffects_flea(
|
||||
env: JNIEnv,
|
||||
_: JClass,
|
||||
bitmap_buffer: JByteBuffer,
|
||||
) -> jstring {
|
||||
let mut rng = rand::thread_rng();
|
||||
let pixels = resolve_pixel_slice(&env, &bitmap_buffer);
|
||||
for p in pixels {
|
||||
p.set_color(
|
||||
p.r | rng.gen::<u8>(),
|
||||
p.g | rng.gen::<u8>(),
|
||||
p.b | rng.gen::<u8>(),
|
||||
)
|
||||
}
|
||||
|
||||
let output = env
|
||||
.new_string("Applied Flea effect!")
|
||||
.expect("Couldn't create java string!");
|
||||
return **output;
|
||||
}
|
||||
|
||||
#[no_mangle]
|
||||
pub extern "C" fn Java_ru_vtosters_lite_ui_wallpapers_NativeEffects_snow(
|
||||
env: JNIEnv,
|
||||
_: JClass,
|
||||
bitmap_buffer: JByteBuffer,
|
||||
) -> jstring {
|
||||
let mut rng = rand::thread_rng();
|
||||
let pixels = resolve_pixel_slice(&env, &bitmap_buffer);
|
||||
for p in pixels {
|
||||
let threshold: u8 = rng.gen();
|
||||
if p.r > threshold && p.g > threshold && p.b > threshold {
|
||||
p.set_color(255, 255, 255);
|
||||
}
|
||||
}
|
||||
|
||||
let output = env
|
||||
.new_string("Applied Snow effect!")
|
||||
.expect("Couldn't create java string!");
|
||||
return **output;
|
||||
}
|
||||
|
||||
#[no_mangle]
|
||||
pub extern "C" fn Java_ru_vtosters_lite_ui_wallpapers_NativeEffects_gaussian(
|
||||
env: JNIEnv,
|
||||
_: JClass,
|
||||
bitmap_buffer: JByteBuffer,
|
||||
height: jint,
|
||||
width: jint,
|
||||
radius: jfloat,
|
||||
) -> jstring {
|
||||
let start = env
|
||||
.get_direct_buffer_address(bitmap_buffer)
|
||||
.expect("Unable to resolve DirectBuffer address");
|
||||
let capacity = env
|
||||
.get_direct_buffer_capacity(bitmap_buffer)
|
||||
.expect("Unable to resolve DirectBuffer size");
|
||||
let s = start as *mut u8;
|
||||
let s = unsafe { std::slice::from_raw_parts_mut(s, capacity) };
|
||||
|
||||
let mut img = image::ImageBuffer::<image::Rgba<u8>, Vec<u8>>::from_raw(
|
||||
width as u32,
|
||||
height as u32,
|
||||
s.to_vec(),
|
||||
)
|
||||
.unwrap();
|
||||
|
||||
let img = image::imageops::blur(&mut img, radius);
|
||||
|
||||
s.copy_from_slice(img.as_raw());
|
||||
|
||||
let output = env
|
||||
.new_string("Applied Gaussian effect!")
|
||||
.expect("Couldn't create java string!");
|
||||
return **output;
|
||||
}
|
||||
|
||||
#[no_mangle]
|
||||
pub extern "C" fn Java_ru_vtosters_lite_ui_wallpapers_NativeEffects_dim(
|
||||
env: JNIEnv,
|
||||
_: JClass,
|
||||
bitmap_buffer: JByteBuffer,
|
||||
height: jint,
|
||||
width: jint,
|
||||
delta: jint,
|
||||
) -> jstring {
|
||||
let start = env
|
||||
.get_direct_buffer_address(bitmap_buffer)
|
||||
.expect("Unable to resolve DirectBuffer address");
|
||||
let capacity = env
|
||||
.get_direct_buffer_capacity(bitmap_buffer)
|
||||
.expect("Unable to resolve DirectBuffer size");
|
||||
let s = start as *mut u8;
|
||||
let s = unsafe { std::slice::from_raw_parts_mut(s, capacity) };
|
||||
|
||||
let img = image::ImageBuffer::<image::Rgba<u8>, Vec<u8>>::from_raw(
|
||||
width as u32,
|
||||
height as u32,
|
||||
s.to_vec(),
|
||||
)
|
||||
.unwrap();
|
||||
|
||||
let img = image::imageops::brighten(&img, delta);
|
||||
|
||||
s.copy_from_slice(img.as_raw());
|
||||
|
||||
let output = env
|
||||
.new_string("Applied Dim effect!")
|
||||
.expect("Couldn't create java string!");
|
||||
return **output;
|
||||
}
|
||||
|
||||
#[no_mangle]
|
||||
pub extern "C" fn Java_ru_vtosters_lite_ui_wallpapers_NativeEffects_mosaic(
|
||||
env: JNIEnv,
|
||||
_: JClass,
|
||||
bitmap_buffer: JByteBuffer,
|
||||
height: jint,
|
||||
width: jint,
|
||||
scale: jint,
|
||||
) -> jstring {
|
||||
let start = env
|
||||
.get_direct_buffer_address(bitmap_buffer)
|
||||
.expect("Unable to resolve DirectBuffer address");
|
||||
let capacity = env
|
||||
.get_direct_buffer_capacity(bitmap_buffer)
|
||||
.expect("Unable to resolve DirectBuffer size");
|
||||
let s = start as *mut u8;
|
||||
let s = unsafe { std::slice::from_raw_parts_mut(s, capacity) };
|
||||
|
||||
let mut img = image::ImageBuffer::<image::Rgba<u8>, Vec<u8>>::from_raw(
|
||||
width as u32,
|
||||
height as u32,
|
||||
s.to_vec(),
|
||||
)
|
||||
.unwrap();
|
||||
|
||||
img = image::imageops::resize(
|
||||
&img,
|
||||
(width / scale) as u32,
|
||||
(height / scale) as u32,
|
||||
image::imageops::FilterType::Nearest,
|
||||
);
|
||||
img = image::imageops::resize(
|
||||
&img,
|
||||
width as u32,
|
||||
height as u32,
|
||||
image::imageops::FilterType::Nearest,
|
||||
);
|
||||
|
||||
s.copy_from_slice(img.as_raw());
|
||||
|
||||
let output = env
|
||||
.new_string("Applied Mosaic effect!")
|
||||
.expect("Couldn't create java string!");
|
||||
return **output;
|
||||
}
|
||||
Executable
BIN
Binary file not shown.
Executable
BIN
Binary file not shown.
@@ -424,38 +424,38 @@
|
||||
return v0
|
||||
.end method
|
||||
|
||||
.method public final c()Ljava/lang/String;
|
||||
.locals 3
|
||||
# .method public final c()Ljava/lang/String;
|
||||
# .locals 3
|
||||
|
||||
invoke-static {}, Lru/vtosters/lite/ui/wallpapers/WallpapersHooks;->getWallpaperUrl()Ljava/lang/String;
|
||||
# invoke-static {}, Lru/vtosters/lite/ui/wallpapers/WallpapersHooks;->getWallpaperUrl()Ljava/lang/String;
|
||||
|
||||
move-result-object v0
|
||||
# move-result-object v0
|
||||
|
||||
return-object v0
|
||||
# return-object v0
|
||||
|
||||
.line 1
|
||||
invoke-direct {p0}, Lcom/vk/im/ui/ImUiPrefs;->k()Landroid/content/SharedPreferences;
|
||||
# .line 1
|
||||
# invoke-direct {p0}, Lcom/vk/im/ui/ImUiPrefs;->k()Landroid/content/SharedPreferences;
|
||||
|
||||
move-result-object v0
|
||||
# move-result-object v0
|
||||
|
||||
const-string v1, "pref_dialog_background_uri"
|
||||
# const-string v1, "pref_dialog_background_uri"
|
||||
|
||||
const-string v2, "default"
|
||||
# const-string v2, "default"
|
||||
|
||||
invoke-interface {v0, v1, v2}, Landroid/content/SharedPreferences;->getString(Ljava/lang/String;Ljava/lang/String;)Ljava/lang/String;
|
||||
# invoke-interface {v0, v1, v2}, Landroid/content/SharedPreferences;->getString(Ljava/lang/String;Ljava/lang/String;)Ljava/lang/String;
|
||||
|
||||
move-result-object v0
|
||||
# move-result-object v0
|
||||
|
||||
if-eqz v0, :cond_0
|
||||
# if-eqz v0, :cond_0
|
||||
|
||||
goto :goto_0
|
||||
# goto :goto_0
|
||||
|
||||
:cond_0
|
||||
const-string v0, ""
|
||||
# :cond_0
|
||||
# const-string v0, ""
|
||||
|
||||
:goto_0
|
||||
return-object v0
|
||||
.end method
|
||||
# :goto_0
|
||||
# return-object v0
|
||||
# .end method
|
||||
|
||||
.method public final d()J
|
||||
.locals 4
|
||||
|
||||
@@ -772,180 +772,180 @@
|
||||
|
||||
return-void
|
||||
|
||||
.line 1
|
||||
sget-object v0, Lcom/vk/im/ui/ImUiPrefs;->g:Lcom/vk/im/ui/ImUiPrefs;
|
||||
# .line 1
|
||||
# sget-object v0, Lcom/vk/im/ui/ImUiPrefs;->g:Lcom/vk/im/ui/ImUiPrefs;
|
||||
|
||||
invoke-virtual {v0}, Lcom/vk/im/ui/ImUiPrefs;->c()Ljava/lang/String;
|
||||
# invoke-virtual {v0}, Lcom/vk/im/ui/ImUiPrefs;->c()Ljava/lang/String;
|
||||
|
||||
move-result-object v0
|
||||
# move-result-object v0
|
||||
|
||||
.line 2
|
||||
invoke-interface {v0}, Ljava/lang/CharSequence;->length()I
|
||||
# .line 2
|
||||
# invoke-interface {v0}, Ljava/lang/CharSequence;->length()I
|
||||
|
||||
move-result v1
|
||||
# move-result v1
|
||||
|
||||
const/4 v2, 0x1
|
||||
# const/4 v2, 0x1
|
||||
|
||||
const/4 v3, 0x0
|
||||
# const/4 v3, 0x0
|
||||
|
||||
if-nez v1, :cond_0
|
||||
# if-nez v1, :cond_0
|
||||
|
||||
const/4 v1, 0x1
|
||||
# const/4 v1, 0x1
|
||||
|
||||
goto :goto_0
|
||||
# goto :goto_0
|
||||
|
||||
:cond_0
|
||||
const/4 v1, 0x0
|
||||
# :cond_0
|
||||
# const/4 v1, 0x0
|
||||
|
||||
:goto_0
|
||||
const-string v4, "msgListComponent"
|
||||
# :goto_0
|
||||
# const-string v4, "msgListComponent"
|
||||
|
||||
const-string v5, "dialogBackgroundView"
|
||||
# const-string v5, "dialogBackgroundView"
|
||||
|
||||
const/4 v6, 0x0
|
||||
# const/4 v6, 0x0
|
||||
|
||||
if-nez v1, :cond_6
|
||||
# if-nez v1, :cond_6
|
||||
|
||||
const-string v1, "default"
|
||||
# const-string v1, "default"
|
||||
|
||||
invoke-static {v0, v1}, Lkotlin/jvm/internal/Intrinsics;->a(Ljava/lang/Object;Ljava/lang/Object;)Z
|
||||
# invoke-static {v0, v1}, Lkotlin/jvm/internal/Intrinsics;->a(Ljava/lang/Object;Ljava/lang/Object;)Z
|
||||
|
||||
move-result v1
|
||||
# move-result v1
|
||||
|
||||
if-nez v1, :cond_6
|
||||
# if-nez v1, :cond_6
|
||||
|
||||
iget-object v1, p0, Lcom/vk/im/ui/fragments/ChatFragment;->E:Lcom/vk/im/engine/models/dialogs/DialogExt;
|
||||
# iget-object v1, p0, Lcom/vk/im/ui/fragments/ChatFragment;->E:Lcom/vk/im/engine/models/dialogs/DialogExt;
|
||||
|
||||
if-eqz v1, :cond_5
|
||||
# if-eqz v1, :cond_5
|
||||
|
||||
invoke-virtual {v1}, Lcom/vk/im/engine/models/dialogs/DialogExt;->t1()Lcom/vk/im/engine/models/dialogs/Dialog;
|
||||
# invoke-virtual {v1}, Lcom/vk/im/engine/models/dialogs/DialogExt;->t1()Lcom/vk/im/engine/models/dialogs/Dialog;
|
||||
|
||||
move-result-object v1
|
||||
# move-result-object v1
|
||||
|
||||
invoke-virtual {v1}, Lcom/vk/im/engine/models/dialogs/Dialog;->U1()Z
|
||||
# invoke-virtual {v1}, Lcom/vk/im/engine/models/dialogs/Dialog;->U1()Z
|
||||
|
||||
move-result v1
|
||||
# move-result v1
|
||||
|
||||
if-eqz v1, :cond_1
|
||||
# if-eqz v1, :cond_1
|
||||
|
||||
goto :goto_1
|
||||
# goto :goto_1
|
||||
|
||||
.line 3
|
||||
:cond_1
|
||||
iget-object v1, p0, Lcom/vk/im/ui/fragments/ChatFragment;->k0:Lcom/vk/im/ui/views/FrescoImageView;
|
||||
# .line 3
|
||||
# :cond_1
|
||||
# iget-object v1, p0, Lcom/vk/im/ui/fragments/ChatFragment;->k0:Lcom/vk/im/ui/views/FrescoImageView;
|
||||
|
||||
if-eqz v1, :cond_4
|
||||
# if-eqz v1, :cond_4
|
||||
|
||||
new-instance v3, Lcom/vk/im/engine/models/Image;
|
||||
# new-instance v3, Lcom/vk/im/engine/models/Image;
|
||||
|
||||
invoke-direct {v3, v0}, Lcom/vk/im/engine/models/Image;-><init>(Ljava/lang/String;)V
|
||||
# invoke-direct {v3, v0}, Lcom/vk/im/engine/models/Image;-><init>(Ljava/lang/String;)V
|
||||
|
||||
invoke-virtual {v1, v3}, Lcom/vk/im/ui/views/FrescoImageView;->setLocalImage(Lcom/vk/im/engine/models/Image;)V
|
||||
# invoke-virtual {v1, v3}, Lcom/vk/im/ui/views/FrescoImageView;->setLocalImage(Lcom/vk/im/engine/models/Image;)V
|
||||
|
||||
.line 4
|
||||
iget-object v0, p0, Lcom/vk/im/ui/fragments/ChatFragment;->k0:Lcom/vk/im/ui/views/FrescoImageView;
|
||||
# .line 4
|
||||
# iget-object v0, p0, Lcom/vk/im/ui/fragments/ChatFragment;->k0:Lcom/vk/im/ui/views/FrescoImageView;
|
||||
|
||||
if-eqz v0, :cond_3
|
||||
# if-eqz v0, :cond_3
|
||||
|
||||
invoke-virtual {v0, v6}, Lcom/vk/im/ui/views/FrescoImageView;->setBackgroundImage(Landroid/graphics/drawable/Drawable;)V
|
||||
# invoke-virtual {v0, v6}, Lcom/vk/im/ui/views/FrescoImageView;->setBackgroundImage(Landroid/graphics/drawable/Drawable;)V
|
||||
|
||||
.line 5
|
||||
iget-object v0, p0, Lcom/vk/im/ui/fragments/ChatFragment;->d0:Lcom/vk/im/ui/components/msg_list/MsgListComponent;
|
||||
# .line 5
|
||||
# iget-object v0, p0, Lcom/vk/im/ui/fragments/ChatFragment;->d0:Lcom/vk/im/ui/components/msg_list/MsgListComponent;
|
||||
|
||||
if-eqz v0, :cond_2
|
||||
# if-eqz v0, :cond_2
|
||||
|
||||
invoke-virtual {v0, v2}, Lcom/vk/im/ui/components/msg_list/MsgListComponent;->b(Z)V
|
||||
# invoke-virtual {v0, v2}, Lcom/vk/im/ui/components/msg_list/MsgListComponent;->b(Z)V
|
||||
|
||||
goto :goto_2
|
||||
# goto :goto_2
|
||||
|
||||
:cond_2
|
||||
invoke-static {v4}, Lkotlin/jvm/internal/Intrinsics;->b(Ljava/lang/String;)V
|
||||
# :cond_2
|
||||
# invoke-static {v4}, Lkotlin/jvm/internal/Intrinsics;->b(Ljava/lang/String;)V
|
||||
|
||||
throw v6
|
||||
# throw v6
|
||||
|
||||
.line 6
|
||||
:cond_3
|
||||
invoke-static {v5}, Lkotlin/jvm/internal/Intrinsics;->b(Ljava/lang/String;)V
|
||||
# .line 6
|
||||
# :cond_3
|
||||
# invoke-static {v5}, Lkotlin/jvm/internal/Intrinsics;->b(Ljava/lang/String;)V
|
||||
|
||||
throw v6
|
||||
# throw v6
|
||||
|
||||
.line 7
|
||||
:cond_4
|
||||
invoke-static {v5}, Lkotlin/jvm/internal/Intrinsics;->b(Ljava/lang/String;)V
|
||||
# .line 7
|
||||
# :cond_4
|
||||
# invoke-static {v5}, Lkotlin/jvm/internal/Intrinsics;->b(Ljava/lang/String;)V
|
||||
|
||||
throw v6
|
||||
# throw v6
|
||||
|
||||
:cond_5
|
||||
const-string v0, "dialogExt"
|
||||
# :cond_5
|
||||
# const-string v0, "dialogExt"
|
||||
|
||||
.line 8
|
||||
invoke-static {v0}, Lkotlin/jvm/internal/Intrinsics;->b(Ljava/lang/String;)V
|
||||
# .line 8
|
||||
# invoke-static {v0}, Lkotlin/jvm/internal/Intrinsics;->b(Ljava/lang/String;)V
|
||||
|
||||
throw v6
|
||||
# throw v6
|
||||
|
||||
.line 9
|
||||
:cond_6
|
||||
:goto_1
|
||||
iget-object v0, p0, Lcom/vk/im/ui/fragments/ChatFragment;->k0:Lcom/vk/im/ui/views/FrescoImageView;
|
||||
# .line 9
|
||||
# :cond_6
|
||||
# :goto_1
|
||||
# iget-object v0, p0, Lcom/vk/im/ui/fragments/ChatFragment;->k0:Lcom/vk/im/ui/views/FrescoImageView;
|
||||
|
||||
if-eqz v0, :cond_a
|
||||
# if-eqz v0, :cond_a
|
||||
|
||||
invoke-virtual {v0, v6}, Lcom/vk/im/ui/views/FrescoImageView;->setLocalImage(Lcom/vk/im/engine/models/Image;)V
|
||||
# invoke-virtual {v0, v6}, Lcom/vk/im/ui/views/FrescoImageView;->setLocalImage(Lcom/vk/im/engine/models/Image;)V
|
||||
|
||||
.line 10
|
||||
iget-object v0, p0, Lcom/vk/im/ui/fragments/ChatFragment;->k0:Lcom/vk/im/ui/views/FrescoImageView;
|
||||
# .line 10
|
||||
# iget-object v0, p0, Lcom/vk/im/ui/fragments/ChatFragment;->k0:Lcom/vk/im/ui/views/FrescoImageView;
|
||||
|
||||
if-eqz v0, :cond_9
|
||||
# if-eqz v0, :cond_9
|
||||
|
||||
new-instance v1, Landroid/graphics/drawable/ColorDrawable;
|
||||
# new-instance v1, Landroid/graphics/drawable/ColorDrawable;
|
||||
|
||||
iget-object v2, p0, Lcom/vk/im/ui/fragments/ChatFragment;->L:Landroid/content/Context;
|
||||
# iget-object v2, p0, Lcom/vk/im/ui/fragments/ChatFragment;->L:Landroid/content/Context;
|
||||
|
||||
if-eqz v2, :cond_8
|
||||
# if-eqz v2, :cond_8
|
||||
|
||||
sget v5, Lcom/vk/im/ui/c;->im_bg_chat:I
|
||||
# sget v5, Lcom/vk/im/ui/c;->im_bg_chat:I
|
||||
|
||||
invoke-static {v2, v5}, Lcom/vk/core/util/ContextExtKt;->h(Landroid/content/Context;I)I
|
||||
# invoke-static {v2, v5}, Lcom/vk/core/util/ContextExtKt;->h(Landroid/content/Context;I)I
|
||||
|
||||
move-result v2
|
||||
# move-result v2
|
||||
|
||||
invoke-direct {v1, v2}, Landroid/graphics/drawable/ColorDrawable;-><init>(I)V
|
||||
# invoke-direct {v1, v2}, Landroid/graphics/drawable/ColorDrawable;-><init>(I)V
|
||||
|
||||
invoke-virtual {v0, v1}, Lcom/vk/im/ui/views/FrescoImageView;->setBackgroundImage(Landroid/graphics/drawable/Drawable;)V
|
||||
# invoke-virtual {v0, v1}, Lcom/vk/im/ui/views/FrescoImageView;->setBackgroundImage(Landroid/graphics/drawable/Drawable;)V
|
||||
|
||||
.line 11
|
||||
iget-object v0, p0, Lcom/vk/im/ui/fragments/ChatFragment;->d0:Lcom/vk/im/ui/components/msg_list/MsgListComponent;
|
||||
# .line 11
|
||||
# iget-object v0, p0, Lcom/vk/im/ui/fragments/ChatFragment;->d0:Lcom/vk/im/ui/components/msg_list/MsgListComponent;
|
||||
|
||||
if-eqz v0, :cond_7
|
||||
# if-eqz v0, :cond_7
|
||||
|
||||
invoke-virtual {v0, v3}, Lcom/vk/im/ui/components/msg_list/MsgListComponent;->b(Z)V
|
||||
# invoke-virtual {v0, v3}, Lcom/vk/im/ui/components/msg_list/MsgListComponent;->b(Z)V
|
||||
|
||||
:goto_2
|
||||
return-void
|
||||
# :goto_2
|
||||
# return-void
|
||||
|
||||
:cond_7
|
||||
invoke-static {v4}, Lkotlin/jvm/internal/Intrinsics;->b(Ljava/lang/String;)V
|
||||
# :cond_7
|
||||
# invoke-static {v4}, Lkotlin/jvm/internal/Intrinsics;->b(Ljava/lang/String;)V
|
||||
|
||||
throw v6
|
||||
# throw v6
|
||||
|
||||
:cond_8
|
||||
const-string v0, "themedContext"
|
||||
# :cond_8
|
||||
# const-string v0, "themedContext"
|
||||
|
||||
.line 12
|
||||
invoke-static {v0}, Lkotlin/jvm/internal/Intrinsics;->b(Ljava/lang/String;)V
|
||||
# .line 12
|
||||
# invoke-static {v0}, Lkotlin/jvm/internal/Intrinsics;->b(Ljava/lang/String;)V
|
||||
|
||||
throw v6
|
||||
# throw v6
|
||||
|
||||
:cond_9
|
||||
invoke-static {v5}, Lkotlin/jvm/internal/Intrinsics;->b(Ljava/lang/String;)V
|
||||
# :cond_9
|
||||
# invoke-static {v5}, Lkotlin/jvm/internal/Intrinsics;->b(Ljava/lang/String;)V
|
||||
|
||||
throw v6
|
||||
# throw v6
|
||||
|
||||
.line 13
|
||||
:cond_a
|
||||
invoke-static {v5}, Lkotlin/jvm/internal/Intrinsics;->b(Ljava/lang/String;)V
|
||||
# .line 13
|
||||
# :cond_a
|
||||
# invoke-static {v5}, Lkotlin/jvm/internal/Intrinsics;->b(Ljava/lang/String;)V
|
||||
|
||||
throw v6
|
||||
# throw v6
|
||||
.end method
|
||||
|
||||
.method private final Y4()V
|
||||
|
||||
Reference in New Issue
Block a user