Ionic 4 intercept android back button for navigation - ionic-framework

so in ionic 3 there was registerBackButton() but in ionic 4 this option is no longer there and has been sitting on the shelf for quite some time now.
I have read the post here that tries to solve the solution I am looking for, however, the back button still performs as it wants to.
this SO answer shows another way but it is the same idea of intercepting and navigating, however, I am just, for now, trying to dismiss the top modal in the stack.
scenario: users open a search modal(modal1) which then they click on a users profile modal(modal2). The person wants to go back to the search modal(modal1) but instead of clicking the nice button that allows them to do that, they use the hardware back button.
result: all modals(modal1 and modal2) are closed.
desired effect: using the hardware back button will allow for custom navigation based on logic in place.
attempted code:
this.platform.backButton.subscribeWithPriority(0, (): void => {
this.modalCtrl.getTop().then(
async (value: HTMLIonModalElement): Promise<void> => {
if (!!value) {
await this.modalCtrl.dismiss();
} else {
this.navCtrl.navigateRoot('/home');
}
},
);
});
also have tried :
// registering back, if there is a view on top, close it, don't go to home.
this.platform.backButton.subscribeWithPriority(0, async (): Promise<void>=> {
try {
console.log('try');
const element = await this.modalCtrl.getTop();
if (element) {
console.log('in true');
await element.dismiss();
}
} catch (error) {
console.log('error closing modal', error);
}
});
note when pressing the back button I never see ANY of the console logs... maybe things have changed a lot more? since the previous Stack overflow questions.
UPDATE:
If you are having this same issue then know you are not alone!
This, and many others are well known, see here for a list they are tracking the issues. Nothing else to do... but wait... I guess...
I will update this when there is a change

Related

Ionic - flashes with wrong starting page on app start

Ive created 2 route guards... one which checks if the user is logged in and one if they are unauthenticated
When the app starts, very briefly it determines, while looking for the localstorage cookie, that the user doest exist and so shows the unauth page (i.e login page)
Im wondering what is the best approach to solve this - in my eyes the authguard with observale to see if the user is logged in or not was the best approach but there is that split second while the code runs that it cannot determine and it wants to show something.
Anyone have any similar issues/creative solutions to solve it.
I had this same issue a few months ago, and I solved it by creating an Auth Guard and returning a promise...
auth.guard.ts
canActivate(
next: ActivatedRouteSnapshot,
state: RouterStateSnapshot,
): Observable<boolean> | Promise<boolean> | boolean {
return new Promise(resolve => {
const userAuthObs = this.afAuth.user.subscribe(user => {
if (user) {
resolve(true);
} else {
this.router.navigate(['signup']);
resolve(false);
}
});
});
}
The app just continues to load normally while it waits for this promise to decide where to direct the user.
You can watch a great video about creating auth guards here...
https://www.youtube.com/watch?v=RxLI9_ub6PM

How can I keep the BarcodeScanner screen open without redirecting me to another page?

I am making an application that allows me to scan QR codes, and I managed to make the code work but my doubt is that when I scan the plugin phonegap-plugin-barcodescanner takes me out of the camera interface, what I want to do is to stay in it and show me an alert with the scanned code, and to give it ok in the alert to stay in it, to avoid being clicked to enter it.
I'm working with the plugin phonegap-plugin-barcodescanner, in ionic 3
public scanQR2() {
this._ButtonText = "Escanear";
this._barcodeScanner.scan().then((barcodeData) => {
if (barcodeData.cancelled) {
console.log("User cancelled the action!");
this._ButtonText = "Escanear";
return false;
}
console.log("Scanned successfully!");
console.log(barcodeData);
}, (err) => {
console.log(err);
});
}
I hope that the application when performing a scan stays on the same interface and does not redirect me to another page

button back to my app in the background and when you resume it starts again

I am developing an app in Xamarin.Forms, before I was trying to make a master detail page to become my MainPage when I logged in to my app, this I have already achieved. Now I have the problem that when I use the button behind the phone my app is miimiza and goes to the background which is the behavior I hope, but when I return to my app does not continue showing my master detail page, but returns to my LginPage.
It is as if my app was running twice or at least there were two instances of LoginPage existing at the same time, this is because in my LoginPage I trigger some DisplayAlert according to some messages that my page is listening through the MessaginCenter and they are they shoot twice.
Can someone tell me how I can return the same to my app on the master detail page and not restart in the strange way described?
LoginView.xaml.cs:
public partial class LogonView : ContentPage
{
LogonViewModel contexto = new LogonViewModel();
public LogonView ()
{
InitializeComponent ();
BindingContext = contexto;
MessagingCenter.Subscribe<LogonViewModel>(this, "ErrorCredentials", async (sender) =>
{
await DisplayAlert("Error", "Email or password is incorrect.", "Ok");
}
);
}
protected override void OnDisappearing()
{
base.OnDisappearing();
MessagingCenter.Unsubscribe<LogonViewModel>(this, "ErrorCredentials");
}
}
Part of my ViewModel:
if (Loged)
{
App.token = token;
Application.Current.MainPage = new RootView();
}
else
{
MessagingCenter.Send(this, "ErrorCredentials");
}
Thanks.
I hope this is in Android. All you can do is, you can override the backbuttonpressed method in MainActivity for not closing on back button pressed of the entry page. like below, you can add some conditions as well.
public override void OnBackPressed()
{
Page currentPage = Xamarin.Forms.Application.Current.MainPage.Navigation.NavigationStack.LastOrDefault();
if (currentPage != null)
{
if (currentPage.GetType().Name == "HomePage" || currentPage.GetType().Name == "LoginPage")
{
return;
}
}
base.OnBackPressed();
}
When you press the Home button, the application is paused and the
current state is saved, and finally the application is frozen in
whatever state it is. After this, when you start the app, it is
resumed from the last point it was saved with.
However, when you use the Back button, you keep traversing back in
the activity stack, closing one activity after another. in the end,
when you close the first activity that you opened, your application
exits. This is why whenever you close your application like this, it
gets restarted when you open it again.
Answer taken from this answer. The original question asks about the native Android platform, but it still applies here.
It means you have to Use Setting Plugin or save data in Application properties.
You have to add below code in App.xaml.cs file:
if (SettingClass.UserName == null)
MainPage = new LoginPage();
else
MainPage = new MasterDetailPage();
For Setting Plugin you can refer this link.

removeBackView() not working in Ionic?

JS code
console.log('Login Success');
$ionicHistory.removeBackView();
I am trying to stop to get the login view after login. But even I was logged in, if I click on back arrow of the browser, I am getting the login page. But Once I logged in I should get home page if I click on back arrow. .removeBackView() is not working properly. Please help me.
Even $ionicHistory disableBack also not working
I was having this problem. Putting removeBackView() in the next state didn't work. So instead I added this to the previous state, right before $location.path( '/app/myFirstPage' )
$ionicHistory.nextViewOptions( {
disableBack : true
} );
I also face same type of problem so use another concept, I think its help you.
if ($state.current.name == "app.home" || $state.current.name == "login") {
$ionicPopup.confirm({
title: "Confirm",
template: "Want to exit?"
}).then(function (res) {
if (res) {
navigator.app.exitApp();
}
});
} else {
navigator.app.backHistory();
}

JavaFX 8 Dialog

I'm implementing a document editor with JavaFX8 and e(fx)clipse and want to user to be informed when the export (write to disc) is ongoing. I'm using the main (GUI) Thread for this as I want to block the gui during this operation (which takes 2-3 seconds). During this operation I want to show a small popup to inform the user that the export is ongoing, nothing fancy.
#FXML
public void export() {
Dialog dialog = new Dialog();
dialog.setContentText("exporting ...");
dialog.show();
// some lenghty methods come here, ~equivalent to Thread.sleep(3000);
dialog.hide();
}
When I press the corresponding Button which invokes the export method, I get somehow two dialogs, one of them NOT closing and remaining open after the method has finished.
Does somebody has an idea what's happening here? I'm really interested in a simple solution, I don't need to have a progress bar etc..
Another possibility would be to show a wait-cursor before the operation starts and switching back to the default cursor after that. Unfortunately, this does also not seem to work. I understand that the UI is blocked during the "lengthty" operation, but I don't udnerstand why I cant change the UI before and after that operation....
Your example isn't very complete - however I would recommend using one of two approaches. However, you aren't putting the long process on a background thread which will FREEZE your app. You want to offload that process.
1) Use the ControlsFX Dialog which has a Progess Alert. Tie your work to either a Task or a Service and provide that to the alert. This will pop the alert up while the thread is active, and will automatically close it when done. If you have intermediary progress values, it can be used to update the progress bar.
Or if you don't want to use this dialog, you could do something like this:
Alert progressAlert = displayProgressDialog(message, stage);
Executors.newSingleThreadExecutor().execute(() -> {
try {
//Do you work here....
Platform.runLater(() ->forcefullyHideDialog(progressAlert));
} catch (Exception e) {
//Do what ever handling you need here....
Platform.runLater(() ->forcefullyHideDialog(progressAlert));
}
});
private Alert displayProgressDialog(String message, Stage stage) {
Alert progressAlert = new Alert(AlertType.NONE);
final ProgressBar progressBar = new ProgressBar();
progressBar.setMaxWidth(Double.MAX_VALUE);
progressBar.setPrefHeight(30);
final Label progressLabel = new Label(message);
progressAlert.setTitle("Please wait....");
progressAlert.setGraphic(progressBar);
progressAlert.setHeaderText("This will take a moment...");
VBox vbox = new VBox(20, progressLabel, progressBar);
vbox.setMaxWidth(Double.MAX_VALUE);
vbox.setPrefSize(300, 100);
progressAlert.getDialogPane().setContent(vbox);
progressAlert.initModality(Modality.WINDOW_MODAL);
progressAlert.initOwner(stage);
progressAlert.show();
return progressAlert;
}
private void forcefullyHideDialog(javafx.scene.control.Dialog<?> dialog) {
// for the dialog to be able to hide, we need a cancel button,
// so lets put one in now and then immediately call hide, and then
// remove the button again (if necessary).
DialogPane dialogPane = dialog.getDialogPane();
dialogPane.getButtonTypes().add(ButtonType.CANCEL);
dialog.hide();
dialogPane.getButtonTypes().remove(ButtonType.CANCEL);
}