Sending email in Xamarin Forms project - plugins

I'm trying to use the Xamarin.Plugins.Messaging NuGet package to send emails from within my Xamrin Forms shared project but keep running into Warning: Attempt to present X on Y whose view is not in the window hierarchy! and nothing appears.
Is there something else that I have to set up?
private void SendEmail()
{
var emailMessagner = CrossMessaging.Current.EmailMessenger;
if (emailMessagner.CanSendEmail)
{
Console.WriteLine("Can send mail");
var email = new EmailMessageBuilder()
.To("emailaddress#gmail.com")
.Subject("Setting subject")
.Body("Setting email body")
.WithAttachment(_filePath, "text/html")
.Build();
emailMessagner.SendEmail(email);
}
else
{
Console.WriteLine("Cant send mail");
}
}
It works on android (other than getting Permission denied for attachment), but I get window not in hierarchy error for iOS. I could write my own email sender that would make sure it's viewController is in the window hierarchy but I assumed this plugin handled that.

I was having the same issue with my Xamarin Forms app. I was calling SendEmail() from a ContentPage which I loaded with PushModalAsync() in a PCL project. As far as I can tell, this doesn't work in any way, shape or form from a modal form.
My work-around was to add a public static Queue property to the calling form (the main form of my app in this case) and when I needed to send an email, I added it to the queue. Then I overrode OnAppearing() on my main page and looped through all of the emails in the queue whenever the main form came back into view. I put a note on my modal form telling the user that the email would be sent when the modal form was closed. Not perfect, but it works. If you can find a way around this for modal forms, that would be fantastic!
Mike

Related

In Delphi, how to restore a minimized modal form that is not the main form

In the project source, I detect a previous instance of my app, and open it then terminate the new instance.
Remember, I do this in the project source.
The application has a main form that can open a second modal form. If the second, modal, form is not open when the app is minimized (or the user switches to another application) it works fine.
The old main form is opened and the new instance is terminated. However, if the second modal form is minimized, its parent main form is also minimized. That's good UI behavior.
The problem exists when attempting to restore the modal form by a new instance. I can't seem to get the modal form to restore.
I can restore the main form, however the modal form still has focus, but is hidden.
This prevents any user action on the now visible main form. From the user's point of view, the app is hung.
The modal form's caption does not change, so it's easy to get its handle.
The app has a DataModule, which is created first. I do all the duplicate app testing in the project source after the DM is created, but before any other forms are, and well before Application.Run.
That assures that the handles I acquire come from the existing app.
I've tried:
PreviousHandle := FindWindow(nil, PAnsiChar('Form Editor'))
ShowWindow(PreviousHandle,SW_RESTORE);
ShowWindow(PreviousHandle,SW_NORMAL);
BringWindowToTop(PreviousHandle);
The best I've gotten out of variations of this is restoring the main form.
When the handle is for the modal form, it sometimes shows in the lower left as a minimized form.
I say sometimes because I've tried so many variations of the above that I don't remember exactly how this code sample behaved.
All I know is, whatever I've tried from the project source did not restore the modal form, so I tried sending a custom Windows Message to the modal form.
I know the message arrived and the message handler caught it. Example:
if not PostMessage(PreviousHandle,WM_RESTORE_FORM,PreviousHandle,0) then
ShowMessage('Can''t automatically show the Form program. '+
'Please click the taskbar icon.');
Here's what the message handler looks like. It is in the Modal Form. As you can see, I pass the form's handle as a Message param. I've verified that it arrives.
Here's the code in a TApplicationEvents OnMessage event:
procedure TfrmDisplayForm.ApplicationEvents1Message(var Msg: tagMSG;
var Handled: Boolean);
var
oldHwnd : THandle;
begin
if Msg.message = WM_RESTORE_ACORD then
begin
oldHwnd := Msg.lParam;
if ForceForegroundWindow(OldHwnd) then ShowMessage('true') else ShowMessage('False');
Handled := True;
end;
end;
Here's the function that is called. However, I've tried various ShowWindows(...) combinations with no luck. Actually, this function didn't do the trick either.
function TfrmDisplayForm.ForceForegroundWindow(hWnd: THandle): BOOL;
var
hCurWnd: THandle;
begin
{credit Peter Below}
hCurWnd := GetForegroundWindow;
AttachThreadInput(GetWindowThreadProcessId(hCurWnd, nil),
GetCurrentThreadId, True);
Result := SetForegroundWindow(hWnd);
AttachThreadInput(GetWindowThreadProcessId(hCurWnd, nil),
GetCurrentThreadId, False);
end;
I've been working on this for a couple of days, and don't know what I'm doing wrong.
Question: How can I restore the modal form? It must be possible because it restores perfectly when the taskbar icon is clicked.
Don't try to restore individual forms instead use TApplication.Restore
Calling TApplication.Restore will restore all of the application windows to the state before the whole application was minimized same as clicking on TaskBar icon of the application.
PS: I also hope you are not allowing users to minimize individual Modal forms. Or you may also run into a problem where application seems to be stuck.

C++ Builder bizarre issue (taskbar icon not appearing)?

I have an application with a login form (which is the main form) and a main form, which is opened after the log-in one is filled in with the correct info.
However, the program icon does not appear on the taskbar. I would like to ask, why does this happen?
I don't think there is anything bizarre in this behaviour.
I assume You hide login form after user provides login information?
By default Main form owns taskbar:
Application->MainFormOnTaskBar = true;
So either make frmMain "main" instead of LoginForm and create login form dynamically before main Form (this will make login form invisible on taskbar) or add following code to frmMain -
in header:
void __fastcall CreateParams(Controls::TCreateParams &Params);
and in the .cpp file:
void __fastcall frmMain::CreateParams(Controls::TCreateParams &Params)
{
TForm::CreateParams(Params);
Params.ExStyle = Params.ExStyle | WS_EX_APPWINDOW;
Params.WndParent = ParentWindow;
}
WS_EX_APPWINDOW "Forces a top-level window onto the taskbar when the window is visible."
As described in this MSDN article
and Embarcadero DocWiki.

JScript setText() in email and password not being read

Hello StackOverflow -
My issue is a strange one and hopefully someone has seen something like it before.
I'm using TestComplete to do front-end functional testing with a REST API.
We have a Login button that drops a modal to enter email and password.
My script:
function modalCheck()
{
var emailBox, mainPage, unexpWnd;
//Browsers.Item(btFirefox).Run("http://[redacted]");
var mainPage = Sys.Browser("firefox").Page("http://[redacted]/");
var loginModalButton = Sys.Browser("firefox").Page("http://[redacted]/").Panel(0).Header(0).Panel(0).Nav(0).Panel(0).Panel(1).Button("login");
//click login button to drop modal
if(loginModalButton.Exists)
{
loginModalButton.Click();
Log.Message("This button exists and I clicked it.");
}
//modal now visible = assign text and click login submit button
var emailBox = Sys.Browser("firefox").Page("http://[redacted]/").Panel(4).Panel(0).Panel(0).Panel(1).Form(0).Panel(0).Panel(0).Panel(0).Panel(0).Textbox("email");
var passwordBox = Sys.Browser("firefox").Page("http://[redacted]/").Panel(4).Panel(0).Panel(0).Panel(1).Form(0).Panel(0).Panel(0).Panel(0).Panel(0).PasswordBox("password");
var loginSubmitButton = Sys.Browser("firefox").Page("http://[redacted]/").Panel(4).Panel(0).Panel(0).Panel(1).Form(0).Panel(1).Panel(0).Panel(0).SubmitButton("login_submit");
emailBox.setText("[redacted]");
passwordBox.setText("[redacted]");
Delay(5000);
loginSubmitButton.Click();
//need to logout - now the button will show "Logout" instead of "Sign Up"
var logoutButton = Sys.Browser("firefox").Page("http://[redacted]/").Panel(0).Header(0).Panel(0).Nav(0).Panel(0).Panel(1).Button("logout");
if(logoutButton.Exists)
{
logoutButton.Click();
Log.Message("This button exists and I clicked it.");
}
}
I can drop the modal, enter my email and password, and click the login button successfully with this script. The problem is - my credentials aren't recognized and/or are flagged as incorrect if they're entered via my script or if the browser autofills them. They work if entered manually (so I know they're correct and I'm not locked out).
As a tester, this is pretty black-box for me. I can pass along some HTML but I'm not involved in the creation. I can also ask the front-end guys more specific questions if it would help solve my issue.
What does it look like my problem is?!
Use the Keys method instead of SetText. The later puts the text directly to the control and this does not fire the required events.
emailBox.Keys("[redacted]");
passwordBox.Keys("[redacted]");

Can we just let "prepareFromRequest" to behave just like traditional non-Ajax page?

Ok, let see how traditional non-Ajax page work. Suppose you have a page like the below link
abc.com#!search;item=car
In the traditional non-Ajax website, when first time you call "abc.com#!search;item=car", it will go to server and get data. After that you go to other page like "abc.com#!customer;name=tom" and then you hit back button it will go back to "abc.com#!search;item=car". However, this time it won't call to the server again cos it remembered it did before.
Now Here is the GWTP problem. Suppose the above abc.com was built in GWTP technology.
At the first time wen user enters the "abc.com#!search;item=car", the GWTP app will initialize the page "search" via onBind, then the prepareFromRequest will be called & it will go to server to get data.
That is Good, no problem. However, if we open a new page (like customer page) by using revealPlace, then we hit the back button it will go back to "search" page & it will call prepareFromRequest again. The prepareFromRequest will then make the exactly same call to server again. That is not good cos it wastes resource.
So I want the "prepareFromRequest" to be called ONLY at the time we initialise the page (run after onBind) & block the "prepareFromRequest" in all other page request (ex like user press the back button).
It mean "prepareFromRequest" should work just like traditional non-Ajax page mentioned above.
Can we do that? or
Do you have a better solution?
Why don't you just check in your prepareFromRequest method if you have already a search result for that specific searchterm and only issue a call to the backend if it has changed?
Something like this:
public Presenter extends .... {
String searchItem = null;
List<DTO> searchResult = null;
#Override
public void prepareFromRequest(PlaceRequest placeRequest) {
super.prepareFromRequest(placeRequest);
String item = placeRequest.getParameter("item",null));
if (searchItem == null || !searchItem.equals(item)) {
searchItem = item;
// MAKE A CALL TO THE BACKEND AND STORE THE DATA IN A FIELD.
searchResult = GET_FROM_SERVER(searchItem);
}
}
}

go back to the first form in windows mobile application

i am developing an application in which i have a logout option at all the forms. When i click that button I have to return to login form which is the first form to be displayed . So i am able to track back to the first from by making a new object of this from by the way this idea is bad to implement because the other froms are also in the stack. My question is how will i go to that first form while the other form objects are distroyed.
The whole idea is about login-logout functionality in winMo app. If somebody can help me with some part of code it will be very great.
Regards,
Madhup
The easiest way is to pass a reference to the Log-in form to all other forms. Avoid creating and destroying forms. Since you know you are going to reuse them, create them only once and then show or hide them.
In log-in form:
if (isLoginSuccessfull) {
newForm.SetParentForm(this);
newForm.Show();
// Do not call Close();
}
In secondary-forms:
public void SetParentForm(Form parent) {
this.parent = parent;
}
// When you need to close the form:
parent.Show();