Proposal to add Scoped Constants

Hello everyone
App Inventor currently offers no semantically efficient method of setting choice properties from within blocks. For example, a user has to use math blocks (1, 2, and 3) to set the alignment of an arrangement’s content. While being semantically unrelated to the actual property value, these numbers also have inconsistencies within components, thus making them unintuitive to use (see below)

image
[ Center is 3 here :arrow_up: ]

image
[ Center is 2 in this case :arrow_up: ]

Secondly, some components require specific inputs from the user to function correctly (the height/widths of arrangements have to be set to -1 or -2 for them to use automatic or fill parent scaling). Users, especially those new to App Inventor, are unlikely to know these specific constants and thus may find it hard to use blocks to the fullest.

@ewpatton has already suggested adding enums to App Inventor (see https://docs.google.com/document/d/1AqT8xQiJfFRI5hIcbaetkCnky-7nvPv77gHYaQdifHE/edit#), and I’d like to build on that design with this proposal. If there is a general consensus regarding the need of such a system of constants, I’d be more than willing to open a GitHub issue so that we can gather feedback and work on it.


Proposal

I propose the introduction of constant blocks to App Inventor, where every constant will semantically represent the value it holds and will have a scope that it’s limited to. I suggest the classification of said blocks into three scopes – the global scope, the component scope, and the property scope.

Global Scope Constants

Constants in the global scope will ideally be free from component restraints and represent values constant throughout a project. A common use case would be as a screen selector with a drop-down of all current screens.

image

This will eliminate the need to enter the screen’s name as a text block when using the open another screen block.

Component Scope Constants

These constants will be bound by the component they are scoped in. Component Scope Constants can be used, for instance, in the AskForPermission block:

image

Users must not be compelled to remember Android jargon to make their apps. The android.permission.WRITE_EXTERNAL_STORAGE text block can be replaced with

image

so that users no longer have to type the permission names manually.

Another use for such constants would be in the Yandex Translate component.

image

The de text block can be replaced by the Component Scope constant shown below:

image

Note that the component’s name is being used here instead of the instance name (Screen instead of Screen1, and Yandex Translate instead of Yandex_Translate1) to further show that these constants are common across all instances of that component.

Property Scope Constants

These constants represent values that a particular property of a component can hold. Taking the example alignments in vertical arrangements, it is easy to illustrate an ideal use case for such a constant.

image

image

image

image


How will they work?

Constants will return a string or integer depending on the type of property they represent. For example, the image block will return the string “de”, and the image block will return an integer 3.

Thus, existing methods and properties will not have to be updated to accommodate these new blocks.


Why Constants?

Having constants over text inputs has several benefits:

  • A semantic relationship between the constant block and its connecting socket can be established. imageimage is more meaningful than
    imageimage.

  • Typographical errors that may occur while manually entering text can be avoided. This is especially true in cases of long constant values like android.permission.WRITE_EXTERNAL_STORAGE.

  • Constant blocks can be internationalised.

  • Constant blocks allow users to see all their choices in a drop-down as opposed to text inputs, where users are forced to use external resources to view their choices (again taking the example of permissions, a drop-down containing all permissions is more helpful than having to look up “list of Android permissions” in a search engine).


Why Scopes?

  • Scoping of constants helps prevent conflicts in their values. As mentioned in the introduction, some properties use 3 to represent Center, while others use 2.
    Having a single constant block called Center will require changes to existing code to ensure all method and property blocks handle this new constant the same way.

  • Building on the point above, extension developers may not always stick to standards set by MIT.
    For example, someone developing a translator extension may write a method that takes “GER” as the language parameter for German. Having a non-scoped constant like image that returns “de” will not work with the extension.
    Scoping allows for two blocks: image which is guaranteed only to work with the Yandex component, and a separate image block that returns “GER” and works with the extension.


Backwards Compatibility

Existing blocks will not require updates as the proposed constant blocks are merely optional replacements to non-semantic text/integer inputs. That means users might as well choose to use
image image
instead of
image image

In essence, the proposed constants are just syntax sugar and do not change the way App Inventor works.


Please let me know what you think of the proposed additions, and if you have any suggestions regarding their implementation. Thanks!

Vishwas

25 Likes

In addition to having the constant blocks like this (extending from my enum proposal), I think we would also want to include a constant block that represents the assets in a project, which is another area where making a spelling error can be frustrating.

I’m not necessarily convinced of the utility of keeping the component and property types in scope though. For example, what does it mean to connect a HorizontalArrangement.AlignHorizontal.Center to a set VerticalArrangement.AlignVertical block? Would you simply not allow this? If so, it’s a bit different than just substituting for the numeric blocks. By not tying the enum to a type, we allowed that you could connect a Center to any property for which Center was a valid value. This is particularly useful in cases where you might want to horizontally align a whole lot of content using a for item in list construct over a list containing a mix of arrangements.

I can certainly see the value of this for extensions where the extensions may need to supply blocks with different semantics from the built-in enums. I also really like the idea of hiding the permissions values behind constants.

8 Likes

I think this is indeed a very practical proposal, It will simplify the use of App Inventor and remove a lot of typo issues.

Concerning Screen Names, this is currently a problematic case for a different reason - there are times when the Screen needs to be re-named but currently this cannot be done within App Inventor. This requirement occurs frequently, often a small group of students working together on a Project, without planning ahead.

6 Likes

Yes, this is true. There are a couple things we could do to mitigate this though. The first and obvious one is to add the ability to rename screens. This would at least address the issue of a single user needing to rename a screen in a manner preferable to hacking the AIA file. The second is to have each screen have a UUID and have this block report the UUID rather than the name of the screen. This way even if the name of the file is changed the UUID will match and we can render the new screen name. There is a UUID property already for screens, but it is always 0 at the moment. This would actually make it useful for something.

5 Likes

(post withdrawn by author, will be automatically deleted in 24 hours unless flagged)

You should ask this in a separate thread. You are hijacking the topic.

4 Likes

I m sorry…

Perhaps we can have "Media" as a pseudo-component and list all assets in its scope, something like this:
image

The blocks would be able to connect, but they will not be guaranteed to work together. I assume users will be able to deduct from the semantic naming that the blocks might not work when connected together.

We could have a single constant that works with all components, but I have a few concerns with such a system:

  1. We will have to rewrite several properties to standardise numbering (1= left, 2 = centre, 3 = right, ...)
    That'll break existing projects unless we can find some way to "upgrade" the properties (I'm not sure how to do this as the method signature effectively remains unchanged).

  2. I was originally thinking of automatically generating constant blocks for all choice properties (from editorArgs in extensions (Configure ChoicePropertyEditor choices through annotations by jerry73204 · Pull Request #993 · mit-cml/appinventor-sources · GitHub), and YoungAndroid<...>ChoicePropertyEditors in native components). It makes things easier for the developer, but as a consequence we get blocks for all property values in their respective namespaces.

  3. There's a chance a component might have two properties that take "Center" as a property value, but with different semantic meanings for both. For instance, a text sprite in a 3D canvas can have a TextAlign property which takes "Left", "Right", "Center", and "Justify" as values, and also a 3D rotation reference point property that takes "Top Left Corner", "Center", and "Top Right Corner" as values. Having a single 3DText . Center constant block might not work for us.

Some solutions:

While I'm not sure how to tackle issue #1, we can get around issues #2 and #3 by using annotations.

The @SimpleProperty annotation can have a generatePropertyBlocks = true variable which the user can set to false if they wish not to generate constant blocks.

This will let us disable automatic block generation for alignment properties.
Instead of constants namespaced in properties, we can have yet another pseudo-component called "Alignments" where we can list all possible alignments that can be passed to the property.

image

Users will thus be able to distinguish between a Center that represents alignment, and a Center that stands for something else.

What are your inputs regarding this?

8 Likes

To offer my input, I think it'd be nice to be called "Assets" rather, because some can get easily confused as to if it's a component for the device, or a component for the distribution itself to help make life easier.

I love the proposal however :heart:!

3 Likes

As far as I know, there is no front-end reference to “Assets” in AI, and all assets are known simply as “Media”. (Just like how users know Forms as Screens)

image

I do agree with you, though; “Assets” is less confusing than “Media”.

2 Likes

I don’t wanna go off-topic, but maybe for other builders it could be called Media, but on Kodular it would have to be Assets because there’s already a category named Media.

All I’m saying in prospect, is that the builder should just name is based on what they have their upload areas called, Assets or Media.

1 Like

One concern I have regarding higher scoped constant blocks is their Blockly workspace placement.

Property and component constant blocks can be placed in the blocks flyout for that component, but the same cannot be done for blocks in the global and pseudo-component scope.

Any input regarding this would be greatly appreciated :slightly_smiling_face:

1 Like

For enumerations, I proposed introducing a separate category of blocks where all of the enumeration blocks could be placed regardless of which components they could be used with. We could include the media/screen enums there as well. A test server with an early prototype is here, but in that version I only implemented AlignHorizontal/AlignVertical. More work would need to be done to cover the whole of the App Inventor code base.

10 Likes