Page 1 of 1

Standalone language and protection schema

Posted: Sat Mar 26, 2016 1:38 am
by trevix
I am developing a desktop and mobile application, with a choice of languages and some reasonable way to protect my stacks.
For languages, I don't trust anymore property profiles, so i devised a way to change languages.

My schema is as such:
- there is a splash stack where the user is asked, on first launch, to choose the language
- base on this, a tab file with all the long names of labels and field text that need to be changed gets loaded.
- it will also load a text file with all the correct text for dialog windows, putting them inside a global
- the splash standalone contains the real application stack: it modifies all language field and button
- then the Splash create a copy of App stack, with the correct language, inside specialfolderpath("resources"),launch it and close itself.

Everything works fine and it is quite speedy. (fields and buttons that need translation have a special name; the tab file has all the correct path to them, collected once, before making the standalone). My language translations are all in the same text files, very easy to manage.

Now, my problem is how to protect my App.
No problem for the Splash stack, since it becomes a standalone.
But as for the App stack, I am not sure on how to do avoid that some one can open it, once saved (once they find it).
I cannot keep it only on memory (putting it for example on a custom prop) because i would have to reset the languages on each relaunch (that instead now is instantaneous)
I use a way (password protecting scripts) but the splash stack needs to unlock them on launch or they will not work correctly. Beside there are many substacks so it is time consuming.

Any suggestions ?
Trevix

Re: Standalone language and protection schema

Posted: Sat Mar 26, 2016 7:22 pm
by jacque
I wouldn't do it that way, there are several places it could fail. On mobile, you can't write to the app folder and on desktop you will have the same problem depending on the user's permissions level. Also, some virus utilities could flag your app because its behavior is suspiciously like malware. You could get around this though by writing to the user's Documents folder instead. But it's still a lot of work for something that isn't really necessary. Also, there is no easy way to protect your stacks without applying password protection.

You can solve these issues by using custom properties (as the profiles do) and setting the language that way. If you don't like how the built-in profiles work, you can do it yourself, which is what I always do. On preOpenCard, just scan through the controls and set the labels to their matching language property. If you do it on preOpenCard instead of all at once on startup, it is very fast and you won't notice a delay. To make it even faster, check to see if the first control is already set to the right language and exit the handler if that's true.

Code: Select all

local sLanguage -- set this to the name of the custom language property you will be using

on preOpenCard
  repeat with x = 1 to the number of controls
    if the sLanguage of control x <> empty then
      if the label of control x = the sLanguage of control x then pass preOpenCard -- already set; exit
      set the label of control x to the sLanguage of control x
    end if
  end repeat
end preOpenCard

on setup -- do this when a language is chosen
  put "cEnglish" into sLanguage -- name of custom property
end setup
If you'd rather read in your text file, you can do that instead of using custom properties. Load the text file into the script local variable when the app opens, convert it to an array, and scan the card controls as above. Instead of setting the labels to their custom property, set it to the matching key in the array.

Re: Standalone language and protection schema

Posted: Tue Mar 29, 2016 10:37 am
by trevix
Hi.
As for the language, I already do it that way, modifying each needed label on preopenstack.
As for the App, now I save it in the specialfolder("resources"). The position should be fine both on mobile and desktop.
The reason for saving it to disk was that I thought that the language change routine could be time consuming, so something to be done only on first launch.

But you may be wright : if I keep the App stack only in memory (using custom prop) I solve the protection problem and, collecting only the needed controls names for language change, redoing it at each launch may be it is not so slow (I don't need a repeat routine for each control, but only for those from a saved list)
But I wonder:
- what happens on mobile when the App is paused?
- is this what most LC developers do?

Thanks

Re: Standalone language and protection schema

Posted: Tue Mar 29, 2016 6:36 pm
by jacque
I recently worked on an app that supported five different languages and had dozens of controls on each card. I used custom properties to store each translation and on preOpenCard I set the labels of each control as I mentioned above. It never took more than a tiny fraction of a second and was imperceptible. I suspect if I'd updated all the labels in the entire stack (about 20 cards) it still wouldn't have taken more than a second or so. The method is very fast. I chose preOpenCard rather than preOpenStack for efficiency; users may not ever visit some of the other cards so there was no point in altering them until they were needed.

I can't speak for all developers, but this method is very commonly used by many of us.

When a stack is paused on mobile, the OS takes control of it in order to manage memory. On Android at least, the OS will hold the app in memory until it needs the RAM, at which point it will delete it. The next time the user requests the app it will start up "new" again. Since you never know when your app might close, you need to assume it always will. Save the app state to disk in a shutdown handler and restore it on preOpenStack (in your case you'd probably store the language name and the current card so you can resume where the user left off.) Since the behavior is unpredictable, that's another reason to choose preOpenCard when updating labels -- you only need to update the current card at any given time. On iOS your app will (or used to) always quit when suspended. I'm not sure how it behaves now that Apple has introduced true suspension for in-use apps; I always save the state anyway.

Re: Standalone language and protection schema

Posted: Tue Mar 29, 2016 9:18 pm
by trevix
Since you never know when your app might close, you need to assume it always will.]
Assuming that I have to always save the state of the app (or card) then I need to save the stack to disk.
Do you mean to keep the app in memory, save it to disk on pause, delete from the disk on closing?

Re: Standalone language and protection schema

Posted: Wed Mar 30, 2016 11:22 pm
by jacque
Assuming that I have to always save the state of the app (or card) then I need to save the stack to disk.
Do you mean to keep the app in memory, save it to disk on pause, delete from the disk on closing?
No, just write the relevant information to a text file in the Documents folder. Then read that file on preOpenStack and use it to set the app up the way it was before. For example, you might write "Language: French" to the text file. On preOpenStack the app would read and parse the file and update the labels to French, or set a custom property to French for preOpenCard labelling. Some developers save the card number so the app can open to the same card where the users left off. Anything else that is unique to the user's experience goes into the file; game scores, a favorites list, the user name, user text entries, etc. Whatever you save, the data is used to repopulate the app's controls or variables as needed.

You can also use a regular stack to store the information if you want, which you can create on first launch. The idea is to save only those things that allow the app to reset itself to the same state it was in when the user left. Writing to a text file or a stack is very fast, and far less intensive than copying an entire app file to disk. Basically you're creating a preferences file.

Re: Standalone language and protection schema

Posted: Thu Mar 31, 2016 3:23 pm
by trevix
I have evaluated what you said, but it would be hard to apply to my case:
Let me paint my situation:
My App has a card where the user does intense drawing, dragging symbols that refers to template cards, connecting lines, etc.
Also there are several substacks, used as templates, and each has several cards (>20), all of which need language translation.
To rebuild all this from a text file would be quite complex.

Case A
The App stack is in memory of the Splash stack. At each restart, the language routine is run (now on iPad 2 takes up to 5 seconds !!)
Mobile :
the user receive a telephone call before exiting the drawing: Everything is lost unless:
1 - I modify the pList (http://livecodejournal.com/forum/viewto ... ?f=25&t=90) UIApplicationExitsOnSuspend.
In this case nothing is lost and he can go back to where was left, the correct language is still there
2 - The App saves everything on shutDown and, at the end of the phone call, will start from the splash, redoing all the language modifications (long)

Desktop:
Since I cannot save changes to custom prop of the standalone, I have to do the language routine at each restart on desktop (I could live with that, because of the speed).

Case B
The App stack is in memory of the Splash stack, but gets translated and copied to specialfolderpath("resources" or "temporary") where will run.
Mobile:
- When there is a need for a suspension (mobile) will restart from it (saved and translated)
- On second startup, the Stack App is already translated and waiting for a fast opening
- I don't know about security but on mobile is not so easy to get to documents unless you know that they are there (since there is not LC for mobile, you also have to crate a specific App to get to them)
Desktop:
I could run the App stack entirely in memory and do the translate routine at each restart (not that long).
How do you feel about the schema ?

About the translation routine:
There are more then 20 cards that need to be translated, so no preopencard unless I split my translation text file so that there is reference to the current card (too complex). Most of them belongs to templates that are copied by the user to create new documents.
The way i do it:
Before saving the standalone I have a script that collects the abbrev ID of controls whose name begin with a precise text, and what needs to be translated (label, text,etc), all trough my stacks and cards.
This tab list gets saved in a custom prop of the Splash and looks like this:
button id 26300 of card "iPad_Main" of stack "FRmain" tab FR__Cancel tab2 Cancel tab3 Annulla
So the list is precise and limited to the controls that need translation.
On launching the App, i just need to tell which tab (tab2= Cancel or tab3=Annulla) has to be replaced on the control.

Re: Standalone language and protection schema

Posted: Thu Mar 31, 2016 8:47 pm
by jacque
I see, that clarifies things quite a bit. Since you are already using the splash stack method you are correct that saving the entire user-edited stack is the right way to do it. I had thought you were trying to save an entire application, but in fact you will just be saving a document. That will work for both mobile and desktop and is similar to my suggestion to save a preferences file -- but in this case the whole stack is the preferences.

If you do this, then the 5-second translation will only happen on the first launch after installation. All launches after that will use the revised user stack and won't need translation. To speed up the translation time, make sure you have locked both the screen and messages, if you haven't already done that.

If you ever decide to do the translations in a preOpenCard handler instead of preOpenStack, it looks like you could filter your list for the ID or name of the current card to extract only those lines that apply:

Code: Select all

put the short name of this cd into tCd
filter tBigList with "*" & tCd & "*"