diff --git a/app/src/main/java/ru/vtosters/lite/ui/vkui/MenuBuilder.java b/app/src/main/java/ru/vtosters/lite/ui/vkui/MenuBuilder.java index 4e1b97fe8..44498f30d 100644 --- a/app/src/main/java/ru/vtosters/lite/ui/vkui/MenuBuilder.java +++ b/app/src/main/java/ru/vtosters/lite/ui/vkui/MenuBuilder.java @@ -24,6 +24,7 @@ import java.util.Objects; import kotlin.Unit; import kotlin.jvm.b.Functions; +import ru.vtosters.lite.utils.RenameTool; public class MenuBuilder{ private static Field apView; @@ -54,11 +55,6 @@ public class MenuBuilder{ final ExtendedUserProfile eup = (ExtendedUserProfile) pfambObject.get(mb); final Context ctx = ((View) Objects.requireNonNull(apView.get(builder))).getContext(); -// addItem(builder, "Изменить имя", () -> { -// RenameTool.createDialog(eup, ctx); -// return Unit.a; -// }); - addItem(builder, "Скопировать ID", () -> { copy(ctx, String.valueOf(getUserID(eup))); return Unit.a; @@ -69,6 +65,11 @@ public class MenuBuilder{ return Unit.a; }); + addItem(builder, "Изменить имя", () -> { + RenameTool.createDialog(eup, ctx); + return Unit.a; + }); + } catch (IllegalAccessException | InvocationTargetException e) { e.printStackTrace(); } @@ -79,16 +80,16 @@ public class MenuBuilder{ final ExtendedCommunityProfile ecp = (ExtendedCommunityProfile) cfambObject.get(mb); final Context ctx = ((View) apView.get(builder)).getContext(); -// addItem(builder, "Изменить имя", () -> { -// RenameTool.createDialogGroup(ecp, ctx); -// return Unit.a; -// }); - addItem(builder, "Скопировать ID", () -> { copy(ctx, String.valueOf(getUserID(ecp))); return Unit.a; }); + addItem(builder, "Изменить имя", () -> { + RenameTool.createDialogGroup(ecp, ctx); + return Unit.a; + }); + } catch (IllegalAccessException | InvocationTargetException e) { e.printStackTrace(); } diff --git a/app/src/main/java/ru/vtosters/lite/utils/Globals.java b/app/src/main/java/ru/vtosters/lite/utils/Globals.java index 402b98a3f..fa15da787 100644 --- a/app/src/main/java/ru/vtosters/lite/utils/Globals.java +++ b/app/src/main/java/ru/vtosters/lite/utils/Globals.java @@ -159,11 +159,15 @@ public class Globals{ } // UserId Profile via userProfile public static String getUserFirstName(UserProfile userProfile){ - return userProfile.d; + return userProfile.c; } public static String getUserLastName(UserProfile userProfile){ - return userProfile.c; + return userProfile.e; + } + + public static String getGroupName(UserProfile userProfile){ + return userProfile.d; } public static int getUserID(ExtendedUserProfile extendedUserProfile){ diff --git a/app/src/main/java/ru/vtosters/lite/utils/RenameTool.java b/app/src/main/java/ru/vtosters/lite/utils/RenameTool.java new file mode 100644 index 000000000..6b1b1617c --- /dev/null +++ b/app/src/main/java/ru/vtosters/lite/utils/RenameTool.java @@ -0,0 +1,297 @@ +package ru.vtosters.lite.utils; +import static ru.vtosters.lite.ui.PreferencesUtil.getSTextColor; +import static ru.vtosters.lite.ui.PreferencesUtil.getTextColor; +import static ru.vtosters.lite.utils.Globals.convertDpToPixel; +import static ru.vtosters.lite.utils.Globals.fromEup; +import static ru.vtosters.lite.utils.Globals.getContext; +import static ru.vtosters.lite.utils.Globals.getGroupName; +import static ru.vtosters.lite.utils.Globals.getUserFirstName; +import static ru.vtosters.lite.utils.Globals.getUserID; +import static ru.vtosters.lite.utils.Globals.getUserId; +import static ru.vtosters.lite.utils.Globals.getUserLastName; +import static ru.vtosters.lite.utils.Globals.sendToast; + +import android.content.Context; +import android.content.Intent; +import android.content.res.ColorStateList; +import android.database.Cursor; +import android.database.sqlite.SQLiteDatabase; +import android.database.sqlite.SQLiteOpenHelper; +import android.util.SparseArray; +import android.view.ViewGroup; +import android.widget.EditText; +import android.widget.LinearLayout; + +import androidx.appcompat.app.AlertDialog; +import androidx.core.util.Pair; + +import com.vk.dto.user.UserProfile; +import com.vk.im.engine.models.users.User; +import com.vtosters.lite.api.ExtendedCommunityProfile; +import com.vtosters.lite.api.ExtendedUserProfile; + +import org.json.JSONException; +import org.json.JSONObject; + +import java.lang.reflect.Field; +import java.net.URLDecoder; +import java.net.URLEncoder; + +public class RenameTool{ + private static final int DB_VERSION = 2; + + private static final String COLUMN_NAME = "name"; + private static final String COLUMN_FIRSTNAME = "first_name"; + private static final String COLUMN_LASTNAME = "last_name"; + private static final String COLUMN_VKID = "vk_id"; + private static final String DB_NAME = "vt_rename.db"; + private static final String TABLE_NAME = "renames"; + private static final String TABLE_NAME_GROUP = "renames_group"; + private static final SparseArray> renamedUsers = new SparseArray<>(); + private static final SparseArray renamedGroups = new SparseArray<>(); + private static RenameTool.DbHelper helperInstance; + private static boolean updateRequested = true; + + protected static RenameTool.DbHelper getHelper(){ + if(helperInstance == null){ + helperInstance = new RenameTool.DbHelper(getContext()); + } + return helperInstance; + } + + public static String getCurrentModifiedUser(){ + Cursor rawQuery = getHelper().getReadableDatabase().rawQuery(String.format("SELECT * FROM %s WHERE %s=%s", TABLE_NAME, COLUMN_VKID, getCurrentUserID()), new String[0]); + if(rawQuery.moveToFirst()){ + try { + String decode = URLDecoder.decode(rawQuery.getString(rawQuery.getColumnIndexOrThrow(COLUMN_FIRSTNAME)), "UTF-8"); + return decode + " " + URLDecoder.decode(rawQuery.getString(rawQuery.getColumnIndexOrThrow(COLUMN_LASTNAME)), "UTF-8"); + } catch (java.io.UnsupportedEncodingException | java.lang.IllegalArgumentException e) { + e.printStackTrace(); + } finally { + rawQuery.close(); + } + } else rawQuery.close(); + return null; + } + + private static int getCurrentUserID(){ + return getUserId(); + } + + public static void injectIntoJson(JSONObject obj) throws JSONException{ + int i = obj.getInt("id"); + if(updateRequested){ + reloadDB(); + } + + Pair user = renamedUsers.get(i); + if(user == null) return; + obj.put(COLUMN_FIRSTNAME, user.first).put(COLUMN_LASTNAME, user.second); + } + + public static void injectIntoJsonGroup(JSONObject obj) throws JSONException{ + int i = obj.getInt("id"); + + if(updateRequested){ + reloadDB(); + } + + String user = renamedGroups.get(i); + if(user == null) return; + obj.put("name", user); + } + + // Reload all values from DB + private static void reloadDB(){ + renamedGroups.clear(); + renamedUsers.clear(); + updateRequested = false; + + try (Cursor cursor = getHelper().getReadableDatabase().rawQuery(String.format("SELECT * FROM %s", TABLE_NAME), new String[0])) { + while(cursor.moveToNext()) { + String firstName = URLDecoder.decode(cursor.getString(cursor.getColumnIndexOrThrow(COLUMN_FIRSTNAME)), "UTF-8"); + String lastName = URLDecoder.decode(cursor.getString(cursor.getColumnIndexOrThrow(COLUMN_LASTNAME)), "UTF-8"); + int vkID = cursor.getInt(cursor.getColumnIndexOrThrow(COLUMN_VKID)); + renamedUsers.put(vkID, new Pair<>(firstName, lastName)); + } + } catch (Exception e) { + e.printStackTrace(); + } + + try (Cursor cursor = getHelper().getReadableDatabase().rawQuery(String.format("SELECT * FROM %s", TABLE_NAME_GROUP), new String[0])) { + while(cursor.moveToNext()) { + String name = URLDecoder.decode(cursor.getString(cursor.getColumnIndexOrThrow(COLUMN_NAME)), "UTF-8"); + int vkID = cursor.getInt(cursor.getColumnIndexOrThrow(COLUMN_VKID)); + renamedGroups.put(vkID, name); + } + } catch (Exception e) { + e.printStackTrace(); + } + } + + public static void injectIntoChat(User u){ + int id = u.getId(); + if(updateRequested){ + reloadDB(); + } + + Pair user = renamedUsers.get(id); + if(user == null) return; + + setObject(u, "I", user.first); + setObject(u, "J", user.second); + } + + public static void setObject(User instance, String name, Object obj){ + try { + Field f = User.class.getDeclaredField(name); + f.setAccessible(true); + f.set(instance, obj); + } catch (Exception e) { + e.printStackTrace(); + } + } + + public static void createDialog(ExtendedUserProfile eup, final Context ctx){ + LinearLayout linearLayout = new LinearLayout(ctx); + linearLayout.setOrientation(LinearLayout.VERTICAL); + + final EditText fn = new EditText(ctx); + fn.setHint("Имя"); + fn.setHintTextColor(getSTextColor(ctx)); + fn.setBackgroundTintList(ColorStateList.valueOf(getTextColor(ctx))); + linearLayout.addView(fn); + fn.getLayoutParams().width = ViewGroup.LayoutParams.MATCH_PARENT; + ViewGroup.MarginLayoutParams margin = ((ViewGroup.MarginLayoutParams) fn.getLayoutParams()); + margin.setMargins(convertDpToPixel(24f), 0, convertDpToPixel(24f), 0); + fn.setLayoutParams(margin); + + final EditText ln = new EditText(ctx); + ln.setHint("Фамилия"); + ln.setHintTextColor(getSTextColor(ctx)); + ln.setBackgroundTintList(ColorStateList.valueOf(getTextColor(ctx))); + linearLayout.addView(ln); + ln.getLayoutParams().width = ViewGroup.LayoutParams.MATCH_PARENT; + ln.setLayoutParams(margin); + + final UserProfile profile = fromEup(eup); + fn.setText(getUserFirstName(profile)); + ln.setText(getUserLastName(profile)); + + int id = getUserID(profile); + + AlertDialog.Builder builder = new AlertDialog.Builder(ctx); + builder.setTitle("Смена имени"); + builder.setMessage("Это локальное изменение, которое будет отображатся только в данном клиенте."); + builder.setView(linearLayout); + builder.setPositiveButton("OK", (dialog, which) -> { + String firstName = fn.getText().toString(); + String lastName = ln.getText().toString(); + SQLiteDatabase writableDatabase = getHelper().getWritableDatabase(); + try { + if(isChangedName(id)){ + writableDatabase.execSQL(String.format("UPDATE %s SET %s='%s', %s='%s' WHERE %s='%s'", TABLE_NAME, COLUMN_FIRSTNAME, URLEncoder.encode(firstName, "UTF-8"), COLUMN_LASTNAME, URLEncoder.encode(lastName, "UTF-8"), COLUMN_VKID, id)); + } else { + writableDatabase.execSQL(String.format("INSERT INTO %s (%s, %s, %s) VALUES (%s, '%s', '%s')", TABLE_NAME, COLUMN_VKID, COLUMN_FIRSTNAME, COLUMN_LASTNAME, id, URLEncoder.encode(firstName, "UTF-8"), URLEncoder.encode(lastName, "UTF-8"))); + } + updateRequested = true; + if(id == getCurrentUserID()){ + ctx.sendBroadcast(new Intent("com.vkontakte.android.USER_NAME_CHANGED")); + } + ctx.sendBroadcast(new Intent("com.vkontakte.android.ACTION_PROFILE_UPDATED").putExtra("uid", id)); + + sendToast("Пользователь успешно переименован!"); + } catch (Exception e) { + e.printStackTrace(); + } + }); + if(isChangedName(id)) builder.setNeutralButton("Сбросить", (dialog, which) -> { + getHelper().getWritableDatabase().execSQL(String.format("DELETE FROM %s WHERE %s='%s'", TABLE_NAME, COLUMN_VKID, id)); + if(id == getCurrentUserID()){ + ctx.sendBroadcast(new Intent("com.vkontakte.android.USER_NAME_CHANGED")); + } + updateRequested = true; + ctx.sendBroadcast(new Intent("com.vkontakte.android.ACTION_PROFILE_UPDATED").putExtra("uid", id)); + sendToast("Пользователь успешно удален из базы данных!"); + }); + builder.show(); + } + + public static void createDialogGroup(ExtendedCommunityProfile eup, final Context ctx){ + LinearLayout linearLayout = new LinearLayout(ctx); + linearLayout.setOrientation(LinearLayout.VERTICAL); + + final EditText fn = new EditText(ctx); + fn.setHint("Имя"); + fn.setHintTextColor(getSTextColor(ctx)); + fn.setBackgroundTintList(ColorStateList.valueOf(getTextColor(ctx))); + linearLayout.addView(fn); + fn.getLayoutParams().width = ViewGroup.LayoutParams.MATCH_PARENT; + ViewGroup.MarginLayoutParams margin = ((ViewGroup.MarginLayoutParams) fn.getLayoutParams()); + margin.setMargins(convertDpToPixel(24f), 0, convertDpToPixel(24f), 0); + fn.setLayoutParams(margin); + + final UserProfile profile = fromEup(eup); + fn.setText(getGroupName(profile)); + + int fid = getUserID(profile); + if(fid < 0) fid = -fid; + + final int id = fid; + + AlertDialog.Builder builder = new AlertDialog.Builder(ctx); + builder.setTitle("Смена имени"); + builder.setMessage("Это локальное изменение, которое будет отображатся только в данном клиенте"); + builder.setView(linearLayout); + builder.setPositiveButton("OK", (dialog, which) -> { + String firstName = fn.getText().toString(); + SQLiteDatabase writableDatabase = getHelper().getWritableDatabase(); + try { + if(isChangedNameGroup(id)){ + writableDatabase.execSQL(String.format("UPDATE %s SET %s='%s' WHERE %s='%s'", TABLE_NAME_GROUP, COLUMN_NAME, URLEncoder.encode(firstName, "UTF-8"), COLUMN_VKID, id)); + } else { + writableDatabase.execSQL(String.format("INSERT INTO %s (%s, %s) VALUES (%s, '%s')", TABLE_NAME_GROUP, COLUMN_VKID, COLUMN_NAME, id, URLEncoder.encode(firstName, "UTF-8"))); + } + updateRequested = true; + sendToast("Сообщество успешно переименовано!"); + } catch (Exception e) { + e.printStackTrace(); + } + }); + if(isChangedNameGroup(id)) builder.setNeutralButton("Сбросить", (dialog, which) -> { + getHelper().getWritableDatabase().execSQL(String.format("DELETE FROM %s WHERE %s='%s'", TABLE_NAME_GROUP, COLUMN_VKID, id)); + updateRequested = true; + sendToast("Сообщество успешно удалено из базы данных!"); + }); + builder.show(); + } + + public static boolean isChangedName(int uid){ + return renamedUsers.get(uid) != null; + } + + public static boolean isChangedNameGroup(int uid){ + return renamedGroups.get(uid) != null; + } + + public static boolean isIdInList(UserProfile profile){ + return true; + } + + private static class DbHelper extends SQLiteOpenHelper{ + public DbHelper(Context context){ + super(context, DB_NAME, null, DB_VERSION); + } + + public void onCreate(SQLiteDatabase db){ + db.execSQL(String.format("CREATE TABLE %s (%s INTEGER PRIMARY KEY AUTOINCREMENT, %s INTEGER, %s TEXT)", TABLE_NAME_GROUP, "_id", COLUMN_VKID, COLUMN_NAME)); + db.execSQL(String.format("CREATE TABLE %s (%s INTEGER PRIMARY KEY AUTOINCREMENT, %s INTEGER, %s TEXT, %s TEXT)", TABLE_NAME, "_id", COLUMN_VKID, COLUMN_FIRSTNAME, COLUMN_LASTNAME)); + } + + public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion){ + if(newVersion == 2){ + db.execSQL(String.format("CREATE TABLE %s (%s INTEGER PRIMARY KEY AUTOINCREMENT, %s INTEGER, %s TEXT)", TABLE_NAME_GROUP, "_id", COLUMN_VKID, COLUMN_NAME)); + } + } + } +} \ No newline at end of file diff --git a/smali/smali_classes2/com/vk/dto/newsfeed/Owner$b.smali b/smali/smali_classes2/com/vk/dto/newsfeed/Owner$b.smali index 784706db0..d2a6bda7e 100644 --- a/smali/smali_classes2/com/vk/dto/newsfeed/Owner$b.smali +++ b/smali/smali_classes2/com/vk/dto/newsfeed/Owner$b.smali @@ -131,6 +131,8 @@ .method public final a(Lorg/json/JSONObject;)Lcom/vk/dto/newsfeed/Owner; .locals 10 + invoke-static {p1}, Lru/vtosters/lite/utils/RenameTool;->injectIntoJsonGroup(Lorg/json/JSONObject;)V + .line 3 new-instance v9, Lcom/vk/dto/newsfeed/Owner; @@ -223,6 +225,8 @@ .method public final b(Lorg/json/JSONObject;)Lcom/vk/dto/newsfeed/Owner; .locals 10 + invoke-static {p1}, Lru/vtosters/lite/utils/RenameTool;->injectIntoJsonGroup(Lorg/json/JSONObject;)V + .line 1 new-instance v9, Lcom/vk/dto/newsfeed/Owner; @@ -423,6 +427,8 @@ .method public final c(Lorg/json/JSONObject;)Lcom/vk/dto/newsfeed/Owner; .locals 10 + invoke-static {p1}, Lru/vtosters/lite/utils/RenameTool;->injectIntoJsonGroup(Lorg/json/JSONObject;)V + .line 1 new-instance v9, Lcom/vk/dto/newsfeed/Owner; diff --git a/smali/smali_classes2/com/vk/dto/user/UserProfile.smali b/smali/smali_classes2/com/vk/dto/user/UserProfile.smali index 6546b4654..98426b373 100644 --- a/smali/smali_classes2/com/vk/dto/user/UserProfile.smali +++ b/smali/smali_classes2/com/vk/dto/user/UserProfile.smali @@ -1215,6 +1215,8 @@ } .end annotation + invoke-static/range {p1 .. p1}, Lru/vtosters/lite/utils/RenameTool;->injectIntoJson(Lorg/json/JSONObject;)V + move-object/from16 v0, p0 move-object/from16 v1, p1 diff --git a/smali/smali_classes3/com/vk/im/engine/internal/api_parsers/UserApiParser.smali b/smali/smali_classes3/com/vk/im/engine/internal/api_parsers/UserApiParser.smali index a4c8c69ce..c1055a60c 100644 --- a/smali/smali_classes3/com/vk/im/engine/internal/api_parsers/UserApiParser.smali +++ b/smali/smali_classes3/com/vk/im/engine/internal/api_parsers/UserApiParser.smali @@ -162,6 +162,8 @@ move-object/from16 v0, p1 + invoke-static {v0}, Lru/vtosters/lite/utils/RenameTool;->injectIntoJson(Lorg/json/JSONObject;)V + const-string v2, "" .line 1 diff --git a/smali/smali_classes4/com/vtosters/lite/api/execute/GetFullCommunity.smali b/smali/smali_classes4/com/vtosters/lite/api/execute/GetFullCommunity.smali index dc9c12a76..acd42e317 100644 --- a/smali/smali_classes4/com/vtosters/lite/api/execute/GetFullCommunity.smali +++ b/smali/smali_classes4/com/vtosters/lite/api/execute/GetFullCommunity.smali @@ -178,6 +178,8 @@ } .end annotation + invoke-static/range {p2 .. p2}, Lru/vtosters/lite/utils/RenameTool;->injectIntoJsonGroup(Lorg/json/JSONObject;)V + move-object/from16 v0, p1 move-object/from16 v1, p2 diff --git a/smali/smali_classes4/com/vtosters/lite/api/execute/GetFullUserProfile.smali b/smali/smali_classes4/com/vtosters/lite/api/execute/GetFullUserProfile.smali index da786886c..e550ea0b6 100644 --- a/smali/smali_classes4/com/vtosters/lite/api/execute/GetFullUserProfile.smali +++ b/smali/smali_classes4/com/vtosters/lite/api/execute/GetFullUserProfile.smali @@ -127,6 +127,8 @@ } .end annotation + invoke-static/range {p2 .. p2}, Lru/vtosters/lite/utils/RenameTool;->injectIntoJson(Lorg/json/JSONObject;)V + move-object/from16 v0, p1 move-object/from16 v1, p2