Maximum call stack size exceeded error when opening application - nativescript

Inside one my tabview tabs I have a 'Logout' button with this
var application = require("application");
application.run({ moduleName: "app-login" });
However I get:
RangeError: Maximum call stack size exceeded
when the code is executed. Ultimately I'm trying to get back to the login screen when the user needs to logout, in full screen (i.e not within the tab). The architecture of the application is based similar to the tabview-template example, with frames for each tab.
Any help much appreciated!

Indeed the application.run() is the method that bootstraps your app. You shouldn't call it twice.
The nested frames feature isn't officially supported and isn't documented, but it's possible in NativeScript core. The reason it's not yet official is due to some unexpected side effects with ActionBars and such. In your scenario you should simply get the correct Frame and call navigate() on it. I created a simple playground example here - https://play.nativescript.org/?template=play-tsc&id=tq6B2K
The key in this example is to assign an id to each Frame in your xml, so that you can use the getFrameById() method to find the correct Frame in the hierarchy.
Also, note that I have set actionBarHidden to true on the page with the tabs. If this is not set, you would see two nested ActionBars.

I may be misunderstanding your architecture, but I don't think calling the bootstrap function application.run({ moduleName: "app-login" }); more than once in the app's lifecycle is valid as the app is already running (regardless the screen it's on).

Related

Laravel + InertiaJS + Vue 3: Play transition on page BEFORE navigation with Link, button, etc

TL;DR: In a Laravel + InertiaJS + Vue 3 developed application, how can I achieve to have a transition between "pages" loaded within a persistent layout <main> section - for example, have that section animate (say, fade out) before loading the next page, then animate (fade) that new page in - when using standard Inertia routing for navigation? I have managed to do it on entering/showing the page, but have found no way to animate before navigation happens.
LONG(ish): The Way I'm trying to do it
Let's assume there is an application (developed with Laravel + InertiaJS + Vue 3).
I have an element in the markup of an Inertia persistent layout that is conditionally shown if a value is true (v-if="shouldAnimate") that is initially set to false when declared, and when onMounted fires, it sets that value to true which in turn triggers the animation to run (doesn't really matter how the animation works, but just in case, I have options to use either GSAP or anime.js).
Up to this point, all is good: every time I navigate to a page (using Inertia-adequate methods such as the Link component) the animation triggers and I am a happy guy.
BUT: I would very much like to be able to play another animation (the reverse of the previous one) before, say, navigation to the next page occurs. I have tried almost everything I can think of and have not been successful. Here's what got the closest to what I need:
I tried hooking into the InertiaJS event Inertia.on('before', ...): effectively, the event fires up right before navigation (checked with some good-old console log), so I tried firing up the animation at this point, only to find out that the Inertia event looks like it is destroying the page immediately before the animation has had time to play; no problem: I'll just event.preventDefault() it, run the animation and THEN, using a setTimeout timed to the length of the animation (300ms) I'll resume navigation, say, by using Inertia.visit.
Doesn't work. Somehow, the default behaviour is prevented (stops the navigation), the animation plays back, but when it comes to the "resume navigation part" I have had mixed results depending on what I use:
Code looks roughly like this:
let removeListener = Inertia.on('before', (event) => {
event.preventDefault()
// Play animation here
setTimeout(() => {
// SOME INERTIA ACTION DESCRIBED BELOW
}, 300)
})
Independently of whether I use Inertia.get(event.detail.visit.url) or Inertia.visit(event.detail.visit.url) what happens is the animation runs its course, and then the timer runs out and this whole code RUNS AGAIN AND AGAIN in intervals equal to the timer. I also tried to do this using the complete event of the animation to trigger the navigation but it behaves the same.
I know this is related to me being an ignorant about how both Inertia and events work, and I am sure there is a proper (correct? right?) way to achieve what I need, but either I have failed in using the correct terms to look for it, or I am approaching this the wrong way. Hopefully this information is enough to explain my issue.
Any help or pointer would be GREATLY appreciated, so thanks in advance.

Making sure the route specified in initialRouteName is always added as the first screen in the stack

Our app have multiple tabs, each tab contains a stack.
We need to be able to navigate from a screen in a stack belonging to one tab to a specific screen in a stack belonging to another tab. This can be done like so navigation.navigate("tab2", {screen:"screen2"}).
We are using react-navigation version 5
Current Behavior
The problem is that if I have not navigated to the initial route for the destination stack(route) before, screen2 is now the only screen in the stack. I need somehow to always make sure that the screen specified in the initialRouteName is added to the stack first.
Expected Behavior
If you specify initialRouteName that route is always added as the first route in the stack, even if you navigate to a specific route defined in the stack.
Setting lazy=false, would solve the issue, but it's important to not initialise the "initial route screen" before actual navigating to a screen in the stack.
It might be that this is work as designed, but are there any way to achieve the behavior I expect then?
How to reproduce
The issue/problem can be reproduced in this snack
Click the "Navigate to Screen2 on Tab 2" button on "tab1". Make sure you have not clicked on Tab2 before doing this.
You are now navigated to Screen2 on Tab2 with no option to navigation to the screen specified in initialRouteName.
This is more of less a copy of this issue
Found that you actual can navigate to a nested navigator and make sure the route specified in initialRouteName is the initial route. It can be done by specifying initial:false like so:
navigation.navigate("tab2", {screen:"screen2", initial: false})
Documentation can be found here

Assertion error when using NSCollectionView with QLPreviewView

I am using an NSCollectionView where each NSCollectionViewItem uses a QLPreviewView to get a rendering of a file's content.
(This is an attempt at a file browser for images and other previewable files.)
Initially, this works fine.
However, once collection items are getting re-used, I get an assertion error (both in 10.13 and 10.14):
[QL] Assertion failure (unreachable code) - [… MyPreviewView activated … doc:[QLPreviewDocument …]] is already activated
Apparently, before I can re-use a NSCollectionViewItem, the previously used QLPreviewItem needs to be set to inactive state somehow. How do I do that?
I've tried to send the close message to the QLPreviewView instance but that doesn't make a difference.
I also do not get a dealloc call on my QLPreviewView subclass, which suggests that the object is still referenced by something else, possibly the QLPreviewDocument, which then gets confused about the change of state.
I have made a demo project available on github: https://github.com/tempelmann/NSCollectionViewWithQLPreview
To test: Run it, then scroll down. When reaching items 50 to 60, the assertion will be triggered.
The fix is to set QLPrewiewView's shouldCloseWithWindow property to NO.
This, I suspect, tells the controller behind the scenes not to attach itself to higher level structures, i.e. tells it to remain self-sufficient.
So, adding this line to the code that sets up a new MyPrewiewView object in the sample code's ViewController.m file prevents the error:
qlView.shouldCloseWithWindow = NO;

CFRunLoopObserver vs. nested CFRunLoops

I`ve got a Cocoa UI app that needs to update its main window as fast as the rest of its UI event loop permits, so I implemented the main updater function via a CFRunLoopObserver. I also have an application-modal alert box and a context menu.
So, my problem is that when I have both an alert and a context menu on the screen, the updater gets stuck, presumably due to excess number of nested run loops above the one it has been attached to back at the start. Surprisingly, I can alleviate the issue by duplicating the observer, and it keeps running — one instance only, randomly chosen from the two existing when the «blocking» nested loop starts. When it ends (a menu item gets chosen, an alert exceeds its timeout or is dismissed manually — whatever), things get back to normal, and the blocked observer regains the ability to run.
Now the question: is there a way to have a single observer that gets executed no matter how deep the run loop stack is?
Sidestepping the runloop issue, have you looked at CVDisplayLink?
You set one up using CVDisplayLinkCreateWithActiveCGDisplays(), and then attach a callback using CVDisplayLinkSetOutputCallback(). It'll ask for data at the refresh rate of the display, so you'll be getting the callback as fast as you need.

Inspecting Firefox Components.interfaces.nsIDOMWindowUtils.screenPixelsPerCSSPixel value in Javascript Scratchpad

I am using Firefox Scratchpad to understand the scaling behavior that
results when the user types the CTRL-PLUS and CTRL-MINUS keys.
In Javascript Scratchpad, I'm evaluating a snippet of Javascript code that accesses the
Components.interfaces.nsIDOMWindowUtils.screenPixelsPerCSSPixel
property like this:
var util = window.QueryInterface(Components.interfaces.nsIInterfaceRequestor).getInterface(Components.interfaces.nsIDOMWindowUtils);
util.screenPixelsPerCSSPixel
In Scratchpad typing CTRL-L after the last l in screenPixelsPerCSSPixel above results in an Exception:
Exception: The operation is insecure.
(Note that the current active Firefox tab is pointing to http://www.google.com).
The devtools.chrome.enabled flag is set to true in this
context, but that does not seem to matter as an Exception is still being thrown.
What do I need to do in order to get Javascript Scratchpad to display
that value?
This is intended only to be temporary to gain understanding during a
debug ritual. Set aside for now the obvious question of "Why is it a
security risk to show a scaling factor?". I'm only after getting at
the value from the confines of standard, and safe, Firefox controls
such as enabling/disabling about:config values that I can easily
undo later when I'm done.
Here is the answer I found:
Accessing the window variable from the Scratchpad scope whose
Environment (see its Environment menu) is set to Content yeilds one
type of object, while if Environment was set to Browser, a different
type of object is in play (CTRL-L on it in Scratch pad reports it is
of type ChromeWindow). The window.content object is the content
object relative to the ChromeWindow object.
The value of
....QueryInterface(Components.interfaces.nsIInterfaceRequestor).getInterface(Components.interfaces.nsIDOMWindowUtils).screenPixelsPerCSSPixel
relative to the window object (ChromeWindow) object returns
1, while calling it on the window.content shows something other
than 1 and show that scaling is involved.
(EDIT: I relocated the Javascript code that used to be here; see below.)
To demonstrate using the value, I've provided some sample Javascript in an answer to my other question at Finding top-level X Window x/y coordinates of CTRL-F text in Firefox

Resources