diff --git a/AnkiDroid/src/main/java/com/ichi2/anki/DeckPicker.java b/AnkiDroid/src/main/java/com/ichi2/anki/DeckPicker.java
index 502b9ff82201..af1028068541 100644
--- a/AnkiDroid/src/main/java/com/ichi2/anki/DeckPicker.java
+++ b/AnkiDroid/src/main/java/com/ichi2/anki/DeckPicker.java
@@ -439,8 +439,8 @@ public void onClick(View v) {
onSdCardNotMounted();
} else if (!CollectionHelper.isCurrentAnkiDroidDirAccessible(this)) {
// AnkiDroid directory inaccessible
- Intent prefIntent = CompatHelper.getCompat().getAdvancedPreferencesIntent(this);
- startActivityForResultWithoutAnimation(prefIntent, REQUEST_PATH_UPDATE);
+ Intent i = CompatHelper.getCompat().getPreferenceSubscreenIntent(this, "com.ichi2.anki.prefs.advanced");
+ startActivityForResultWithoutAnimation(i, REQUEST_PATH_UPDATE);
Toast.makeText(this, R.string.directory_inaccessible, Toast.LENGTH_LONG).show();
} else {
showDatabaseErrorDialog(DatabaseErrorDialog.DIALOG_LOAD_FAILED);
diff --git a/AnkiDroid/src/main/java/com/ichi2/anki/Preferences.java b/AnkiDroid/src/main/java/com/ichi2/anki/Preferences.java
index b3b44e48a0fd..a1cfc6cd60d4 100644
--- a/AnkiDroid/src/main/java/com/ichi2/anki/Preferences.java
+++ b/AnkiDroid/src/main/java/com/ichi2/anki/Preferences.java
@@ -181,6 +181,7 @@ protected void onResume() {
// syncAccount's summary can change while preferences are still open (user logs
// in from preferences screen), so we need to update it here.
updatePreference(prefs, "syncAccount", this);
+ updatePreference(prefs, "custom_sync_server_link", this);
}
}
@@ -282,6 +283,16 @@ public boolean onPreferenceChange(Preference preference, final Object newValue)
}
}
});
+ // Custom sync server option
+ Preference customSyncServerPreference = screen.findPreference("custom_sync_server_link");
+ customSyncServerPreference.setOnPreferenceClickListener(new OnPreferenceClickListener() {
+ public boolean onPreferenceClick(Preference preference) {
+ Intent i = CompatHelper.getCompat().getPreferenceSubscreenIntent(Preferences.this,
+ "com.ichi2.anki.prefs.custom_sync_server");
+ startActivity(i);
+ return true;
+ }
+ });
// Force full sync option
Preference fullSyncPreference = screen.findPreference("force_full_sync");
fullSyncPreference.setOnPreferenceClickListener(new OnPreferenceClickListener() {
@@ -296,6 +307,10 @@ public boolean onPreferenceClick(Preference preference) {
// Workaround preferences
removeUnnecessaryAdvancedPrefs(screen);
break;
+ case "com.ichi2.anki.prefs.custom_sync_server":
+ getSupportActionBar().setTitle(R.string.custom_sync_server_title);
+ listener.addPreferencesFromResource(R.xml.preferences_custom_sync_server);
+ break;
}
}
@@ -374,7 +389,6 @@ private void initPreference(Preference pref) {
CharSequence s = pref.getSummary();
mOriginalSumarries.put(pref.getKey(), (s != null) ? s.toString() : "");
// Update summary
-
updateSummary(pref);
}
@@ -515,8 +529,15 @@ private void updateSummary(Preference pref) {
if (pref == null || pref.getKey() == null) {
return;
}
+ // Handle special cases
if (pref.getKey().equals("about_dialog_preference")) {
pref.setSummary(getResources().getString(R.string.about_version) + " " + VersionUtils.getPkgVersionName());
+ } else if (pref.getKey().equals("custom_sync_server_link")) {
+ if (!AnkiDroidApp.getSharedPrefs(this).getBoolean("useCustomSyncServer", false)) {
+ pref.setSummary(R.string.disabled);
+ } else {
+ pref.setSummary(AnkiDroidApp.getSharedPrefs(this).getString("syncBaseUrl", ""));
+ }
}
// Get value text
String value;
@@ -709,6 +730,7 @@ public void onResume() {
// syncAccount's summary can change while preferences are still open (user logs
// in from preferences screen), so we need to update it here.
((Preferences) getActivity()).updatePreference(prefs, "syncAccount", this);
+ ((Preferences) getActivity()).updatePreference(prefs, "custom_sync_server_link", this);
}
@Override
diff --git a/AnkiDroid/src/main/java/com/ichi2/compat/Compat.java b/AnkiDroid/src/main/java/com/ichi2/compat/Compat.java
index d41bfebd0123..df5833efad23 100644
--- a/AnkiDroid/src/main/java/com/ichi2/compat/Compat.java
+++ b/AnkiDroid/src/main/java/com/ichi2/compat/Compat.java
@@ -59,6 +59,6 @@ public interface Compat {
void setSelectableBackground(View view);
void openUrl(AnkiActivity activity, Uri uri);
void supportAddContentMenu(final DeckPicker a);
- Intent getAdvancedPreferencesIntent(Context context);
+ Intent getPreferenceSubscreenIntent(Context context, String subscreen);
}
diff --git a/AnkiDroid/src/main/java/com/ichi2/compat/CompatV10.java b/AnkiDroid/src/main/java/com/ichi2/compat/CompatV10.java
index 3d3b93aab9ea..ea93b1f91833 100644
--- a/AnkiDroid/src/main/java/com/ichi2/compat/CompatV10.java
+++ b/AnkiDroid/src/main/java/com/ichi2/compat/CompatV10.java
@@ -161,10 +161,10 @@ public void onClick(@NonNull MaterialDialog d, @NonNull DialogAction w) {
}
@Override
- public Intent getAdvancedPreferencesIntent(Context context) {
+ public Intent getPreferenceSubscreenIntent(Context context, String subscreen) {
// We're using "legacy preference headers" below API 11
Intent i = new Intent(context, Preferences.class);
- i.setAction("com.ichi2.anki.prefs.advanced");
+ i.setAction(subscreen);
return i;
}
}
\ No newline at end of file
diff --git a/AnkiDroid/src/main/java/com/ichi2/compat/CompatV11.java b/AnkiDroid/src/main/java/com/ichi2/compat/CompatV11.java
index 53e3079f308b..4f7fcfcfaea5 100644
--- a/AnkiDroid/src/main/java/com/ichi2/compat/CompatV11.java
+++ b/AnkiDroid/src/main/java/com/ichi2/compat/CompatV11.java
@@ -38,12 +38,13 @@ public void disableDatabaseWriteAheadLogging(SQLiteDatabase db) {
}
@Override
- public Intent getAdvancedPreferencesIntent(Context context) {
+ public Intent getPreferenceSubscreenIntent(Context context, String subscreen) {
Intent i = new Intent(context, Preferences.class);
i.putExtra(PreferenceActivity.EXTRA_SHOW_FRAGMENT, "com.ichi2.anki.Preferences$SettingsFragment");
Bundle extras = new Bundle();
- extras.putString("subscreen", "com.ichi2.anki.prefs.advanced");
+ extras.putString("subscreen", subscreen);
i.putExtra(PreferenceActivity.EXTRA_SHOW_FRAGMENT_ARGUMENTS, extras);
+ i.putExtra(PreferenceActivity.EXTRA_NO_HEADERS, true);
return i;
}
}
diff --git a/AnkiDroid/src/main/java/com/ichi2/libanki/sync/FullSyncer.java b/AnkiDroid/src/main/java/com/ichi2/libanki/sync/FullSyncer.java
index 6e4733c0e13e..8f0b914dca78 100644
--- a/AnkiDroid/src/main/java/com/ichi2/libanki/sync/FullSyncer.java
+++ b/AnkiDroid/src/main/java/com/ichi2/libanki/sync/FullSyncer.java
@@ -16,11 +16,13 @@
package com.ichi2.libanki.sync;
+import android.content.SharedPreferences;
import android.database.sqlite.SQLiteDatabaseCorruptException;
import com.ichi2.anki.AnkiDatabaseManager;
import com.ichi2.anki.AnkiDb;
+import com.ichi2.anki.AnkiDroidApp;
import com.ichi2.anki.R;
import com.ichi2.anki.exception.UnknownHttpResponseException;
import com.ichi2.async.Connection;
@@ -60,6 +62,13 @@ public FullSyncer(Collection col, String hkey, Connection con) {
@Override
public String syncURL() {
+ // Allow user to specify custom sync server
+ SharedPreferences userPreferences = AnkiDroidApp.getSharedPrefs(AnkiDroidApp.getInstance());
+ if (userPreferences!= null && userPreferences.getBoolean("useCustomSyncServer", false)) {
+ File syncBase = new File(userPreferences.getString("syncBaseUrl", Consts.SYNC_BASE));
+ return new File(syncBase, "/sync").toString() + "/";
+ }
+ // Usual case
return Consts.SYNC_BASE + "sync/";
}
diff --git a/AnkiDroid/src/main/java/com/ichi2/libanki/sync/HttpSyncer.java b/AnkiDroid/src/main/java/com/ichi2/libanki/sync/HttpSyncer.java
index cfa39d8067a5..3ed608d7caac 100644
--- a/AnkiDroid/src/main/java/com/ichi2/libanki/sync/HttpSyncer.java
+++ b/AnkiDroid/src/main/java/com/ichi2/libanki/sync/HttpSyncer.java
@@ -20,6 +20,8 @@
+import android.content.SharedPreferences;
+
import com.ichi2.anki.AnkiDroidApp;
import com.ichi2.anki.exception.UnknownHttpResponseException;
import com.ichi2.async.Connection;
@@ -448,6 +450,13 @@ public HttpResponse register(String user, String pw) throws UnknownHttpResponseE
public String syncURL() {
+ // Allow user to specify custom sync server
+ SharedPreferences userPreferences = AnkiDroidApp.getSharedPrefs(AnkiDroidApp.getInstance());
+ if (userPreferences!= null && userPreferences.getBoolean("useCustomSyncServer", false)) {
+ File syncBase = new File(userPreferences.getString("syncBaseUrl", Consts.SYNC_BASE));
+ return new File(syncBase, "/sync").toString() + "/";
+ }
+ // Usual case
return Consts.SYNC_BASE + "sync/";
}
}
diff --git a/AnkiDroid/src/main/java/com/ichi2/libanki/sync/RemoteMediaServer.java b/AnkiDroid/src/main/java/com/ichi2/libanki/sync/RemoteMediaServer.java
index 8a27e17bf36b..9b5b768c4cde 100644
--- a/AnkiDroid/src/main/java/com/ichi2/libanki/sync/RemoteMediaServer.java
+++ b/AnkiDroid/src/main/java/com/ichi2/libanki/sync/RemoteMediaServer.java
@@ -17,8 +17,10 @@
package com.ichi2.libanki.sync;
+import android.content.SharedPreferences;
import android.text.TextUtils;
+import com.ichi2.anki.AnkiDroidApp;
import com.ichi2.anki.exception.MediaSyncException;
import com.ichi2.anki.exception.UnknownHttpResponseException;
import com.ichi2.async.Connection;
@@ -55,6 +57,13 @@ public RemoteMediaServer(Collection col, String hkey, Connection con) {
@Override
public String syncURL() {
+ // Allow user to specify custom sync server
+ SharedPreferences userPreferences = AnkiDroidApp.getSharedPrefs(AnkiDroidApp.getInstance());
+ if (userPreferences!= null && userPreferences.getBoolean("useCustomSyncServer", false)) {
+ File mediaSyncBase = new File(userPreferences.getString("syncMediaUrl", Consts.SYNC_MEDIA_BASE));
+ return mediaSyncBase.toString() + "/";
+ }
+ // Usual case
return Consts.SYNC_MEDIA_BASE;
}
diff --git a/AnkiDroid/src/main/res/layout/my_account.xml b/AnkiDroid/src/main/res/layout/my_account.xml
index 835ef05346fc..e6d0605b63c5 100644
--- a/AnkiDroid/src/main/res/layout/my_account.xml
+++ b/AnkiDroid/src/main/res/layout/my_account.xml
@@ -108,8 +108,15 @@
android:text="@string/sign_up_description"
android:layout_gravity="center"
android:textSize="@dimen/abc_text_size_button_material"
- android:textStyle="bold"
- />
+ android:textStyle="bold"/>
+