mirror of
https://codeberg.org/comaps/comaps
synced 2025-12-19 13:03:36 +00:00
[android][sdk] Add build config to sdk module
Signed-off-by: Andrei Shkrob <github@shkrob.dev>
This commit is contained in:
committed by
Konstantin Pastbin
parent
a8353a6a80
commit
3a90f9783d
@@ -119,7 +119,9 @@ public class MwmApplication extends Application implements Application.ActivityL
|
|||||||
|
|
||||||
sInstance = this;
|
sInstance = this;
|
||||||
|
|
||||||
mOrganicMaps = new OrganicMaps(getApplicationContext());
|
mOrganicMaps =
|
||||||
|
new OrganicMaps(getApplicationContext(), BuildConfig.FLAVOR, BuildConfig.APPLICATION_ID,
|
||||||
|
BuildConfig.VERSION_CODE, BuildConfig.VERSION_NAME, BuildConfig.FILE_PROVIDER_AUTHORITY);
|
||||||
|
|
||||||
ConnectionState.INSTANCE.initialize(this);
|
ConnectionState.INSTANCE.initialize(this);
|
||||||
|
|
||||||
|
|||||||
@@ -8,8 +8,11 @@ android {
|
|||||||
|
|
||||||
ndkVersion = '28.2.13676358'
|
ndkVersion = '28.2.13676358'
|
||||||
|
|
||||||
defaultConfig {
|
buildFeatures {
|
||||||
|
buildConfig = true
|
||||||
|
}
|
||||||
|
|
||||||
|
defaultConfig {
|
||||||
minSdk = propMinSdkVersion.toInteger()
|
minSdk = propMinSdkVersion.toInteger()
|
||||||
targetSdk = propTargetSdkVersion.toInteger()
|
targetSdk = propTargetSdkVersion.toInteger()
|
||||||
|
|
||||||
|
|||||||
@@ -6,7 +6,6 @@ import android.view.MotionEvent;
|
|||||||
import android.view.Surface;
|
import android.view.Surface;
|
||||||
import androidx.annotation.NonNull;
|
import androidx.annotation.NonNull;
|
||||||
import androidx.annotation.Nullable;
|
import androidx.annotation.Nullable;
|
||||||
import app.organicmaps.BuildConfig;
|
|
||||||
import app.organicmaps.R;
|
import app.organicmaps.R;
|
||||||
import app.organicmaps.sdk.display.DisplayType;
|
import app.organicmaps.sdk.display.DisplayType;
|
||||||
import app.organicmaps.sdk.location.LocationHelper;
|
import app.organicmaps.sdk.location.LocationHelper;
|
||||||
@@ -181,7 +180,7 @@ public final class Map
|
|||||||
setupWidgets(context, surfaceFrame.width(), surfaceFrame.height());
|
setupWidgets(context, surfaceFrame.width(), surfaceFrame.height());
|
||||||
|
|
||||||
final boolean firstStart = mLocationHelper.isInFirstRun();
|
final boolean firstStart = mLocationHelper.isInFirstRun();
|
||||||
if (!nativeCreateEngine(surface, surfaceDpi, firstStart, mLaunchByDeepLink, BuildConfig.VERSION_CODE,
|
if (!nativeCreateEngine(surface, surfaceDpi, firstStart, mLaunchByDeepLink, Config.getVersionCode(),
|
||||||
ROMUtils.isCustomROM()))
|
ROMUtils.isCustomROM()))
|
||||||
{
|
{
|
||||||
if (mCallbackUnsupported != null)
|
if (mCallbackUnsupported != null)
|
||||||
|
|||||||
@@ -31,6 +31,9 @@ public final class OrganicMaps implements DefaultLifecycleObserver
|
|||||||
{
|
{
|
||||||
private static final String TAG = OrganicMaps.class.getSimpleName();
|
private static final String TAG = OrganicMaps.class.getSimpleName();
|
||||||
|
|
||||||
|
@NonNull
|
||||||
|
private final String mFlavor;
|
||||||
|
|
||||||
@NonNull
|
@NonNull
|
||||||
private final Context mContext;
|
private final Context mContext;
|
||||||
|
|
||||||
@@ -74,8 +77,10 @@ public final class OrganicMaps implements DefaultLifecycleObserver
|
|||||||
return mIsolinesManager;
|
return mIsolinesManager;
|
||||||
}
|
}
|
||||||
|
|
||||||
public OrganicMaps(@NonNull Context context)
|
public OrganicMaps(@NonNull Context context, @NonNull String flavor, @NonNull String applicationId, int versionCode,
|
||||||
|
@NonNull String versionName, @NonNull String fileProviderAuthority)
|
||||||
{
|
{
|
||||||
|
mFlavor = flavor;
|
||||||
mContext = context.getApplicationContext();
|
mContext = context.getApplicationContext();
|
||||||
mPreferences = mContext.getSharedPreferences(context.getString(app.organicmaps.sdk.R.string.pref_file_name),
|
mPreferences = mContext.getSharedPreferences(context.getString(app.organicmaps.sdk.R.string.pref_file_name),
|
||||||
Context.MODE_PRIVATE);
|
Context.MODE_PRIVATE);
|
||||||
@@ -88,7 +93,7 @@ public final class OrganicMaps implements DefaultLifecycleObserver
|
|||||||
Logger.d(TAG, "Settings path = " + settingsPath);
|
Logger.d(TAG, "Settings path = " + settingsPath);
|
||||||
nativeSetSettingsDir(settingsPath);
|
nativeSetSettingsDir(settingsPath);
|
||||||
|
|
||||||
Config.init(mContext, mPreferences);
|
Config.init(mContext, mPreferences, flavor, applicationId, versionCode, versionName, fileProviderAuthority);
|
||||||
OsmOAuth.init(mPreferences);
|
OsmOAuth.init(mPreferences);
|
||||||
SharedPropertiesUtils.init(mPreferences);
|
SharedPropertiesUtils.init(mPreferences);
|
||||||
LogsManager.INSTANCE.initFileLogging(mContext, mPreferences);
|
LogsManager.INSTANCE.initFileLogging(mContext, mPreferences);
|
||||||
@@ -158,8 +163,7 @@ public final class OrganicMaps implements DefaultLifecycleObserver
|
|||||||
// external storage is damaged or not available (read-only).
|
// external storage is damaged or not available (read-only).
|
||||||
createPlatformDirectories(writablePath, privatePath, tempPath);
|
createPlatformDirectories(writablePath, privatePath, tempPath);
|
||||||
|
|
||||||
nativeInitPlatform(mContext, apkPath, writablePath, privatePath, tempPath, app.organicmaps.BuildConfig.FLAVOR,
|
nativeInitPlatform(mContext, apkPath, writablePath, privatePath, tempPath, mFlavor, BuildConfig.BUILD_TYPE,
|
||||||
app.organicmaps.BuildConfig.BUILD_TYPE,
|
|
||||||
/* isTablet */ false);
|
/* isTablet */ false);
|
||||||
Config.setStoragePath(writablePath);
|
Config.setStoragePath(writablePath);
|
||||||
Config.setStatisticsEnabled(SharedPropertiesUtils.isStatisticsEnabled());
|
Config.setStatisticsEnabled(SharedPropertiesUtils.isStatisticsEnabled());
|
||||||
|
|||||||
@@ -6,7 +6,7 @@ import android.os.Parcelable;
|
|||||||
import androidx.annotation.ColorInt;
|
import androidx.annotation.ColorInt;
|
||||||
import androidx.annotation.DrawableRes;
|
import androidx.annotation.DrawableRes;
|
||||||
import androidx.annotation.NonNull;
|
import androidx.annotation.NonNull;
|
||||||
import app.organicmaps.BuildConfig;
|
import app.organicmaps.sdk.BuildConfig;
|
||||||
import app.organicmaps.sdk.util.StringUtils;
|
import app.organicmaps.sdk.util.StringUtils;
|
||||||
import app.organicmaps.sdk.util.log.Logger;
|
import app.organicmaps.sdk.util.log.Logger;
|
||||||
import dalvik.annotation.optimization.FastNative;
|
import dalvik.annotation.optimization.FastNative;
|
||||||
|
|||||||
@@ -4,7 +4,6 @@ import androidx.annotation.IntDef;
|
|||||||
import androidx.annotation.NonNull;
|
import androidx.annotation.NonNull;
|
||||||
import androidx.annotation.Size;
|
import androidx.annotation.Size;
|
||||||
import androidx.annotation.WorkerThread;
|
import androidx.annotation.WorkerThread;
|
||||||
import app.organicmaps.BuildConfig;
|
|
||||||
import app.organicmaps.sdk.Framework;
|
import app.organicmaps.sdk.Framework;
|
||||||
import app.organicmaps.sdk.bookmarks.data.Metadata;
|
import app.organicmaps.sdk.bookmarks.data.Metadata;
|
||||||
import app.organicmaps.sdk.editor.data.FeatureCategory;
|
import app.organicmaps.sdk.editor.data.FeatureCategory;
|
||||||
@@ -12,6 +11,7 @@ import app.organicmaps.sdk.editor.data.Language;
|
|||||||
import app.organicmaps.sdk.editor.data.LocalizedName;
|
import app.organicmaps.sdk.editor.data.LocalizedName;
|
||||||
import app.organicmaps.sdk.editor.data.LocalizedStreet;
|
import app.organicmaps.sdk.editor.data.LocalizedStreet;
|
||||||
import app.organicmaps.sdk.editor.data.NamesDataSource;
|
import app.organicmaps.sdk.editor.data.NamesDataSource;
|
||||||
|
import app.organicmaps.sdk.util.Config;
|
||||||
import java.lang.annotation.Retention;
|
import java.lang.annotation.Retention;
|
||||||
import java.lang.annotation.RetentionPolicy;
|
import java.lang.annotation.RetentionPolicy;
|
||||||
|
|
||||||
@@ -45,7 +45,7 @@ public final class Editor
|
|||||||
public static void uploadChanges()
|
public static void uploadChanges()
|
||||||
{
|
{
|
||||||
if (nativeHasSomethingToUpload() && OsmOAuth.isAuthorized())
|
if (nativeHasSomethingToUpload() && OsmOAuth.isAuthorized())
|
||||||
nativeUploadChanges(OsmOAuth.getAuthToken(), BuildConfig.VERSION_NAME, BuildConfig.APPLICATION_ID);
|
nativeUploadChanges(OsmOAuth.getAuthToken(), Config.getVersionName(), Config.getApplicationId());
|
||||||
}
|
}
|
||||||
|
|
||||||
public static native boolean nativeShouldShowEditPlace();
|
public static native boolean nativeShouldShowEditPlace();
|
||||||
|
|||||||
@@ -6,7 +6,7 @@ import android.os.SystemClock;
|
|||||||
import androidx.annotation.Keep;
|
import androidx.annotation.Keep;
|
||||||
import androidx.annotation.NonNull;
|
import androidx.annotation.NonNull;
|
||||||
import androidx.annotation.Nullable;
|
import androidx.annotation.Nullable;
|
||||||
import app.organicmaps.BuildConfig;
|
import app.organicmaps.sdk.BuildConfig;
|
||||||
import app.organicmaps.sdk.util.log.Logger;
|
import app.organicmaps.sdk.util.log.Logger;
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.io.InputStream;
|
import java.io.InputStream;
|
||||||
|
|||||||
@@ -5,7 +5,6 @@ import android.content.SharedPreferences;
|
|||||||
import android.os.Build;
|
import android.os.Build;
|
||||||
import androidx.annotation.NonNull;
|
import androidx.annotation.NonNull;
|
||||||
import androidx.preference.PreferenceManager;
|
import androidx.preference.PreferenceManager;
|
||||||
import app.organicmaps.BuildConfig;
|
|
||||||
import app.organicmaps.R;
|
import app.organicmaps.R;
|
||||||
|
|
||||||
public final class Config
|
public final class Config
|
||||||
@@ -14,6 +13,24 @@ public final class Config
|
|||||||
@NonNull
|
@NonNull
|
||||||
private static SharedPreferences mPrefs;
|
private static SharedPreferences mPrefs;
|
||||||
|
|
||||||
|
@SuppressWarnings("NotNullFieldNotInitialized")
|
||||||
|
@NonNull
|
||||||
|
private static String mFlavor;
|
||||||
|
|
||||||
|
@SuppressWarnings("NotNullFieldNotInitialized")
|
||||||
|
@NonNull
|
||||||
|
private static String mApplicationId;
|
||||||
|
|
||||||
|
private static int mVersionCode;
|
||||||
|
|
||||||
|
@SuppressWarnings("NotNullFieldNotInitialized")
|
||||||
|
@NonNull
|
||||||
|
private static String mVersionName;
|
||||||
|
|
||||||
|
@SuppressWarnings("NotNullFieldNotInitialized")
|
||||||
|
@NonNull
|
||||||
|
private static String mFileProviderAuthority;
|
||||||
|
|
||||||
private static final String KEY_APP_STORAGE = "StoragePath";
|
private static final String KEY_APP_STORAGE = "StoragePath";
|
||||||
|
|
||||||
private static final String KEY_DOWNLOADER_AUTO = "AutoDownloadEnabled";
|
private static final String KEY_DOWNLOADER_AUTO = "AutoDownloadEnabled";
|
||||||
@@ -125,6 +142,29 @@ public final class Config
|
|||||||
nativeSetBoolean(key, value);
|
nativeSetBoolean(key, value);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@NonNull
|
||||||
|
public static String getApplicationId()
|
||||||
|
{
|
||||||
|
return mApplicationId;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static int getVersionCode()
|
||||||
|
{
|
||||||
|
return mVersionCode;
|
||||||
|
}
|
||||||
|
|
||||||
|
@NonNull
|
||||||
|
public static String getVersionName()
|
||||||
|
{
|
||||||
|
return mVersionName;
|
||||||
|
}
|
||||||
|
|
||||||
|
@NonNull
|
||||||
|
public static String getFileProviderAuthority()
|
||||||
|
{
|
||||||
|
return mFileProviderAuthority;
|
||||||
|
}
|
||||||
|
|
||||||
public static String getStoragePath()
|
public static String getStoragePath()
|
||||||
{
|
{
|
||||||
return getString(KEY_APP_STORAGE);
|
return getString(KEY_APP_STORAGE);
|
||||||
@@ -351,31 +391,37 @@ public final class Config
|
|||||||
}
|
}
|
||||||
|
|
||||||
@NonNull
|
@NonNull
|
||||||
@SuppressWarnings("ConstantConditions") // BuildConfig
|
|
||||||
public static String getDonateUrl(@NonNull Context context)
|
public static String getDonateUrl(@NonNull Context context)
|
||||||
{
|
{
|
||||||
final String url = getString(KEY_DONATE_URL);
|
final String url = getString(KEY_DONATE_URL);
|
||||||
// Enable donations by default if not Google or Huawei. Replace comaps.app/donate/ with localized page.
|
// Enable donations by default if not Google or Huawei. Replace comaps.app/donate/ with localized page.
|
||||||
if ((url.isEmpty() && !BuildConfig.FLAVOR.equals("google") && !BuildConfig.FLAVOR.equals("huawei"))
|
if ((url.isEmpty() && !mFlavor.equals("google") && !mFlavor.equals("huawei"))
|
||||||
|| url.endsWith("comaps.app/donate/"))
|
|| url.endsWith("comaps.app/donate/"))
|
||||||
return context.getString(R.string.app_site_url) + "donate/";
|
return context.getString(R.string.app_site_url) + "donate/";
|
||||||
return url;
|
return url;
|
||||||
}
|
}
|
||||||
|
|
||||||
public static void init(@NonNull Context context, @NonNull SharedPreferences prefs)
|
public static void init(@NonNull Context context, @NonNull SharedPreferences prefs, @NonNull String flavor,
|
||||||
|
@NonNull String applicationId, int versionCode, @NonNull String versionName,
|
||||||
|
@NonNull String fileProviderAuthority)
|
||||||
{
|
{
|
||||||
PreferenceManager.setDefaultValues(context, R.xml.prefs_main, false);
|
PreferenceManager.setDefaultValues(context, R.xml.prefs_main, false);
|
||||||
|
|
||||||
mPrefs = prefs;
|
mPrefs = prefs;
|
||||||
|
mFlavor = flavor;
|
||||||
|
mApplicationId = applicationId;
|
||||||
|
mVersionCode = versionCode;
|
||||||
|
mVersionName = versionName;
|
||||||
|
mFileProviderAuthority = fileProviderAuthority;
|
||||||
final SharedPreferences.Editor editor = mPrefs.edit();
|
final SharedPreferences.Editor editor = mPrefs.edit();
|
||||||
|
|
||||||
// Update counters.
|
// Update counters.
|
||||||
final int launchNumber = mPrefs.getInt(KEY_APP_LAUNCH_NUMBER, 0);
|
final int launchNumber = mPrefs.getInt(KEY_APP_LAUNCH_NUMBER, 0);
|
||||||
editor.putInt(KEY_APP_LAUNCH_NUMBER, launchNumber + 1);
|
editor.putInt(KEY_APP_LAUNCH_NUMBER, launchNumber + 1);
|
||||||
editor.putLong(KEY_APP_LAST_SESSION_TIMESTAMP, System.currentTimeMillis());
|
editor.putLong(KEY_APP_LAST_SESSION_TIMESTAMP, System.currentTimeMillis());
|
||||||
editor.putInt(KEY_APP_LAST_INSTALL_VERSION_CODE, BuildConfig.VERSION_CODE);
|
editor.putInt(KEY_APP_LAST_INSTALL_VERSION_CODE, mVersionCode);
|
||||||
if (launchNumber == 0 || mPrefs.getInt(KEY_APP_FIRST_INSTALL_VERSION_CODE, 0) == 0)
|
if (launchNumber == 0 || mPrefs.getInt(KEY_APP_FIRST_INSTALL_VERSION_CODE, 0) == 0)
|
||||||
editor.putInt(KEY_APP_FIRST_INSTALL_VERSION_CODE, BuildConfig.VERSION_CODE);
|
editor.putInt(KEY_APP_FIRST_INSTALL_VERSION_CODE, mVersionCode);
|
||||||
|
|
||||||
// Clean up legacy counters.
|
// Clean up legacy counters.
|
||||||
editor.remove("FirstInstallFlavor");
|
editor.remove("FirstInstallFlavor");
|
||||||
|
|||||||
@@ -11,7 +11,6 @@ import androidx.annotation.NonNull;
|
|||||||
import androidx.annotation.Nullable;
|
import androidx.annotation.Nullable;
|
||||||
import androidx.core.content.FileProvider;
|
import androidx.core.content.FileProvider;
|
||||||
import androidx.documentfile.provider.DocumentFile;
|
import androidx.documentfile.provider.DocumentFile;
|
||||||
import app.organicmaps.BuildConfig;
|
|
||||||
import app.organicmaps.sdk.util.log.Logger;
|
import app.organicmaps.sdk.util.log.Logger;
|
||||||
import java.io.File;
|
import java.io.File;
|
||||||
import java.io.FileInputStream;
|
import java.io.FileInputStream;
|
||||||
@@ -94,7 +93,7 @@ public class StorageUtils
|
|||||||
{
|
{
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
return Utils.getApplicationInfo(context.getPackageManager(), BuildConfig.APPLICATION_ID, 0).sourceDir;
|
return Utils.getApplicationInfo(context.getPackageManager(), Config.getApplicationId(), 0).sourceDir;
|
||||||
}
|
}
|
||||||
catch (final PackageManager.NameNotFoundException e)
|
catch (final PackageManager.NameNotFoundException e)
|
||||||
{
|
{
|
||||||
@@ -150,7 +149,7 @@ public class StorageUtils
|
|||||||
@NonNull
|
@NonNull
|
||||||
public static Uri getUriForFilePath(@NonNull Context context, @NonNull String path)
|
public static Uri getUriForFilePath(@NonNull Context context, @NonNull String path)
|
||||||
{
|
{
|
||||||
return FileProvider.getUriForFile(context.getApplicationContext(), BuildConfig.FILE_PROVIDER_AUTHORITY,
|
return FileProvider.getUriForFile(context.getApplicationContext(), Config.getFileProviderAuthority(),
|
||||||
new File(path));
|
new File(path));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -17,7 +17,7 @@ import androidx.annotation.Keep;
|
|||||||
import androidx.annotation.NonNull;
|
import androidx.annotation.NonNull;
|
||||||
import androidx.annotation.Nullable;
|
import androidx.annotation.Nullable;
|
||||||
import androidx.annotation.StringRes;
|
import androidx.annotation.StringRes;
|
||||||
import app.organicmaps.BuildConfig;
|
import app.organicmaps.sdk.BuildConfig;
|
||||||
import app.organicmaps.sdk.util.log.Logger;
|
import app.organicmaps.sdk.util.log.Logger;
|
||||||
import java.io.Closeable;
|
import java.io.Closeable;
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
@@ -211,7 +211,7 @@ public class Utils
|
|||||||
@SuppressWarnings("unused")
|
@SuppressWarnings("unused")
|
||||||
public static String getVersion()
|
public static String getVersion()
|
||||||
{
|
{
|
||||||
return BuildConfig.VERSION_NAME;
|
return Config.getVersionName();
|
||||||
}
|
}
|
||||||
|
|
||||||
// Called from JNI.
|
// Called from JNI.
|
||||||
@@ -222,7 +222,7 @@ public class Utils
|
|||||||
// Please sync with getVersion() in build.gradle
|
// Please sync with getVersion() in build.gradle
|
||||||
// - % 100000000 removes prefix for special markets, e.g Huawei.
|
// - % 100000000 removes prefix for special markets, e.g Huawei.
|
||||||
// - / 100 removes the number of commits in the current day.
|
// - / 100 removes the number of commits in the current day.
|
||||||
return (BuildConfig.VERSION_CODE % 1_00_00_00_00) / 100;
|
return (Config.getVersionCode() % 1_00_00_00_00) / 100;
|
||||||
}
|
}
|
||||||
|
|
||||||
@NonNull
|
@NonNull
|
||||||
|
|||||||
@@ -4,7 +4,7 @@ import android.util.Log;
|
|||||||
import androidx.annotation.Keep;
|
import androidx.annotation.Keep;
|
||||||
import androidx.annotation.NonNull;
|
import androidx.annotation.NonNull;
|
||||||
import androidx.annotation.Nullable;
|
import androidx.annotation.Nullable;
|
||||||
import app.organicmaps.BuildConfig;
|
import app.organicmaps.sdk.BuildConfig;
|
||||||
import java.io.File;
|
import java.io.File;
|
||||||
import java.io.FileWriter;
|
import java.io.FileWriter;
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
|
|||||||
@@ -16,8 +16,9 @@ import androidx.annotation.Keep;
|
|||||||
import androidx.annotation.NonNull;
|
import androidx.annotation.NonNull;
|
||||||
import androidx.annotation.Nullable;
|
import androidx.annotation.Nullable;
|
||||||
import androidx.core.content.ContextCompat;
|
import androidx.core.content.ContextCompat;
|
||||||
import app.organicmaps.BuildConfig;
|
|
||||||
import app.organicmaps.R;
|
import app.organicmaps.R;
|
||||||
|
import app.organicmaps.sdk.BuildConfig;
|
||||||
|
import app.organicmaps.sdk.util.Config;
|
||||||
import app.organicmaps.sdk.util.ROMUtils;
|
import app.organicmaps.sdk.util.ROMUtils;
|
||||||
import app.organicmaps.sdk.util.StringUtils;
|
import app.organicmaps.sdk.util.StringUtils;
|
||||||
import java.io.File;
|
import java.io.File;
|
||||||
@@ -246,9 +247,9 @@ public final class LogsManager
|
|||||||
for (String abi : Build.SUPPORTED_ABIS)
|
for (String abi : Build.SUPPORTED_ABIS)
|
||||||
sb.append(' ').append(abi);
|
sb.append(' ').append(abi);
|
||||||
sb.append("\nApp version: ")
|
sb.append("\nApp version: ")
|
||||||
.append(BuildConfig.APPLICATION_ID)
|
.append(Config.getApplicationId())
|
||||||
.append(' ')
|
.append(' ')
|
||||||
.append(BuildConfig.VERSION_NAME)
|
.append(Config.getVersionName())
|
||||||
.append("\nLocale: ")
|
.append("\nLocale: ")
|
||||||
.append(Locale.getDefault())
|
.append(Locale.getDefault())
|
||||||
.append("\nNetworks: ");
|
.append("\nNetworks: ");
|
||||||
|
|||||||
Reference in New Issue
Block a user