Compare commits
2 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| d955edce80 | |||
| 4b4daa42cf |
@@ -29,8 +29,8 @@ android {
|
|||||||
|
|
||||||
defaultConfig {
|
defaultConfig {
|
||||||
applicationId "com.aoleyun.sn"
|
applicationId "com.aoleyun.sn"
|
||||||
versionCode 210
|
versionCode 212
|
||||||
versionName "1.6.0403"
|
versionName "1.6.0421"
|
||||||
|
|
||||||
//There are no CERT files because If the mini sdk version is 23+, the AGP will ignore the V1 scheme signature.
|
//There are no CERT files because If the mini sdk version is 23+, the AGP will ignore the V1 scheme signature.
|
||||||
minSdkVersion 24
|
minSdkVersion 24
|
||||||
|
|||||||
@@ -117,6 +117,7 @@ import com.aoleyun.sn.network.api.post.MACAddressApi;
|
|||||||
import com.aoleyun.sn.network.api.post.NetAndLaunchApi;
|
import com.aoleyun.sn.network.api.post.NetAndLaunchApi;
|
||||||
import com.aoleyun.sn.network.api.post.NetworkConnectApi;
|
import com.aoleyun.sn.network.api.post.NetworkConnectApi;
|
||||||
import com.aoleyun.sn.network.api.post.NewAppinsideWebApi;
|
import com.aoleyun.sn.network.api.post.NewAppinsideWebApi;
|
||||||
|
import com.aoleyun.sn.network.api.post.RankCommonAppApi;
|
||||||
import com.aoleyun.sn.network.api.post.SendDownloadInfoApi;
|
import com.aoleyun.sn.network.api.post.SendDownloadInfoApi;
|
||||||
import com.aoleyun.sn.network.api.post.SendDownloadTimesApi;
|
import com.aoleyun.sn.network.api.post.SendDownloadTimesApi;
|
||||||
import com.aoleyun.sn.network.api.post.SendRestoreTimesApi;
|
import com.aoleyun.sn.network.api.post.SendRestoreTimesApi;
|
||||||
@@ -182,6 +183,7 @@ import io.reactivex.rxjava3.core.Observable;
|
|||||||
import io.reactivex.rxjava3.core.Observer;
|
import io.reactivex.rxjava3.core.Observer;
|
||||||
import io.reactivex.rxjava3.disposables.Disposable;
|
import io.reactivex.rxjava3.disposables.Disposable;
|
||||||
import io.reactivex.rxjava3.functions.BiFunction;
|
import io.reactivex.rxjava3.functions.BiFunction;
|
||||||
|
import io.reactivex.rxjava3.functions.Function3;
|
||||||
import io.reactivex.rxjava3.functions.Function6;
|
import io.reactivex.rxjava3.functions.Function6;
|
||||||
import io.reactivex.rxjava3.functions.Function7;
|
import io.reactivex.rxjava3.functions.Function7;
|
||||||
import io.reactivex.rxjava3.schedulers.Schedulers;
|
import io.reactivex.rxjava3.schedulers.Schedulers;
|
||||||
@@ -801,6 +803,13 @@ public class NetInterfaceManager {
|
|||||||
.observeOn(AndroidSchedulers.mainThread());
|
.observeOn(AndroidSchedulers.mainThread());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public Observable<BaseResponse<List<AppDateInfo>>> getRankCommonAppObservable() {
|
||||||
|
return mRetrofit.create(RankCommonAppApi.class)
|
||||||
|
.getRankApp(HTTP_KEY, Utils.getSerial(mContext), "1")
|
||||||
|
.subscribeOn(Schedulers.io())
|
||||||
|
.observeOn(AndroidSchedulers.mainThread());
|
||||||
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
*
|
*
|
||||||
* API
|
* API
|
||||||
@@ -1772,6 +1781,7 @@ public class NetInterfaceManager {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Deprecated
|
||||||
public void getDesktopIcon(boolean refresh, BehaviorSubject<ActivityEvent> lifecycle, onCompleteCallback callback) {
|
public void getDesktopIcon(boolean refresh, BehaviorSubject<ActivityEvent> lifecycle, onCompleteCallback callback) {
|
||||||
ConnectMode connectMode = ConnectMode.SIX_HOUR;
|
ConnectMode connectMode = ConnectMode.SIX_HOUR;
|
||||||
if (refresh) {
|
if (refresh) {
|
||||||
@@ -2717,15 +2727,15 @@ public class NetInterfaceManager {
|
|||||||
public void setPushTags(BehaviorSubject<ActivityEvent> lifecycle, PushTagCallback callback) {
|
public void setPushTags(BehaviorSubject<ActivityEvent> lifecycle, PushTagCallback callback) {
|
||||||
getPushTagsObservable()
|
getPushTagsObservable()
|
||||||
.compose(RxLifecycle.bindUntilEvent(lifecycle, ActivityEvent.DESTROY))
|
.compose(RxLifecycle.bindUntilEvent(lifecycle, ActivityEvent.DESTROY))
|
||||||
.subscribe(getgetPushTagsObserver(callback));
|
.subscribe(getPushTagsObserver(callback));
|
||||||
}
|
}
|
||||||
|
|
||||||
public void setPushTags() {
|
public void setPushTags() {
|
||||||
getPushTagsObservable()
|
getPushTagsObservable()
|
||||||
.subscribe(getgetPushTagsObserver(null));
|
.subscribe(getPushTagsObserver(null));
|
||||||
}
|
}
|
||||||
|
|
||||||
private Observer<BaseResponse<Batch>> getgetPushTagsObserver(PushTagCallback callback) {
|
private Observer<BaseResponse<Batch>> getPushTagsObserver(PushTagCallback callback) {
|
||||||
return new Observer<BaseResponse<Batch>>() {
|
return new Observer<BaseResponse<Batch>>() {
|
||||||
@Override
|
@Override
|
||||||
public void onSubscribe(@NonNull Disposable d) {
|
public void onSubscribe(@NonNull Disposable d) {
|
||||||
@@ -3454,7 +3464,7 @@ public class NetInterfaceManager {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public void getAppLimit(BehaviorSubject<ActivityEvent> lifecycle, onCompleteCallback callback) {
|
public void getAppLimit(BehaviorSubject<ActivityEvent> lifecycle, onCompleteCallback callback) {
|
||||||
Observable.zip(getAppLimitObservable(), getAdminAppObservable(), getBiFunction())
|
Observable.zip(getAppLimitObservable(), getAdminAppObservable(), getRankCommonAppObservable(), getBiFunction())
|
||||||
.compose(RxLifecycle.bindUntilEvent(lifecycle, ActivityEvent.DESTROY))
|
.compose(RxLifecycle.bindUntilEvent(lifecycle, ActivityEvent.DESTROY))
|
||||||
.subscribe(getAppLimitListObserver(callback));
|
.subscribe(getAppLimitListObserver(callback));
|
||||||
// getAppLimitObservable()
|
// getAppLimitObservable()
|
||||||
@@ -3463,29 +3473,29 @@ public class NetInterfaceManager {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public void getAppLimit(onCompleteCallback callback) {
|
public void getAppLimit(onCompleteCallback callback) {
|
||||||
Observable.zip(getAppLimitObservable(), getAdminAppObservable(), getBiFunction())
|
Observable.zip(getAppLimitObservable(), getAdminAppObservable(), getRankCommonAppObservable(), getBiFunction())
|
||||||
.subscribe(getAppLimitListObserver(callback));
|
.subscribe(getAppLimitListObserver(callback));
|
||||||
// getAppLimitObservable()
|
// getAppLimitObservable()
|
||||||
// .subscribe(getAppLimitObserver(callback));
|
// .subscribe(getAppLimitObserver(callback));
|
||||||
}
|
}
|
||||||
|
|
||||||
public void getAppLimit() {
|
public void getAppLimit() {
|
||||||
Observable.zip(getAppLimitObservable(), getAdminAppObservable(), getBiFunction())
|
Observable.zip(getAppLimitObservable(), getAdminAppObservable(), getRankCommonAppObservable(), getBiFunction())
|
||||||
.subscribe(getAppLimitListObserver(null));
|
.subscribe(getAppLimitListObserver(null));
|
||||||
// getAppLimitObservable()
|
// getAppLimitObservable()
|
||||||
// .subscribe(getAppLimitObserver(null));
|
// .subscribe(getAppLimitObserver(null));
|
||||||
}
|
}
|
||||||
|
|
||||||
private void getAppLimitList() {
|
private void getAppLimitList() {
|
||||||
Observable.zip(getAppLimitObservable(), getAdminAppObservable(), getBiFunction())
|
Observable.zip(getAppLimitObservable(), getAdminAppObservable(), getRankCommonAppObservable(), getBiFunction())
|
||||||
.subscribe(getAppLimitListObserver(null));
|
.subscribe(getAppLimitListObserver(null));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
private BiFunction<BaseResponse<AppLimit>, BaseResponse<List<AppDateInfo>>, List<String>> getBiFunction() {
|
private Function3<BaseResponse<AppLimit>, BaseResponse<List<AppDateInfo>>, BaseResponse<List<AppDateInfo>>, List<String>> getBiFunction() {
|
||||||
return new BiFunction<BaseResponse<AppLimit>, BaseResponse<List<AppDateInfo>>, List<String>>() {
|
return new Function3<BaseResponse<AppLimit>, BaseResponse<List<AppDateInfo>>, BaseResponse<List<AppDateInfo>>, List<String>>() {
|
||||||
@Override
|
@Override
|
||||||
public List<String> apply(BaseResponse<AppLimit> appLimitBaseResponse, BaseResponse<List<AppDateInfo>> listBaseResponse) throws Throwable {
|
public List<String> apply(BaseResponse<AppLimit> appLimitBaseResponse, BaseResponse<List<AppDateInfo>> listBaseResponse, BaseResponse<List<AppDateInfo>> appDateInfoResponse) throws Throwable {
|
||||||
List<String> appNames = new ArrayList<>();
|
List<String> appNames = new ArrayList<>();
|
||||||
if (appLimitBaseResponse.code == 200) {
|
if (appLimitBaseResponse.code == 200) {
|
||||||
AppLimit appLimit = appLimitBaseResponse.data;
|
AppLimit appLimit = appLimitBaseResponse.data;
|
||||||
@@ -3503,6 +3513,16 @@ public class NetInterfaceManager {
|
|||||||
}).collect(Collectors.toSet());
|
}).collect(Collectors.toSet());
|
||||||
appNames.addAll(pkgs);
|
appNames.addAll(pkgs);
|
||||||
}
|
}
|
||||||
|
if (appDateInfoResponse.code == 200) {
|
||||||
|
List<AppDateInfo> appDateInfos = appDateInfoResponse.data;
|
||||||
|
Set<String> pkgs = appDateInfos.stream().map(new Function<AppDateInfo, String>() {
|
||||||
|
@Override
|
||||||
|
public String apply(AppDateInfo appDateInfo) {
|
||||||
|
return appDateInfo.getApp_baoming();
|
||||||
|
}
|
||||||
|
}).collect(Collectors.toSet());
|
||||||
|
appNames.addAll(pkgs);
|
||||||
|
}
|
||||||
return appNames;
|
return appNames;
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -39,6 +39,8 @@ public class UrlAddress {
|
|||||||
public static final String SET_WHITE_PACKAGE_LIST = "firmware/index";
|
public static final String SET_WHITE_PACKAGE_LIST = "firmware/index";
|
||||||
/*获取全部应用*/
|
/*获取全部应用*/
|
||||||
public static final String GET_ALL_APP = "recommend/index";
|
public static final String GET_ALL_APP = "recommend/index";
|
||||||
|
/*公共应用*/
|
||||||
|
public static final String HTTP_TAG_COMMOAPP = "Rank/commonApp";
|
||||||
/*强制安装应用*/
|
/*强制安装应用*/
|
||||||
public static final String GET_FORCE_INSTALL_LIST = "forceinstall/index";
|
public static final String GET_FORCE_INSTALL_LIST = "forceinstall/index";
|
||||||
/*分组应用强制安装*/
|
/*分组应用强制安装*/
|
||||||
|
|||||||
@@ -0,0 +1,22 @@
|
|||||||
|
package com.aoleyun.sn.network.api.post;
|
||||||
|
|
||||||
|
import com.aoleyun.sn.bean.AppDateInfo;
|
||||||
|
import com.aoleyun.sn.bean.BaseResponse;
|
||||||
|
import com.aoleyun.sn.network.UrlAddress;
|
||||||
|
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
import io.reactivex.rxjava3.core.Observable;
|
||||||
|
import retrofit2.http.Field;
|
||||||
|
import retrofit2.http.FormUrlEncoded;
|
||||||
|
import retrofit2.http.POST;
|
||||||
|
|
||||||
|
public interface RankCommonAppApi {
|
||||||
|
@FormUrlEncoded
|
||||||
|
@POST(UrlAddress.HTTP_TAG_COMMOAPP)
|
||||||
|
Observable<BaseResponse<List<AppDateInfo>>> getRankApp(
|
||||||
|
@Field("key") String key,
|
||||||
|
@Field("sn") String sn,
|
||||||
|
@Field("page") String page
|
||||||
|
);
|
||||||
|
}
|
||||||
@@ -8,11 +8,9 @@ import android.os.Build;
|
|||||||
import android.text.TextUtils;
|
import android.text.TextUtils;
|
||||||
import android.util.Log;
|
import android.util.Log;
|
||||||
|
|
||||||
import com.aoleyun.sn.comm.CommonConfig;
|
|
||||||
import com.aoleyun.sn.comm.PackageNames;
|
import com.aoleyun.sn.comm.PackageNames;
|
||||||
import com.aoleyun.sn.network.NetInterfaceManager;
|
import com.aoleyun.sn.network.NetInterfaceManager;
|
||||||
import com.aoleyun.sn.utils.ApkUtils;
|
import com.aoleyun.sn.utils.ApkUtils;
|
||||||
import com.aoleyun.sn.utils.CmdUtil;
|
|
||||||
import com.aoleyun.sn.utils.JgyUtils;
|
import com.aoleyun.sn.utils.JgyUtils;
|
||||||
|
|
||||||
import java.util.concurrent.TimeUnit;
|
import java.util.concurrent.TimeUnit;
|
||||||
@@ -76,7 +74,6 @@ public class NewAppReceiver extends BroadcastReceiver {
|
|||||||
JgyUtils.getInstance().setAllowPermissionsPackage();
|
JgyUtils.getInstance().setAllowPermissionsPackage();
|
||||||
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
|
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
|
||||||
if (!PackageNames.APPSTORE.equals(packageName) || !PackageNames.DEVICE_INFO.equals(packageName)) {
|
if (!PackageNames.APPSTORE.equals(packageName) || !PackageNames.DEVICE_INFO.equals(packageName)) {
|
||||||
ApkUtils.addShortcut(context);
|
|
||||||
ApkUtils.RemoveTask(context, packageName);
|
ApkUtils.RemoveTask(context, packageName);
|
||||||
}
|
}
|
||||||
JgyUtils.getInstance().wakeUpAoleyunAPP();
|
JgyUtils.getInstance().wakeUpAoleyunAPP();
|
||||||
@@ -122,6 +119,7 @@ public class NewAppReceiver extends BroadcastReceiver {
|
|||||||
NetInterfaceManager.getInstance().getAppLimit();
|
NetInterfaceManager.getInstance().getAppLimit();
|
||||||
// NetInterfaceManager.getInstance().getDefaultDesktop();
|
// NetInterfaceManager.getInstance().getDefaultDesktop();
|
||||||
NetInterfaceManager.getInstance().getNetAndLaunchSetting();
|
NetInterfaceManager.getInstance().getNetAndLaunchSetting();
|
||||||
|
NetInterfaceManager.getInstance().getDesktopIcon();
|
||||||
NetInterfaceManager.getInstance().sendInstalledAppInfo(new NetInterfaceManager.onCompleteCallback() {
|
NetInterfaceManager.getInstance().sendInstalledAppInfo(new NetInterfaceManager.onCompleteCallback() {
|
||||||
@Override
|
@Override
|
||||||
public void onComplete() {
|
public void onComplete() {
|
||||||
|
|||||||
@@ -599,13 +599,14 @@ public class MainService extends Service implements MainSContact.MainView, Netwo
|
|||||||
|
|
||||||
registerReceivers();
|
registerReceivers();
|
||||||
NetworkUtils.registerNetworkStatusChangedListener(this);
|
NetworkUtils.registerNetworkStatusChangedListener(this);
|
||||||
addShortcut();
|
|
||||||
timeChangedStart.onstar(System.currentTimeMillis());
|
timeChangedStart.onstar(System.currentTimeMillis());
|
||||||
setStatusbar();
|
setStatusbar();
|
||||||
setFloatingWindow();
|
setFloatingWindow();
|
||||||
JgyUtils.getInstance().writeAppPackageList();
|
JgyUtils.getInstance().writeAppPackageList();
|
||||||
// notificationManager = NotificationManagerCompat.from(this);
|
notificationManager = NotificationManagerCompat.from(this);
|
||||||
// createNotificationChannel();
|
createNotificationChannel();
|
||||||
|
sendSimpleNotification();
|
||||||
|
|
||||||
// aliyunPushInit();
|
// aliyunPushInit();
|
||||||
|
|
||||||
IActivityManager activityManager = ActivityManagerNative.getDefault();
|
IActivityManager activityManager = ActivityManagerNative.getDefault();
|
||||||
@@ -673,7 +674,6 @@ public class MainService extends Service implements MainSContact.MainView, Netwo
|
|||||||
channel.setDescription(CHANNEL_DESCRIPTION);
|
channel.setDescription(CHANNEL_DESCRIPTION);
|
||||||
// Register the channel with the system; you can't change the importance
|
// Register the channel with the system; you can't change the importance
|
||||||
// or other notification behaviors after this
|
// or other notification behaviors after this
|
||||||
NotificationManager notificationManager = getSystemService(NotificationManager.class);
|
|
||||||
notificationManager.createNotificationChannel(channel);
|
notificationManager.createNotificationChannel(channel);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -691,11 +691,8 @@ public class MainService extends Service implements MainSContact.MainView, Netwo
|
|||||||
.setOngoing(true)
|
.setOngoing(true)
|
||||||
.setPriority(NotificationCompat.PRIORITY_MAX);
|
.setPriority(NotificationCompat.PRIORITY_MAX);
|
||||||
// notificationId is a unique int for each notification that you must define
|
// notificationId is a unique int for each notification that you must define
|
||||||
notificationManager.notify(NotificationID, builder.build());
|
// notificationManager.notify(NotificationID, builder.build());
|
||||||
}
|
startForeground(NotificationID, builder.build());
|
||||||
|
|
||||||
private void addShortcut() {
|
|
||||||
ApkUtils.addShortcut(this);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private void setStatusbar() {
|
private void setStatusbar() {
|
||||||
@@ -923,7 +920,11 @@ public class MainService extends Service implements MainSContact.MainView, Netwo
|
|||||||
@Override
|
@Override
|
||||||
public void onReceive(Context context, Intent intent) {
|
public void onReceive(Context context, Intent intent) {
|
||||||
Log.e("TimeChangedReceiver", "onReceive: " + intent.getAction());
|
Log.e("TimeChangedReceiver", "onReceive: " + intent.getAction());
|
||||||
switch (intent.getAction()) {
|
String action = intent.getAction();
|
||||||
|
if (TextUtils.isEmpty(action)) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
switch (action) {
|
||||||
case Intent.ACTION_DATE_CHANGED:
|
case Intent.ACTION_DATE_CHANGED:
|
||||||
case Intent.ACTION_TIME_CHANGED:
|
case Intent.ACTION_TIME_CHANGED:
|
||||||
case Intent.ACTION_TIMEZONE_CHANGED:
|
case Intent.ACTION_TIMEZONE_CHANGED:
|
||||||
@@ -1168,7 +1169,6 @@ public class MainService extends Service implements MainSContact.MainView, Netwo
|
|||||||
Log.e(TAG, "setLockedState: " + loocked);
|
Log.e(TAG, "setLockedState: " + loocked);
|
||||||
if (loocked) {
|
if (loocked) {
|
||||||
Toaster.debugShow("设备已上锁");
|
Toaster.debugShow("设备已上锁");
|
||||||
// sendSimpleNotification();
|
|
||||||
mPresenter.setPushTags();
|
mPresenter.setPushTags();
|
||||||
ApkUtils.UninstallAPP(this, "com.joytv.live");
|
ApkUtils.UninstallAPP(this, "com.joytv.live");
|
||||||
ApkUtils.UninstallAPP(this, "com.tencent.android.qqdownloader");
|
ApkUtils.UninstallAPP(this, "com.tencent.android.qqdownloader");
|
||||||
|
|||||||
@@ -1365,10 +1365,6 @@ public class ApkUtils {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public static void addShortcut(Context context) {
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
private static final Set<String> AoleyunOSApp = new HashSet<String>() {{
|
private static final Set<String> AoleyunOSApp = new HashSet<String>() {{
|
||||||
this.add("com.aoleyun.info");
|
this.add("com.aoleyun.info");
|
||||||
this.add("com.aoleyun.os");
|
this.add("com.aoleyun.os");
|
||||||
|
|||||||
@@ -245,7 +245,11 @@ public class JgyUtils {
|
|||||||
public static void init(Context context) {
|
public static void init(Context context) {
|
||||||
if (sInstance == null) {
|
if (sInstance == null) {
|
||||||
Log.e(TAG, "init: ");
|
Log.e(TAG, "init: ");
|
||||||
sInstance = new JgyUtils(context);
|
synchronized (JgyUtils.class) {
|
||||||
|
if (sInstance == null) {
|
||||||
|
sInstance = new JgyUtils(context);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1527,7 +1531,6 @@ public class JgyUtils {
|
|||||||
setAppRestriction(0);
|
setAppRestriction(0);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
ApkUtils.addShortcut(mContext);
|
|
||||||
HashSet<String> pkgSet = new HashSet<>(defaultPackages);
|
HashSet<String> pkgSet = new HashSet<>(defaultPackages);
|
||||||
if (BuildConfig.DEBUG) {
|
if (BuildConfig.DEBUG) {
|
||||||
pkgSet.add("com.reqable.android");
|
pkgSet.add("com.reqable.android");
|
||||||
@@ -3009,6 +3012,7 @@ public class JgyUtils {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Deprecated
|
||||||
public List<String> getHidePackage() {
|
public List<String> getHidePackage() {
|
||||||
String jsonString = cacheHelper.getAsString(UrlAddress.GET_HIDE_DESKTOPICON);
|
String jsonString = cacheHelper.getAsString(UrlAddress.GET_HIDE_DESKTOPICON);
|
||||||
//为 "" 是已经请求成功的
|
//为 "" 是已经请求成功的
|
||||||
|
|||||||
@@ -28,7 +28,7 @@ allprojects {
|
|||||||
|
|
||||||
repositories {
|
repositories {
|
||||||
google()
|
google()
|
||||||
mavenCentral()
|
// mavenCentral()
|
||||||
maven { url "https://jitpack.io" }
|
maven { url "https://jitpack.io" }
|
||||||
maven { url 'https://developer.huawei.com/repo/' }
|
maven { url 'https://developer.huawei.com/repo/' }
|
||||||
maven { url 'https://maven.aliyun.com/repository/central/' }
|
maven { url 'https://maven.aliyun.com/repository/central/' }
|
||||||
|
|||||||
Reference in New Issue
Block a user