XamarinForms Shell OnResume - previous page is showing - xamarin

I want to achieve lock mechanism in XF 4.5.0 Shell app.
I have static timer that counts how much seconds passed, and based on some logic present either screen that user was before put the app in behind (user went to instagram, but app is in the background running)
So, my OnResume() method looks like this:
private bool IsUserExists()
{
if (!string.IsNullOrWhiteSpace(GlobalAppSettings.Email) && !string.IsNullOrWhiteSpace(GlobalAppSettings.Password) && !string.IsNullOrWhiteSpace(GlobalAppSettings.Pin))
{
return true;
}
else
{
return false;
}
}
protected override void OnResume()
{
if ((!OnSleepOrPauseTime.HasValue || OnSleepOrPauseTime.Value.AddSeconds(5) <= DateTime.Now)
&&(IsUserExists()))
{
Xamarin.Forms.Device.BeginInvokeOnMainThread(async () =>
{
await Shell.Current.GoToAsync(Routes.LoginPinPage, false);
});
}
}
The problem: user sees for a like half second the screen where he was before, and then it redirects to LoginPinPage.
The happy path: Should be that user doesnt see that flickering page that was before exiting form an app, just immediately lock screen.
Possible solution: That crossed on my mind, before leaving the app to somehow redirect in background app to login pin screen?

PushAsync has 2 overloads - docs
By default the PushAsync method pushes the new page with animation. I think that this is the so-called "flickering" that you are referring to.
You can try to use the second overload and pass false for the animated property and see if it makes any difference.
PushAsync(new LoginPinPage(), false);
If you want to redirect the user on app leave - you can use another of the Application's lifecycle methods - OnSleep and invoke your navigation there. But I suggest to try it without animations first.
Keep in mind that, should you choose to use the OnSleep method, you will also have to push the page without animations. I have just tested pushing with animations and I do indeed see the flickering that you are mentioning. Setting the animated flag to false, removed any flickering for me.

Related

Access multiple renderers with spectron

I'm working on an Electron application. The main process opens a first renderer (browserWindow). When the user click on a button, this renderer sends an IPC message to the main process. When this message is received, the main process opens a second, different, renderer. Those two renderers live concurently. The application works fine.
Then, using Spectron to test this app, how to access both renderers ? The problem is app.rendererProcess always returns the first renderer.
This is the same problem with app.client which always contains the WebdriverIO browser object of the first renderer and never the second.
Is there a way to list all the process of a Spectron application in a test? Is it possible to access the browser object of the second renderer ?
With AVA:
test.(async t => {
// the application is open before the test
// at this point, the first renderer is open
// click on the button to open the second renderer
await t.context.app.client.click('#bt_openSecondRenderer');
// wait for the second renderer to open
// error: this element doesn't exist
await t.context.app.client.click('elt_of_the_scnd_renderer');
});
I'm using AVA but I don't think it is the problem. So if anyone know how to make this works with Mocha or anything else, it would be very helpfull.
Thanks !
Following the philosophy given by Tim answer, instead of using BrowserWindow, we can use WebDriverIO to focus the desired window:
test.(async t => {
// here, t.context.app.client handles the first window
await t.context.app.client.windowByIndex(1).then(() => {
// here, t.context.app.client handles the second window
});
});
Like a user, Specton can only interact with the focused window. This should work but I haven't tested it:
// The docs say that app.electron gives you access to all the Electron APIs
// This should get you a list of BrowserWindows
const windows = await t.context.app.electron.BrowserWindow.getAllWindows();
// Focus the window you want to interact with
windows[1].focus();
// Do your clicking
await t.context.app.client.click('elt_of_the_scnd_renderer');
it('Switch window', async () => {
await app.client.waitUntilWindowLoaded(100000)
.windowByIndex(0);
.windowByIndex(1);
})

Detect controller input in VRTK

I'm kind of new to this so sorry if I'm writing in the wrong place - let me know and I'll move / delete this comment.
I'm currently having issues detecting controller input while using VRTK.
For example, when I have a collision between two objects, I want to be able to detect what buttons are being pressed on the controllers but can't seem to work out how I can do this.
Also, I have implemented the Interact Use functionality but I'm struggling to work out how to make two buttons do different actions.
For example:
once I grab an object with the simple pointer I want one button to
bring the object closer and another to move it away, but I've only
managed to implement one or the other.
Any suggestions? I've looked everywhere in the docs, examples and Google and can't seem to find anything. Any help would be MUCH appreciated! Pulling my hair out here!
You could utilise the Grabbedmethod on the InteractableObject: https://vrtoolkit.readme.io/docs/vrtk_interactableobject#section-grabbed-1
Or you could use the ControllerGrabInteractableObject event on The InteractGrab script: https://vrtoolkit.readme.io/docs/vrtk_interactgrab#section-class-events
Or you could have an Update routine and check the grabbed status on the controller doing GetGrabbedObject() != null (which checks to see if the controller has an object grabbed if it's null then one isn't grabbed).
Then you can use the ControllerEvents button bools to do something on a button press. So a script with this in that sits on the controller script alias gameobject next to the interact grab script:
void Update() {
if (GetComponent<VRTK_InteractGrab>().GetGrabbedObject != null) {
var controllerEvents = GetComponent<VRTK_ControllerEvents>();
if (controllerEvents.IsButtonPressed(VRTK_ControllerEvents.ButtonAlias.Trigger_Press) {
//Do something on trigger press
}
if (controllerEvents.IsButtonPressed(VRTK_ControllerEvents.ButtonAlias.Grip_Press) {
//Do something on grip press
}
}
}

GCD hangs in menu bar app

I have a menu bar app, which out of nowhere (no code changes) stopped working. Oddly the app continues to execute once I select it, or if I use any of the system keys (volume, brightness, iTunes, etc...). My code uses GCD to manage behavior. Is there a way to debug this and see what's going on behind the scenes? My confusion is why using the system keys (which pop up a window to show volume level, brightness level) makes my software continue execution?
DispatchQueue.main.async() { doSomething() }
func doSomething() {
//run a bunch of things in a background process
//so far works ok
let fooFrame = NSMakeRect(0, 0, 100, 100)
print("tag1") //this prints just fine
DispqtchQueue.main.sync() {
print("tag2") //this doesn't print and doesn't execute until I click on the app or use the volume keys.
//run code to update UI works fine once I use volume keys (no idea why)
self.window.frame = fooFrame
}
}
Also I am not getting any messages or exceptions raised. Just the app freezes. I have also noticed that if I have multiple displays and activate a second display, where the menu bar activates, then my process continues again and everything is normal.
Calling AnyQue.sync from the the same queue (AnyQueue) causes a deadlock, as the calling task is waiting for the called one. But the called one will start after the calling one finished.
As written by matt, using async fixes the issue. This code:
func doSomething() {
print("tag1")
DispatchQueue.main.async() {
print("tag2")
}
}
DispatchQueue.main.async() {
doSomething()
}
prints:
tag1
tag2
Figured it out, I had a CFRunLoop running which needed to be stopped and then everything seems to work fine now. Also additionally, the entire process was running as a background dispatch process, that's why using sync worked.

Disable 2 finger swipe back navigation in Chrome on OSX [duplicate]

I want to disable the two finger swipe that causes Chrome going back or forward.
I have a website where the user might lose progress on his work if he doesn't specifically saves.
I have tried using window.onbeforeunload but that doesn't seem to work if I have hashes in the url (back forward would change between www.example.com/work/#step1#unsaved www.example.com/work/#step0) and the event doesn't seem to trigger.
I was about to switch to another solution but today I noticed that in Google Docs it's completely disabled. How did they achieve that?
Disable Chrome two fingers back/forward swipe
This worked for me. In your CSS file:
html {
overscroll-behavior-x: none;
}
body {
overscroll-behavior-x: none;
}
Make the specific page open in a new tab/window by default (by putting target="_blank"> in hyperlink). That way there'll be no previous page to go back to.
Or prevent Horizontal Scrolling by default. To do that, you can use jquery.mousewheel to do:
$(document).on("mousewheel",function(event,delta){
// prevent horizontal scrolling
if (event.originalEvent.wheelDeltaX !== 0) {
event.preventDefault();
}
});
Assuming you have a horizontal-scrolling element, adding overscroll-behavior-x: contain; is the easiest way prevent the scroll action from spilling out into the page and causing the navigation.
https://dev.to/danburzo/css-micro-tip-prevent-history-navigation-on-horizontally-scrolling-elements-3iil
https://caniuse.com/#feat=css-overscroll-behavior
Disable or replace swipe gestures for Google Chrome 61
The question that leads me here was marked "duplicate" and closed to answers. I believe this answer is better suited for the "duplicated" question, however, I feel this answer could possibly save time for someone landing on either question.
Better question:
Disable navigation swipe on Chrome browser in javascript
This Google developers article helped me to allow the e.preventDefault() to work and prevent swipe gestures as of Chrome 61.
https://developers.google.com/web/updates/2017/01/scrolling-intervention
givanse's answer to the following was the code that I used to write my own swipe event handlers:
Detect a finger swipe through JavaScript on the iPhone and Android
In summary, the following two events are used to implement the swipe gestures:
handleTouchStart (e) {
...
},
handleTouchMove (e) {
...
e.preventDefault()
}
As of Chrome 56, the default behavior is to make the event listeners passive and thus disable the ability to prevent Chrome's swipe gestures. To override this behavior, event listeners can be added as follows:
document.addEventListener(
'touchstart',
this.handleTouchStart,
{passive: false}
)
document.addEventListener(
'touchmove',
this.handleTouchMove,
{passive: false}
)
By passing the {passive: false} object as the third parameter to the addEventListener method, the listener is registered as active and can stop Chrome's default behavior with the e.preventDefault() event method.
Building on both the previous answers given by #roy riojas and #redgetan - I combined their answers to allow for this to be dynamic and prevent both forward and backwards - again - per #roy's comments - you must know the class of your element, and for this implementation - the class of the nested element that is actually being scrolled
(function ($) {
$(document).on('mousewheel', function(e) {
var $target = $(e.target).closest('.scrollable-h');
var scroll = $target.scrollLeft();
var maxScroll = $target.find('.scrollable-h-content').width() - $target.width();
if(scroll <= 0) {
if(scroll <= 0 && e.originalEvent.wheelDeltaX >= 0) {
e.preventDefault();
}
}
if(scroll >= maxScroll) {
if (scroll >1 && e.originalEvent.wheelDeltaX <= 0) {
e.preventDefault();
}
}
});}(jQuery));
I've been working on something similar where I want to override the forward/backward history swiping gesture. Depending on what your swipe area is you can tweak the selector as follows:
html { touch-action:none; }
This is the associated documentation that gives you all the properties to all touch actions like panning or zooming features built into the browser.
https://developer.mozilla.org/en-US/docs/Web/CSS/touch-action
I was able to disable it by typing chrome://flags in the address bar and heading down to "Overscroll history navigation" and setting it to "Disabled" from the dropdown.
You can disable back/forward with this code:
document.addEventListener("wheel", function(event) {
event.preventDefault();
}, { passive: false });
Note that adding { passive: false } is essential, at least in Chrome. If you only want to disable back/forward in certain areas you can use code like this (assuming you're using jquery and you add the class disable-back-forward to the sections where you want to disable back/forward):
document.addEventListener("wheel", function(event) {
if ($(event.target).closest('.disable-back-forward').length)
event.preventDefault();
}, { passive: false });
Hi this worked for me on chrome but not for the entire page, but for places where I have scrollable content.
In Google Docs (Spreadsheets) it seems to be working because they don't have a back page to go. If you navigate to another URL (manually) it will not prevent you from navigating back.
$(document).on('mousewheel', function(e) {
var $target = $(e.target).closest('.scrollable-h');
if ($target.scrollLeft () <= 4) {
$target.scrollLeft(5);
return false;
}
});
One thing to keep in mind is that the code above is making two assumptions:
your element with horizontal scrollable content has a class scrollable-h
If checks if the scrollLeft if bigger less than 4px and then just make it scroll to 5px
returning false effectively cancel the back gesture
Important:
- This only prevents the back swipe gesture, when is done fast, if you do it very slow it will still trigger sometimes.
Also this does not prevent the forward swipe gesture, but it could also be done by checking if the element has reached the maximum scrollLeft. If that is the case then move it 20px back and return false to prevent the event from happening... It is up to you to add this use case if it happens to make sense to you.
You can take a look to a proof of concept here. http://jsfiddle.net/royriojas/JVA6m/#base
You're looking at the problem at the wrong level. OnBeforeUnload is simply not triggered because there is nothing being unloaded from the browsers perspective. Therefore you have, quite bluntly, implemented the wrong mechanism for versioning - fragments are for page states, not document states as you are using it now.
If you insist on maintaining state through hash fragments you need to use another mechanism to guard against page state changing. Since all current browsers support LocalStorage I'd use that. And well, while at it, put all the document state data there instead of in the URL, since that is how Google Docs does it and that is why they don't have this issue.

Converting from 3.1 to 4.0... gamestates

I'm restarting development of a game I was working on, and have successfully converted it over to XNA 4.0 using the cheat sheet. Most of it works, some of it doesn't, and I'm in the process of fixing what doesn't work.
One thing that I had was a state system that was heavily based on the state system used as an example of XNA Unleashed, the ebook. I didn't have much in it.... basically just the ability to pause the game.
When I paused the game, the action of the game would stop, and the word "PAUSED" would appear in block letters across the screen, and you'd see the paused action. However, now it seems that the sprite batch automatically clears out everything between frames, so when I pause the game now, the screen clears, leaving PAUSED over a purple background. Back then, I believe that adding "SaveStateMode.SaveState" would prevent that from happening, but that functionality was removed. When I did some research, I found out that it was removed because it was essentially useless, that's all handled in the game state manager.
However, I can't find any documentation on this. Where should I start? Right now, my code looks like this:
In the Playing Game State update method:
if (input.WasPressed(0, Buttons.Start, Keys.Enter))
{
GameManager.PushState((GameState)ThisGame.PausedGameState.Value);
}
public void PushState(GameState newState)
{
AddState(newState);
//Let everyone know we just changed states
if (OnStateChange != null)
{
OnStateChange(this, null);
}
}
private void AddState(GameState state)
{
states.Push(state);
Game.Components.Add(state);
//Register the event for this state
OnStateChange += state.StateChanged;
}
//PausedGameState Draw method:
public override void Draw(GameTime gameTime)
{
ThisGame.SpriteBatch.Begin(SpriteSortMode.Deferred, BlendState.AlphaBlend, null, null, null, null);
DrawPaused(); //draws the Paused Text
ThisGame.SpriteBatch.End();
}
The goal is to make "PAUSED" appear over the screen, with a snapshot of where the gameplay left off... and not "PAUSED" over a cleared purple screen.
Do you suppose that GraphicsDevice.Clear() somehow got called after the state changed to paused? What does the DrawPaused() method do in your code?

Resources