Fix account data migration for real

This commit is contained in:
Grishka
2024-10-01 23:19:48 +03:00
parent cb0d7e73d4
commit 77b6344032
6 changed files with 65 additions and 35 deletions

View File

@@ -13,7 +13,7 @@ android {
applicationId "org.joinmastodon.android" applicationId "org.joinmastodon.android"
minSdk 23 minSdk 23
targetSdk 34 targetSdk 34
versionCode 117 versionCode 118
versionName "2.7.0" versionName "2.7.0"
testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner" testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"
} }

View File

@@ -35,7 +35,7 @@
*; *;
} }
-keepnames public class org.joinmastodon.android.api.session**{ -keepnames public class org.joinmastodon.android.api.session.**{
*; *;
} }

View File

@@ -1,7 +1,11 @@
package org.joinmastodon.android.api.session; package org.joinmastodon.android.api.session;
import com.google.gson.annotations.SerializedName;
public class AccountActivationInfo{ public class AccountActivationInfo{
@SerializedName(value="email", alternate="a")
public String email; public String email;
@SerializedName(value="last_email_confirmation_resend", alternate="b")
public long lastEmailConfirmationResend; public long lastEmailConfirmationResend;
public AccountActivationInfo(String email, long lastEmailConfirmationResend){ public AccountActivationInfo(String email, long lastEmailConfirmationResend){

View File

@@ -9,6 +9,7 @@ import android.util.Log;
import com.google.gson.JsonObject; import com.google.gson.JsonObject;
import com.google.gson.JsonParser; import com.google.gson.JsonParser;
import com.google.gson.annotations.SerializedName;
import com.google.gson.reflect.TypeToken; import com.google.gson.reflect.TypeToken;
import org.joinmastodon.android.E; import org.joinmastodon.android.E;
@@ -30,7 +31,6 @@ import org.joinmastodon.android.model.Application;
import org.joinmastodon.android.model.FilterAction; import org.joinmastodon.android.model.FilterAction;
import org.joinmastodon.android.model.FilterContext; import org.joinmastodon.android.model.FilterContext;
import org.joinmastodon.android.model.FilterResult; import org.joinmastodon.android.model.FilterResult;
import org.joinmastodon.android.model.FollowList;
import org.joinmastodon.android.model.Instance; import org.joinmastodon.android.model.Instance;
import org.joinmastodon.android.model.LegacyFilter; import org.joinmastodon.android.model.LegacyFilter;
import org.joinmastodon.android.model.Preferences; import org.joinmastodon.android.model.Preferences;
@@ -57,21 +57,37 @@ public class AccountSession{
public static final int FLAG_ACTIVATED=1; public static final int FLAG_ACTIVATED=1;
public static final int FLAG_NEED_UPDATE_PUSH_SETTINGS=1 << 1; public static final int FLAG_NEED_UPDATE_PUSH_SETTINGS=1 << 1;
@SerializedName(value="token", alternate="a")
public Token token; public Token token;
@SerializedName(value="self", alternate="b")
public Account self; public Account self;
@SerializedName(value="domain", alternate="c")
public String domain; public String domain;
@SerializedName(value="app", alternate="d")
public Application app; public Application app;
@SerializedName(value="info_last_updated", alternate="e")
public long infoLastUpdated; public long infoLastUpdated;
@SerializedName(value="activated", alternate="f")
public boolean activated=true; public boolean activated=true;
@SerializedName(value="push_private_key", alternate="g")
public String pushPrivateKey; public String pushPrivateKey;
@SerializedName(value="push_public_key", alternate="h")
public String pushPublicKey; public String pushPublicKey;
@SerializedName(value="push_auth_key", alternate="i")
public String pushAuthKey; public String pushAuthKey;
@SerializedName(value="push_subscription", alternate="j")
public PushSubscription pushSubscription; public PushSubscription pushSubscription;
@SerializedName(value="need_update_push_settings", alternate="k")
public boolean needUpdatePushSettings; public boolean needUpdatePushSettings;
@SerializedName(value="filters_last_updated", alternate="l")
public long filtersLastUpdated; public long filtersLastUpdated;
@SerializedName(value="word_filters", alternate="m")
public List<LegacyFilter> wordFilters=new ArrayList<>(); public List<LegacyFilter> wordFilters=new ArrayList<>();
@SerializedName(value="push_account_i_d", alternate="n")
public String pushAccountID; public String pushAccountID;
@SerializedName(value="activation_info", alternate="o")
public AccountActivationInfo activationInfo; public AccountActivationInfo activationInfo;
@SerializedName(value="preferences", alternate="p")
public Preferences preferences; public Preferences preferences;
private transient MastodonAPIController apiController; private transient MastodonAPIController apiController;
private transient StatusInteractionController statusInteractionController; private transient StatusInteractionController statusInteractionController;

View File

@@ -19,6 +19,7 @@ import android.net.Uri;
import android.os.Build; import android.os.Build;
import android.util.Log; import android.util.Log;
import com.google.gson.JsonArray;
import com.google.gson.JsonElement; import com.google.gson.JsonElement;
import com.google.gson.JsonObject; import com.google.gson.JsonObject;
import com.google.gson.JsonParser; import com.google.gson.JsonParser;
@@ -649,6 +650,7 @@ public class AccountSessionManager{
`last_updated` bigint, `last_updated` bigint,
`version` integer NOT NULL DEFAULT 1 `version` integer NOT NULL DEFAULT 1
)"""); )""");
maybeMigrateAccounts(db);
} }
@Override @Override
@@ -662,37 +664,7 @@ public class AccountSessionManager{
`emojis` text, `emojis` text,
`last_updated` bigint `last_updated` bigint
)"""); )""");
maybeMigrateAccounts(db);
File accountsFile=new File(MastodonApp.context.getFilesDir(), "accounts.json");
if(accountsFile.exists()){
HashSet<String> domains=new HashSet<>();
try(FileInputStream in=new FileInputStream(accountsFile)){
JsonObject jobj=JsonParser.parseReader(new InputStreamReader(in, StandardCharsets.UTF_8)).getAsJsonObject();
ContentValues values=new ContentValues();
for(JsonElement jacc:jobj.getAsJsonArray("accounts")){
AccountSession session=MastodonAPIController.gson.fromJson(jacc, AccountSession.class);
domains.add(session.domain.toLowerCase());
session.toContentValues(values);
db.insertWithOnConflict("accounts", null, values, SQLiteDatabase.CONFLICT_REPLACE);
}
}catch(Exception x){
Log.e(TAG, "Error migrating accounts", x);
return;
}
accountsFile.delete();
for(String domain:domains){
File file=new File(MastodonApp.context.getFilesDir(), "instance_"+domain.replace('.', '_')+".json");
try(FileInputStream in=new FileInputStream(file)){
JsonObject jobj=JsonParser.parseReader(new InputStreamReader(in, StandardCharsets.UTF_8)).getAsJsonObject();
insertInstanceIntoDatabase(db, domain, MastodonAPIController.gson.fromJson(jobj.get("instance"), Instance.class),
MastodonAPIController.gson.fromJson(jobj.get("emojis"), new TypeToken<>(){}.getType()), jobj.get("last_updated").getAsLong());
}catch(Exception x){
Log.w(TAG, "Error reading instance info file for "+domain, x);
}
file.delete();
}
}
} }
if(oldVersion<3){ if(oldVersion<3){
db.execSQL("ALTER TABLE `instances` ADD `version` integer NOT NULL DEFAULT 1"); db.execSQL("ALTER TABLE `instances` ADD `version` integer NOT NULL DEFAULT 1");
@@ -717,5 +689,39 @@ public class AccountSessionManager{
`preferences` text `preferences` text
)"""); )""");
} }
private void maybeMigrateAccounts(SQLiteDatabase db){
File accountsFile=new File(MastodonApp.context.getFilesDir(), "accounts.json");
if(accountsFile.exists()){
HashSet<String> domains=new HashSet<>();
try(FileInputStream in=new FileInputStream(accountsFile)){
JsonObject jobj=JsonParser.parseReader(new InputStreamReader(in, StandardCharsets.UTF_8)).getAsJsonObject();
ContentValues values=new ContentValues();
JsonArray accounts=jobj.has("a") ? jobj.getAsJsonArray("a") : jobj.getAsJsonArray("accounts");
for(JsonElement jacc:accounts){
AccountSession session=MastodonAPIController.gson.fromJson(jacc, AccountSession.class);
domains.add(session.domain.toLowerCase());
session.toContentValues(values);
db.insertWithOnConflict("accounts", null, values, SQLiteDatabase.CONFLICT_REPLACE);
}
}catch(Exception x){
Log.e(TAG, "Error migrating accounts", x);
return;
}
accountsFile.delete();
for(String domain:domains){
File file=new File(MastodonApp.context.getFilesDir(), "instance_"+domain.replace('.', '_')+".json");
try(FileInputStream in=new FileInputStream(file)){
JsonObject jobj=JsonParser.parseReader(new InputStreamReader(in, StandardCharsets.UTF_8)).getAsJsonObject();
insertInstanceIntoDatabase(db, domain, MastodonAPIController.gson.fromJson(jobj.get("instance"), Instance.class),
MastodonAPIController.gson.fromJson(jobj.get("emojis"), new TypeToken<>(){}.getType()), jobj.get("last_updated").getAsLong());
}catch(Exception x){
Log.w(TAG, "Error reading instance info file for "+domain, x);
}
file.delete();
}
}
}
} }
} }

View File

@@ -30,6 +30,7 @@ import org.joinmastodon.android.events.StatusDisplaySettingsChangedEvent;
import org.joinmastodon.android.fragments.discover.DiscoverFragment; import org.joinmastodon.android.fragments.discover.DiscoverFragment;
import org.joinmastodon.android.fragments.onboarding.OnboardingFollowSuggestionsFragment; import org.joinmastodon.android.fragments.onboarding.OnboardingFollowSuggestionsFragment;
import org.joinmastodon.android.model.Account; import org.joinmastodon.android.model.Account;
import org.joinmastodon.android.model.Instance;
import org.joinmastodon.android.model.Notification; import org.joinmastodon.android.model.Notification;
import org.joinmastodon.android.model.NotificationType; import org.joinmastodon.android.model.NotificationType;
import org.joinmastodon.android.ui.OutlineProviders; import org.joinmastodon.android.ui.OutlineProviders;
@@ -291,7 +292,10 @@ public class HomeFragment extends AppKitFragment{
} }
private void reloadNotificationsForUnreadCount(){ private void reloadNotificationsForUnreadCount(){
if(AccountSessionManager.get(accountID).getInstanceInfo().getApiVersion()>=2){ Instance instance=AccountSessionManager.get(accountID).getInstanceInfo();
if(instance==null)
return;
if(instance.getApiVersion()>=2){
new GetUnreadNotificationsCount() new GetUnreadNotificationsCount()
.setCallback(new Callback<>(){ .setCallback(new Callback<>(){
@Override @Override