Remove another global callback object (#6316)
This commit is contained in:
parent
cfb9745246
commit
c98194f519
|
@ -126,7 +126,13 @@
|
|||
<activity
|
||||
android:name=".activity.DownloadAuthenticationActivity"
|
||||
android:theme="@style/Theme.AntennaPod.Dark.Translucent"
|
||||
android:launchMode="singleInstance"/>
|
||||
android:exported="false"
|
||||
android:launchMode="singleInstance">
|
||||
<intent-filter>
|
||||
<action android:name="de.danoeh.antennapod.intents.DOWNLOAD_AUTH_ACTIVITY" />
|
||||
<category android:name="android.intent.category.DEFAULT" />
|
||||
</intent-filter>
|
||||
</activity>
|
||||
|
||||
<activity
|
||||
android:name=".activity.PreferenceActivity"
|
||||
|
|
|
@ -12,7 +12,6 @@ import com.joanzapata.iconify.fonts.MaterialModule;
|
|||
|
||||
import de.danoeh.antennapod.activity.SplashActivity;
|
||||
import de.danoeh.antennapod.config.ApplicationCallbacksImpl;
|
||||
import de.danoeh.antennapod.config.DownloadServiceCallbacksImpl;
|
||||
import de.danoeh.antennapod.core.ApCoreEventBusIndex;
|
||||
import de.danoeh.antennapod.core.ClientConfig;
|
||||
import de.danoeh.antennapod.core.ClientConfigurator;
|
||||
|
@ -35,7 +34,6 @@ public class PodcastApp extends MultiDexApplication {
|
|||
super.onCreate();
|
||||
ClientConfig.USER_AGENT = "AntennaPod/" + BuildConfig.VERSION_NAME;
|
||||
ClientConfig.applicationCallbacks = new ApplicationCallbacksImpl();
|
||||
ClientConfig.downloadServiceCallbacks = new DownloadServiceCallbacksImpl();
|
||||
|
||||
Thread.setDefaultUncaughtExceptionHandler(new CrashReportWriter());
|
||||
RxJavaErrorHandlerSetup.setupRxJavaErrorHandler();
|
||||
|
|
|
@ -12,10 +12,10 @@ import de.danoeh.antennapod.net.download.serviceinterface.DownloadRequest;
|
|||
import de.danoeh.antennapod.core.storage.DBReader;
|
||||
import de.danoeh.antennapod.core.storage.DBWriter;
|
||||
import de.danoeh.antennapod.dialog.AuthenticationDialog;
|
||||
import de.danoeh.antennapod.ui.appstartintent.DownloadAuthenticationActivityStarter;
|
||||
import io.reactivex.Completable;
|
||||
import io.reactivex.android.schedulers.AndroidSchedulers;
|
||||
import io.reactivex.schedulers.Schedulers;
|
||||
import org.apache.commons.lang3.Validate;
|
||||
|
||||
|
||||
/**
|
||||
|
@ -23,19 +23,13 @@ import org.apache.commons.lang3.Validate;
|
|||
* The activity MUST be started with the ARG_DOWNlOAD_REQUEST argument set to a non-null value.
|
||||
*/
|
||||
public class DownloadAuthenticationActivity extends AppCompatActivity {
|
||||
|
||||
/**
|
||||
* The download request object that contains information about the resource that requires a username and a password.
|
||||
*/
|
||||
public static final String ARG_DOWNLOAD_REQUEST = "request";
|
||||
|
||||
@Override
|
||||
protected void onCreate(Bundle savedInstanceState) {
|
||||
setTheme(ThemeSwitcher.getTranslucentTheme(this));
|
||||
super.onCreate(savedInstanceState);
|
||||
|
||||
Validate.isTrue(getIntent().hasExtra(ARG_DOWNLOAD_REQUEST), "Download request missing");
|
||||
DownloadRequest request = getIntent().getParcelableExtra(ARG_DOWNLOAD_REQUEST);
|
||||
DownloadRequest request = getIntent().getParcelableExtra(
|
||||
DownloadAuthenticationActivityStarter.EXTRA_DOWNLOAD_REQUEST);
|
||||
|
||||
new AuthenticationDialog(this, R.string.authentication_label, true, "", "") {
|
||||
@Override
|
||||
|
|
|
@ -76,7 +76,6 @@ public class MainActivity extends CastEnabledActivity {
|
|||
public static final String PREF_NAME = "MainActivityPrefs";
|
||||
public static final String PREF_IS_FIRST_LAUNCH = "prefMainActivityIsFirstLaunch";
|
||||
|
||||
public static final String EXTRA_FRAGMENT_ARGS = "fragment_args";
|
||||
public static final String EXTRA_FEED_ID = "fragment_feed_id";
|
||||
public static final String EXTRA_REFRESH_ON_START = "refresh_on_start";
|
||||
public static final String EXTRA_STARTED_FROM_SEARCH = "started_from_search";
|
||||
|
@ -516,21 +515,12 @@ public class MainActivity extends CastEnabledActivity {
|
|||
}
|
||||
|
||||
private void handleNavIntent() {
|
||||
Log.d(TAG, "handleNavIntent()");
|
||||
Intent intent = getIntent();
|
||||
if (intent.hasExtra(EXTRA_FEED_ID) || intent.hasExtra(MainActivityStarter.EXTRA_FRAGMENT_TAG)
|
||||
|| intent.hasExtra(EXTRA_REFRESH_ON_START)) {
|
||||
Log.d(TAG, "handleNavIntent()");
|
||||
String tag = intent.getStringExtra(MainActivityStarter.EXTRA_FRAGMENT_TAG);
|
||||
Bundle args = intent.getBundleExtra(EXTRA_FRAGMENT_ARGS);
|
||||
boolean refreshOnStart = intent.getBooleanExtra(EXTRA_REFRESH_ON_START, false);
|
||||
if (refreshOnStart) {
|
||||
AutoUpdateManager.runImmediate(this);
|
||||
}
|
||||
|
||||
if (intent.hasExtra(EXTRA_FEED_ID)) {
|
||||
long feedId = intent.getLongExtra(EXTRA_FEED_ID, 0);
|
||||
if (tag != null) {
|
||||
loadFragment(tag, args);
|
||||
} else if (feedId > 0) {
|
||||
Bundle args = intent.getBundleExtra(MainActivityStarter.EXTRA_FRAGMENT_ARGS);
|
||||
if (feedId > 0) {
|
||||
boolean startedFromSearch = intent.getBooleanExtra(EXTRA_STARTED_FROM_SEARCH, false);
|
||||
boolean addToBackStack = intent.getBooleanExtra(EXTRA_ADD_TO_BACK_STACK, false);
|
||||
if (startedFromSearch || addToBackStack) {
|
||||
|
@ -540,6 +530,13 @@ public class MainActivity extends CastEnabledActivity {
|
|||
}
|
||||
}
|
||||
sheetBehavior.setState(BottomSheetBehavior.STATE_COLLAPSED);
|
||||
} else if (intent.hasExtra(MainActivityStarter.EXTRA_FRAGMENT_TAG)) {
|
||||
String tag = intent.getStringExtra(MainActivityStarter.EXTRA_FRAGMENT_TAG);
|
||||
Bundle args = intent.getBundleExtra(MainActivityStarter.EXTRA_FRAGMENT_ARGS);
|
||||
if (tag != null) {
|
||||
loadFragment(tag, args);
|
||||
}
|
||||
sheetBehavior.setState(BottomSheetBehavior.STATE_COLLAPSED);
|
||||
} else if (intent.getBooleanExtra(MainActivityStarter.EXTRA_OPEN_PLAYER, false)) {
|
||||
sheetBehavior.setState(BottomSheetBehavior.STATE_EXPANDED);
|
||||
bottomSheetCallback.onSlide(null, 1.0f);
|
||||
|
@ -547,9 +544,12 @@ public class MainActivity extends CastEnabledActivity {
|
|||
handleDeeplink(intent.getData());
|
||||
}
|
||||
|
||||
if (intent.hasExtra(MainActivityStarter.EXTRA_OPEN_DRAWER) && drawerLayout != null) {
|
||||
if (intent.getBooleanExtra(MainActivityStarter.EXTRA_OPEN_DRAWER, false) && drawerLayout != null) {
|
||||
drawerLayout.open();
|
||||
}
|
||||
if (intent.getBooleanExtra(EXTRA_REFRESH_ON_START, false)) {
|
||||
AutoUpdateManager.runImmediate(this);
|
||||
}
|
||||
// to avoid handling the intent twice when the configuration changes
|
||||
setIntent(new Intent(MainActivity.this, MainActivity.class));
|
||||
}
|
||||
|
|
|
@ -1,58 +0,0 @@
|
|||
package de.danoeh.antennapod.config;
|
||||
|
||||
import android.app.PendingIntent;
|
||||
import android.content.Context;
|
||||
import android.content.Intent;
|
||||
import android.os.Build;
|
||||
|
||||
import android.os.Bundle;
|
||||
import de.danoeh.antennapod.R;
|
||||
import de.danoeh.antennapod.activity.DownloadAuthenticationActivity;
|
||||
import de.danoeh.antennapod.activity.MainActivity;
|
||||
import de.danoeh.antennapod.core.DownloadServiceCallbacks;
|
||||
import de.danoeh.antennapod.net.download.serviceinterface.DownloadRequest;
|
||||
import de.danoeh.antennapod.fragment.CompletedDownloadsFragment;
|
||||
import de.danoeh.antennapod.fragment.QueueFragment;
|
||||
import de.danoeh.antennapod.ui.appstartintent.MainActivityStarter;
|
||||
|
||||
|
||||
public class DownloadServiceCallbacksImpl implements DownloadServiceCallbacks {
|
||||
|
||||
@Override
|
||||
public PendingIntent getNotificationContentIntent(Context context) {
|
||||
MainActivityStarter starter = new MainActivityStarter(context)
|
||||
.withFragmentLoaded(CompletedDownloadsFragment.TAG);
|
||||
return PendingIntent.getActivity(context,
|
||||
R.id.pending_intent_download_service_notification, starter.getIntent(),
|
||||
PendingIntent.FLAG_UPDATE_CURRENT | (Build.VERSION.SDK_INT >= 23 ? PendingIntent.FLAG_IMMUTABLE : 0));
|
||||
}
|
||||
|
||||
@Override
|
||||
public PendingIntent getAuthentificationNotificationContentIntent(Context context, DownloadRequest request) {
|
||||
final Intent activityIntent = new Intent(context.getApplicationContext(), DownloadAuthenticationActivity.class);
|
||||
activityIntent.setAction("request" + request.getFeedfileId());
|
||||
activityIntent.putExtra(DownloadAuthenticationActivity.ARG_DOWNLOAD_REQUEST, request);
|
||||
return PendingIntent.getActivity(context.getApplicationContext(),
|
||||
request.getSource().hashCode(), activityIntent,
|
||||
PendingIntent.FLAG_ONE_SHOT | (Build.VERSION.SDK_INT >= 23 ? PendingIntent.FLAG_IMMUTABLE : 0));
|
||||
}
|
||||
|
||||
@Override
|
||||
public PendingIntent getReportNotificationContentIntent(Context context) {
|
||||
Intent intent = new Intent(context, MainActivity.class);
|
||||
intent.putExtra(MainActivityStarter.EXTRA_FRAGMENT_TAG, CompletedDownloadsFragment.TAG);
|
||||
Bundle args = new Bundle();
|
||||
args.putBoolean(CompletedDownloadsFragment.ARG_SHOW_LOGS, true);
|
||||
intent.putExtra(MainActivity.EXTRA_FRAGMENT_ARGS, args);
|
||||
return PendingIntent.getActivity(context, R.id.pending_intent_download_service_report, intent,
|
||||
PendingIntent.FLAG_UPDATE_CURRENT | (Build.VERSION.SDK_INT >= 23 ? PendingIntent.FLAG_IMMUTABLE : 0));
|
||||
}
|
||||
|
||||
@Override
|
||||
public PendingIntent getAutoDownloadReportNotificationContentIntent(Context context) {
|
||||
Intent intent = new Intent(context, MainActivity.class);
|
||||
intent.putExtra(MainActivityStarter.EXTRA_FRAGMENT_TAG, QueueFragment.TAG);
|
||||
return PendingIntent.getActivity(context, R.id.pending_intent_download_service_autodownload_report, intent,
|
||||
PendingIntent.FLAG_UPDATE_CURRENT | (Build.VERSION.SDK_INT >= 23 ? PendingIntent.FLAG_IMMUTABLE : 0));
|
||||
}
|
||||
}
|
|
@ -343,7 +343,9 @@ public class NavDrawerFragment extends Fragment implements SharedPreferences.OnS
|
|||
navAdapter.notifyDataSetChanged();
|
||||
if (UserPreferences.getHiddenDrawerItems().contains(getLastNavFragment(getContext()))) {
|
||||
new MainActivityStarter(getContext())
|
||||
.withFragmentLoaded(UserPreferences.getDefaultPage()).start();
|
||||
.withFragmentLoaded(UserPreferences.getDefaultPage())
|
||||
.withDrawerOpen()
|
||||
.start();
|
||||
}
|
||||
});
|
||||
return true;
|
||||
|
|
|
@ -11,6 +11,4 @@ public class ClientConfig {
|
|||
public static String USER_AGENT;
|
||||
|
||||
public static ApplicationCallbacks applicationCallbacks;
|
||||
|
||||
public static DownloadServiceCallbacks downloadServiceCallbacks;
|
||||
}
|
||||
|
|
|
@ -1,54 +0,0 @@
|
|||
package de.danoeh.antennapod.core;
|
||||
|
||||
import android.app.PendingIntent;
|
||||
import android.content.Context;
|
||||
|
||||
import de.danoeh.antennapod.net.download.serviceinterface.DownloadRequest;
|
||||
|
||||
/**
|
||||
* Callbacks for the DownloadService of the core module.
|
||||
*/
|
||||
public interface DownloadServiceCallbacks {
|
||||
|
||||
/**
|
||||
* Returns a PendingIntent for a notification the main notification of the DownloadService.
|
||||
* <p/>
|
||||
* The PendingIntent takes the users to a screen where they can observe all currently running
|
||||
* downloads.
|
||||
*
|
||||
* @return A non-null PendingIntent for the notification.
|
||||
*/
|
||||
PendingIntent getNotificationContentIntent(Context context);
|
||||
|
||||
/**
|
||||
* Returns a PendingIntent for a notification that tells the user to enter a username
|
||||
* or a password for a requested download.
|
||||
* <p/>
|
||||
* The PendingIntent takes users to an Activity that lets the user enter their username
|
||||
* and password to retry the download.
|
||||
*
|
||||
* @return A non-null PendingIntent for the notification.
|
||||
*/
|
||||
PendingIntent getAuthentificationNotificationContentIntent(Context context, DownloadRequest request);
|
||||
|
||||
/**
|
||||
* Returns a PendingIntent for notification that notifies the user about the completion of downloads
|
||||
* along with information about failed and successful downloads.
|
||||
* <p/>
|
||||
* The PendingIntent takes users to an activity where they can look at all successful and failed downloads.
|
||||
*
|
||||
* @return A non-null PendingIntent for the notification
|
||||
*/
|
||||
PendingIntent getReportNotificationContentIntent(Context context);
|
||||
|
||||
/**
|
||||
* Returns a PendingIntent for notification that notifies the user about the episodes that have been automatically
|
||||
* downloaded.
|
||||
* <p/>
|
||||
* The PendingIntent takes users to an activity where they can look at their episode queue.
|
||||
*
|
||||
* @return A non-null PendingIntent for the notification
|
||||
*/
|
||||
PendingIntent getAutoDownloadReportNotificationContentIntent(Context context);
|
||||
}
|
||||
|
|
@ -4,9 +4,10 @@ import android.app.Notification;
|
|||
import android.app.NotificationManager;
|
||||
import android.app.PendingIntent;
|
||||
import android.content.Context;
|
||||
import android.content.Intent;
|
||||
import android.os.Build;
|
||||
import android.util.Log;
|
||||
import androidx.core.app.NotificationCompat;
|
||||
import de.danoeh.antennapod.core.ClientConfig;
|
||||
import de.danoeh.antennapod.core.R;
|
||||
import de.danoeh.antennapod.core.util.DownloadErrorLabel;
|
||||
import de.danoeh.antennapod.model.download.DownloadStatus;
|
||||
|
@ -14,6 +15,8 @@ import de.danoeh.antennapod.model.feed.Feed;
|
|||
import de.danoeh.antennapod.model.feed.FeedMedia;
|
||||
import de.danoeh.antennapod.core.util.gui.NotificationUtils;
|
||||
import de.danoeh.antennapod.net.download.serviceinterface.DownloadRequest;
|
||||
import de.danoeh.antennapod.ui.appstartintent.DownloadAuthenticationActivityStarter;
|
||||
import de.danoeh.antennapod.ui.appstartintent.MainActivityStarter;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
|
@ -34,7 +37,7 @@ public class DownloadServiceNotification {
|
|||
.setWhen(0)
|
||||
.setOnlyAlertOnce(true)
|
||||
.setShowWhen(false)
|
||||
.setContentIntent(ClientConfig.downloadServiceCallbacks.getNotificationContentIntent(context))
|
||||
.setContentIntent(getNotificationContentIntent(context))
|
||||
.setSmallIcon(R.drawable.ic_notification_sync);
|
||||
notificationCompatBuilder.setVisibility(NotificationCompat.VISIBILITY_PUBLIC);
|
||||
|
||||
|
@ -185,14 +188,14 @@ public class DownloadServiceNotification {
|
|||
channelId = NotificationUtils.CHANNEL_ID_AUTO_DOWNLOAD;
|
||||
titleId = R.string.auto_download_report_title;
|
||||
iconId = R.drawable.ic_notification_new;
|
||||
intent = ClientConfig.downloadServiceCallbacks.getAutoDownloadReportNotificationContentIntent(context);
|
||||
intent = getAutoDownloadReportNotificationContentIntent(context);
|
||||
id = R.id.notification_auto_download_report;
|
||||
content = createAutoDownloadNotificationContent(reportQueue);
|
||||
} else {
|
||||
channelId = NotificationUtils.CHANNEL_ID_DOWNLOAD_ERROR;
|
||||
titleId = R.string.download_report_title;
|
||||
iconId = R.drawable.ic_notification_sync_error;
|
||||
intent = ClientConfig.downloadServiceCallbacks.getReportNotificationContentIntent(context);
|
||||
intent = getReportNotificationContentIntent(context);
|
||||
id = R.id.notification_download_report;
|
||||
content = createFailedDownloadNotificationContent(reportQueue);
|
||||
}
|
||||
|
@ -226,9 +229,32 @@ public class DownloadServiceNotification {
|
|||
+ ": " + resourceTitle))
|
||||
.setSmallIcon(R.drawable.ic_notification_key)
|
||||
.setAutoCancel(true)
|
||||
.setContentIntent(ClientConfig.downloadServiceCallbacks.getAuthentificationNotificationContentIntent(context, downloadRequest));
|
||||
.setContentIntent(new DownloadAuthenticationActivityStarter(
|
||||
context, downloadRequest.getFeedfileId(), downloadRequest).getPendingIntent());
|
||||
builder.setVisibility(NotificationCompat.VISIBILITY_PUBLIC);
|
||||
NotificationManager nm = (NotificationManager) context.getSystemService(Context.NOTIFICATION_SERVICE);
|
||||
nm.notify(downloadRequest.getSource().hashCode(), builder.build());
|
||||
}
|
||||
|
||||
public PendingIntent getReportNotificationContentIntent(Context context) {
|
||||
Intent intent = new MainActivityStarter(context)
|
||||
.withFragmentLoaded("DownloadsFragment")
|
||||
.withFragmentArgs("show_logs", true)
|
||||
.getIntent();
|
||||
return PendingIntent.getActivity(context, R.id.pending_intent_download_service_report, intent,
|
||||
PendingIntent.FLAG_UPDATE_CURRENT | (Build.VERSION.SDK_INT >= 23 ? PendingIntent.FLAG_IMMUTABLE : 0));
|
||||
}
|
||||
|
||||
public PendingIntent getAutoDownloadReportNotificationContentIntent(Context context) {
|
||||
Intent intent = new MainActivityStarter(context).withFragmentLoaded("QueueFragment").getIntent();
|
||||
return PendingIntent.getActivity(context, R.id.pending_intent_download_service_autodownload_report, intent,
|
||||
PendingIntent.FLAG_UPDATE_CURRENT | (Build.VERSION.SDK_INT >= 23 ? PendingIntent.FLAG_IMMUTABLE : 0));
|
||||
}
|
||||
|
||||
public PendingIntent getNotificationContentIntent(Context context) {
|
||||
Intent intent = new MainActivityStarter(context).withFragmentLoaded("DownloadsFragment").getIntent();
|
||||
return PendingIntent.getActivity(context,
|
||||
R.id.pending_intent_download_service_notification, intent,
|
||||
PendingIntent.FLAG_UPDATE_CURRENT | (Build.VERSION.SDK_INT >= 23 ? PendingIntent.FLAG_IMMUTABLE : 0));
|
||||
}
|
||||
}
|
||||
|
|
|
@ -0,0 +1,39 @@
|
|||
package de.danoeh.antennapod.ui.appstartintent;
|
||||
|
||||
import android.app.PendingIntent;
|
||||
import android.content.Context;
|
||||
import android.content.Intent;
|
||||
import android.os.Build;
|
||||
import android.os.Parcelable;
|
||||
|
||||
/**
|
||||
* Launches the download authentication activity of the app with specific arguments.
|
||||
* Does not require a dependency on the actual implementation of the activity.
|
||||
*/
|
||||
public class DownloadAuthenticationActivityStarter {
|
||||
public static final String INTENT = "de.danoeh.antennapod.intents.DOWNLOAD_AUTH_ACTIVITY";
|
||||
public static final String EXTRA_DOWNLOAD_REQUEST = "download_request";
|
||||
|
||||
private final Intent intent;
|
||||
private final Context context;
|
||||
private final long feedFileId;
|
||||
|
||||
public DownloadAuthenticationActivityStarter(Context context, long feedFileId, Parcelable downloadRequest) {
|
||||
this.context = context;
|
||||
this.feedFileId = feedFileId;
|
||||
intent = new Intent(INTENT);
|
||||
intent.setAction("request" + feedFileId);
|
||||
intent.putExtra(EXTRA_DOWNLOAD_REQUEST, downloadRequest);
|
||||
intent.setPackage(context.getPackageName());
|
||||
}
|
||||
|
||||
public Intent getIntent() {
|
||||
return intent;
|
||||
}
|
||||
|
||||
public PendingIntent getPendingIntent() {
|
||||
return PendingIntent.getActivity(context.getApplicationContext(),
|
||||
("downloadAuth" + feedFileId).hashCode(), getIntent(),
|
||||
PendingIntent.FLAG_ONE_SHOT | (Build.VERSION.SDK_INT >= 23 ? PendingIntent.FLAG_IMMUTABLE : 0));
|
||||
}
|
||||
}
|
|
@ -4,6 +4,7 @@ import android.app.PendingIntent;
|
|||
import android.content.Context;
|
||||
import android.content.Intent;
|
||||
import android.os.Build;
|
||||
import android.os.Bundle;
|
||||
|
||||
/**
|
||||
* Launches the main activity of the app with specific arguments.
|
||||
|
@ -16,9 +17,11 @@ public class MainActivityStarter {
|
|||
public static final String EXTRA_ADD_TO_BACK_STACK = "add_to_back_stack";
|
||||
public static final String EXTRA_FRAGMENT_TAG = "fragment_tag";
|
||||
public static final String EXTRA_OPEN_DRAWER = "open_drawer";
|
||||
public static final String EXTRA_FRAGMENT_ARGS = "fragment_args";
|
||||
|
||||
private final Intent intent;
|
||||
private final Context context;
|
||||
private Bundle fragmentArgs = null;
|
||||
|
||||
public MainActivityStarter(Context context) {
|
||||
this.context = context;
|
||||
|
@ -56,11 +59,19 @@ public class MainActivityStarter {
|
|||
|
||||
public MainActivityStarter withFragmentLoaded(String fragmentName) {
|
||||
intent.putExtra(EXTRA_FRAGMENT_TAG, fragmentName);
|
||||
return withDrawerOpen();
|
||||
return this;
|
||||
}
|
||||
|
||||
private MainActivityStarter withDrawerOpen() {
|
||||
public MainActivityStarter withDrawerOpen() {
|
||||
intent.putExtra(EXTRA_OPEN_DRAWER, true);
|
||||
return this;
|
||||
}
|
||||
|
||||
public MainActivityStarter withFragmentArgs(String name, boolean value) {
|
||||
if (fragmentArgs == null) {
|
||||
fragmentArgs = new Bundle();
|
||||
}
|
||||
fragmentArgs.putBoolean(name, value);
|
||||
return this;
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue