Release script.skinvariables - Construct skin variables and perform other skin functions
#61
@Hitcher - Your JSON is invalid because of trailing commas. JSON splits at commas, so it always expects a new item to start after a comma. It trips me up all the time.

Basically it should be "a,b,c" not "a,b,c,"

e.g. the commas at the end of all your "library" lines should be removed because the next character is a closing curly brace. Same goes for the last line in your viewtype labels.

e.g. this is invalid
json:

"sources": {
"rule": "Container.Content(sources)",
"viewtypes": ["50"],
"library": "50",
},
"addons": {
"rule": "Container.Content(addons)",
"viewtypes": ["50"],
"library": "50",
}

To be valid JSON that would be:

json:

"sources": {
"rule": "Container.Content(sources)",
"viewtypes": ["50"],
"library": "50"
},
"addons": {
"rule": "Container.Content(addons)",
"viewtypes": ["50"],
"library": "50"
}



If you're using SublimeText3, I'd recommend installing SublimeLinter with the SublimeLinter-json package using the strict value set to True and it will highlight these trailing comma errors for you.
https://packagecontrol.io/packages/SublimeLinter-json
Arctic Fuse - Alpha now available. Support me on Ko-fi.
Reply
#62
Thanks. Weird thing is I checked it was valid using an online checker and it said it was fine. Huh
Reply
#63
EDIT: Figured it out.

Almost there but 2 view types are visible at all for some reason.

json:
{
"prefix": "Exp_View",
"viewtypes": {
"50": "31161",
"51": "31130",
"52": "31111",
"53": "31160",
"54": "31112",
"55": "31159",
"56": "31172"
},
"rules": {
"images": {
"rule": "Container.Content(images)",
"viewtypes": ["50", "53", "55"],
"library": "50"
},
"videos": {
"rule": "Container.Content(videos)",
"viewtypes": ["50", "51", "52", "53", "55", "56"],
"library": "50"
},
"movies": {
"rule": "Container.Content(movies)",
"viewtypes": ["53"],
"library": "53"
},
"sets": {
"rule": "Container.Content(sets)",
"viewtypes": ["53"],
"library": "53"
},
"tvshows": {
"rule": "Container.Content(tvshows)",
"viewtypes": ["51", "53"],
"library": "53"
},
"seasons": {
"rule": "Container.Content(seasons)",
"viewtypes": ["51", "53"],
"library": "53"
},
"episodes": {
"rule": "Container.Content(episodes)",
"viewtypes": ["52", "55"],
"library": "52",
"plugins": "55"
},
"genres": {
"rule": "Container.Content(genres)",
"viewtypes": ["50"],
"library": "50"
},
"years": {
"rule": "Container.Content(years)",
"viewtypes": ["50"],
"library": "50"
},
"studios": {
"rule": "Container.Content(studios)",
"viewtypes": ["50"],
"library": "50"
},
"directors": {
"rule": "Container.Content(directors)",
"viewtypes": ["50"],
"library": "50"
},
"countries": {
"rule": "Container.Content(countries)",
"viewtypes": ["50"],
"library": "50"
},
"tags": {
"rule": "Container.Content(tags)",
"viewtypes": ["50"],
"library": "50"
},
"roles": {
"rule": "Container.Content(roles)",
"viewtypes": ["50"],
"library": "50"
},
"actors": {
"rule": "Container.Content(actors)",
"viewtypes": ["50"],
"library": "50"
},
"playlists": {
"rule": "Container.Content(playlists)",
"viewtypes": ["50"],
"library": "50"
},
"games": {
"rule": "Container.Content(games)",
"viewtypes": ["50", "53", "55"],
"library": "50"
},
"musicvideos": {
"rule": "Container.Content(musicvideos)",
"viewtypes": ["50", "53", "55"],
"library": "50"
},
"artists": {
"rule": "Container.Content(artists)",
"viewtypes": ["50"],
"library": "50"
},
"albums": {
"rule": "Container.Content(albums)",
"viewtypes": ["50"],
"library": "50"
},
"songs": {
"rule": "Container.Content(songs)",
"viewtypes": ["54", "50"],
"library": "54"
},
"files": {
"rule": "Container.Content(files)",
"viewtypes": ["50"],
"library": "50"
},
"sources": {
"rule": "Container.Content(sources)",
"viewtypes": ["50"],
"library": "50"
},
"addons": {
"rule": "Container.Content(addons)",
"viewtypes": ["50"],
"library": "50"
},
"none": {
"rule": "Container.Content()",
"viewtypes": ["50"],
"library": "50"
}

}
}

xml:
<?xml version="1.0" encoding="UTF-8"?>
<includes>

<expression name="Exp_View_50">[[Container.Content(images) + [[String.IsEmpty(Container.PluginName)] | [!String.IsEmpty(Container.PluginName)]]] | [Container.Content(videos) + [[String.IsEmpty(Container.PluginName)] | [!String.IsEmpty(Container.PluginName)]]] | [Container.Content(genres) + [[String.IsEmpty(Container.PluginName)] | [!String.IsEmpty(Container.PluginName)]]] | [Container.Content(years) + [[String.IsEmpty(Container.PluginName)] | [!String.IsEmpty(Container.PluginName)]]] | [Container.Content(studios) + [[String.IsEmpty(Container.PluginName)] | [!String.IsEmpty(Container.PluginName)]]] | [Container.Content(directors) + [[String.IsEmpty(Container.PluginName)] | [!String.IsEmpty(Container.PluginName)]]] | [Container.Content(countries) + [[String.IsEmpty(Container.PluginName)] | [!String.IsEmpty(Container.PluginName)]]] | [Container.Content(tags) + [[String.IsEmpty(Container.PluginName)] | [!String.IsEmpty(Container.PluginName)]]] | [Container.Content(roles) + [[String.IsEmpty(Container.PluginName)] | [!String.IsEmpty(Container.PluginName)]]] | [Container.Content(actors) + [[String.IsEmpty(Container.PluginName)] | [!String.IsEmpty(Container.PluginName)]]] | [Container.Content(playlists) + [[String.IsEmpty(Container.PluginName)] | [!String.IsEmpty(Container.PluginName)]]] | [Container.Content(games) + [[String.IsEmpty(Container.PluginName)] | [!String.IsEmpty(Container.PluginName)]]] | [Container.Content(musicvideos) + [[String.IsEmpty(Container.PluginName)] | [!String.IsEmpty(Container.PluginName)]]] | [Container.Content(artists) + [[String.IsEmpty(Container.PluginName)] | [!String.IsEmpty(Container.PluginName)]]] | [Container.Content(albums) + [[String.IsEmpty(Container.PluginName)] | [!String.IsEmpty(Container.PluginName)]]] | [Container.Content(files) + [[String.IsEmpty(Container.PluginName)] | [!String.IsEmpty(Container.PluginName)]]] | [Container.Content(sources) + [[String.IsEmpty(Container.PluginName)] | [!String.IsEmpty(Container.PluginName)]]] | [Container.Content(addons) + [[String.IsEmpty(Container.PluginName)] | [!String.IsEmpty(Container.PluginName)]]] | [Container.Content() + [[String.IsEmpty(Container.PluginName)] | [!String.IsEmpty(Container.PluginName)]]]]</expression>
<expression name="Exp_View_50_Include">True</expression>
<expression name="Exp_View_51">[False]</expression>
<expression name="Exp_View_51_Include">False</expression>
<expression name="Exp_View_52">[[Container.Content(episodes) + [[String.IsEmpty(Container.PluginName)] | [!String.IsEmpty(Container.PluginName)]]]]</expression>
<expression name="Exp_View_52_Include">True</expression>
<expression name="Exp_View_53">[[Container.Content(movies) + [[String.IsEmpty(Container.PluginName)] | [!String.IsEmpty(Container.PluginName)]]] | [Container.Content(sets) + [[String.IsEmpty(Container.PluginName)] | [!String.IsEmpty(Container.PluginName)]]] | [Container.Content(tvshows) + [[String.IsEmpty(Container.PluginName)] | [!String.IsEmpty(Container.PluginName)]]] | [Container.Content(seasons) + [[String.IsEmpty(Container.PluginName)] | [!String.IsEmpty(Container.PluginName)]]]]</expression>
<expression name="Exp_View_53_Include">True</expression>
<expression name="Exp_View_54">[[Container.Content(songs) + [[String.IsEmpty(Container.PluginName)] | [!String.IsEmpty(Container.PluginName)]]]]</expression>
<expression name="Exp_View_54_Include">True</expression>
<expression name="Exp_View_55">[False]</expression>
<expression name="Exp_View_55_Include">False</expression>
<expression name="Exp_View_56">[False]</expression>
<expression name="Exp_View_56_Include">False</expression>
</includes>

55 and 56 are empty. Confused
Reply
#64
(2023-11-14, 16:20)Hitcher Wrote: EDIT: Figured it out.

Almost there but 2 view types are visible at all for some reason.

xml:
<?xml version="1.0" encoding="UTF-8"?>
<includes>

<expression name="Exp_View_50">[[Container.Content(images) + [[String.IsEmpty(Container.PluginName)] | [!String.IsEmpty(Container.PluginName)]]] | [Container.Content(videos) + [[String.IsEmpty(Container.PluginName)] | [!String.IsEmpty(Container.PluginName)]]] | [Container.Content(genres) + [[String.IsEmpty(Container.PluginName)] | [!String.IsEmpty(Container.PluginName)]]] | [Container.Content(years) + [[String.IsEmpty(Container.PluginName)] | [!String.IsEmpty(Container.PluginName)]]] | [Container.Content(studios) + [[String.IsEmpty(Container.PluginName)] | [!String.IsEmpty(Container.PluginName)]]] | [Container.Content(directors) + [[String.IsEmpty(Container.PluginName)] | [!String.IsEmpty(Container.PluginName)]]] | [Container.Content(countries) + [[String.IsEmpty(Container.PluginName)] | [!String.IsEmpty(Container.PluginName)]]] | [Container.Content(tags) + [[String.IsEmpty(Container.PluginName)] | [!String.IsEmpty(Container.PluginName)]]] | [Container.Content(roles) + [[String.IsEmpty(Container.PluginName)] | [!String.IsEmpty(Container.PluginName)]]] | [Container.Content(actors) + [[String.IsEmpty(Container.PluginName)] | [!String.IsEmpty(Container.PluginName)]]] | [Container.Content(playlists) + [[String.IsEmpty(Container.PluginName)] | [!String.IsEmpty(Container.PluginName)]]] | [Container.Content(games) + [[String.IsEmpty(Container.PluginName)] | [!String.IsEmpty(Container.PluginName)]]] | [Container.Content(musicvideos) + [[String.IsEmpty(Container.PluginName)] | [!String.IsEmpty(Container.PluginName)]]] | [Container.Content(artists) + [[String.IsEmpty(Container.PluginName)] | [!String.IsEmpty(Container.PluginName)]]] | [Container.Content(albums) + [[String.IsEmpty(Container.PluginName)] | [!String.IsEmpty(Container.PluginName)]]] | [Container.Content(files) + [[String.IsEmpty(Container.PluginName)] | [!String.IsEmpty(Container.PluginName)]]] | [Container.Content(sources) + [[String.IsEmpty(Container.PluginName)] | [!String.IsEmpty(Container.PluginName)]]] | [Container.Content(addons) + [[String.IsEmpty(Container.PluginName)] | [!String.IsEmpty(Container.PluginName)]]] | [Container.Content() + [[String.IsEmpty(Container.PluginName)] | [!String.IsEmpty(Container.PluginName)]]]]</expression>
<expression name="Exp_View_50_Include">True</expression>
<expression name="Exp_View_51">[False]</expression>
<expression name="Exp_View_51_Include">False</expression>
<expression name="Exp_View_52">[[Container.Content(episodes) + [[String.IsEmpty(Container.PluginName)] | [!String.IsEmpty(Container.PluginName)]]]]</expression>
<expression name="Exp_View_52_Include">True</expression>
<expression name="Exp_View_53">[[Container.Content(movies) + [[String.IsEmpty(Container.PluginName)] | [!String.IsEmpty(Container.PluginName)]]] | [Container.Content(sets) + [[String.IsEmpty(Container.PluginName)] | [!String.IsEmpty(Container.PluginName)]]] | [Container.Content(tvshows) + [[String.IsEmpty(Container.PluginName)] | [!String.IsEmpty(Container.PluginName)]]] | [Container.Content(seasons) + [[String.IsEmpty(Container.PluginName)] | [!String.IsEmpty(Container.PluginName)]]]]</expression>
<expression name="Exp_View_53_Include">True</expression>
<expression name="Exp_View_54">[[Container.Content(songs) + [[String.IsEmpty(Container.PluginName)] | [!String.IsEmpty(Container.PluginName)]]]]</expression>
<expression name="Exp_View_54_Include">True</expression>
<expression name="Exp_View_55">[False]</expression>
<expression name="Exp_View_55_Include">False</expression>
<expression name="Exp_View_56">[False]</expression>
<expression name="Exp_View_56_Include">False</expression>
</includes>

55 and 56 are empty. Confused

That's correct and working as intended.

In your default configuration, neither view 55 or 56 are being used so their visibility is set to false (additionally 51 is not currently being used). When you run the script to change views and select one of those views for one of the rules, the visibility conditions will update so that they become visible in those contexts (and the previously used views will be set to false for those rules).

Additionally the Exp_View_55_Include and Exp_View_56_Include expressions are also set to false so that you can prevent those viewtypes code from being included until they are actually required by the user.

The whole purpose of the visibility conditions is that they force only one specific viewtype to be visible per rule (and per plugin/library) so that Kodi cannot arbitrarily change the viewtype. If the only visible viewtype is the one the user has chosen then it is impossible for Kodi to select a different one.
Arctic Fuse - Alpha now available. Support me on Ko-fi.
Reply
#65
Thanks for the explanation, it's helped me understand things a lot better now. And I also know what the _Include parts are for, don't know how I didn't realise they're used as conditions for the view includes.
Reply
#66
Got it all working now and I wish I'd looked into it earlier as it's really helpful. Just want to say thanks for all your addons and the help you give us.
Reply
#67
Since my skin now has script.skinvariables as a required addon, I would need that at least version 1.1.46 would be available through the Kodi official repo before submitting an Omega version of my skin to the official repo, however I see that only 0.2.5 version is currently available. Do you know when an updated version of this wonderful script will be available? Many thanks for your great work!
If I have helped you or increased your knowledge, please click the 'thumbs up' button to give thanks :)
Reply
#68
(2023-12-10, 13:32)manfeed Wrote: Since my skin now has script.skinvariables as a required addon, I would need that at least version 1.1.46 would be available through the Kodi official repo before submitting an Omega version of my skin to the official repo, however I see that only 0.2.5 version is currently available. Do you know when an updated version of this wonderful script will be available? Many thanks for your great work!

I'll try to submit a PR for it soon.

As to how long it will take for review once submitted, I can't say. It really depends on when someone in the team has the time to review it.
Arctic Fuse - Alpha now available. Support me on Ko-fi.
Reply
#69
(2023-12-11, 02:03)jurialmunkey Wrote: I'll try to submit a PR for it soon.

As to how long it will take for review once submitted, I can't say. It really depends on when someone in the team has the time to review it.

Not trying to push you in any way, but I would be very grateful if you could do that, please. Thanks!
If I have helped you or increased your knowledge, please click the 'thumbs up' button to give thanks :)
Reply
#70
@jurialmunkey a little help please as I'm trying to add viewtypes for plugins but under certain conditions the dialog won't open.

json:
{
"prefix": "Exp_View",
"viewtypes": {
"50": "31161",
"51": "31130",
"52": "31111",
"53": "31160",
"54": "31112",
"55": "31159",
"56": "31172"
},
"rules": {
"images": {
"rule": "Container.Content(images)",
"viewtypes": ["50", "53", "55"],
"library": "50"
},
"videos": {
"rule": "Container.Content(videos)",
"viewtypes": ["50", "51", "52", "53", "55", "56"],
"library": "50"
},
"movies": {
"rule": "Container.Content(movies)",
"viewtypes": ["50", "51", "52", "53", "55", "56"],
"library": "53"
},
"sets": {
"rule": "Container.Content(sets)",
"viewtypes": ["53"],
"library": "53"
},
"videoversions": {
"rule": "Container.Content(videoversions)",
"viewtypes": ["50"],
"library": "50"
},
"tvshows": {
"rule": "Container.Content(tvshows)",
"viewtypes": ["51", "53"],
"library": "53"
},
"seasons": {
"rule": "Container.Content(seasons)",
"viewtypes": ["51", "53"],
"library": "53"
},
"episodes_library": {
"rule": "Container.Content(episodes)",
"viewtypes": ["50", "51", "52", "53", "55", "56"],
"library": "52"
},
"genres": {
"rule": "Container.Content(genres)",
"viewtypes": ["50"],
"library": "50"
},
"years": {
"rule": "Container.Content(years)",
"viewtypes": ["50"],
"library": "50"
},
"studios": {
"rule": "Container.Content(studios)",
"viewtypes": ["50"],
"library": "50"
},
"directors": {
"rule": "Container.Content(directors)",
"viewtypes": ["50"],
"library": "50"
},
"countries": {
"rule": "Container.Content(countries)",
"viewtypes": ["50"],
"library": "50"
},
"tags": {
"rule": "Container.Content(tags)",
"viewtypes": ["50"],
"library": "50"
},
"roles": {
"rule": "Container.Content(roles)",
"viewtypes": ["50"],
"library": "50"
},
"actors": {
"rule": "Container.Content(actors)",
"viewtypes": ["50"],
"library": "50"
},
"playlists": {
"rule": "Container.Content(playlists)",
"viewtypes": ["50"],
"library": "50"
},
"games": {
"rule": "Container.Content(games)",
"viewtypes": ["50", "53", "55"],
"library": "50"
},
"musicvideos": {
"rule": "Container.Content(musicvideos)",
"viewtypes": ["50", "53", "55"],
"library": "50"
},
"artists": {
"rule": "Container.Content(artists)",
"viewtypes": ["50"],
"library": "50"
},
"albums": {
"rule": "Container.Content(albums)",
"viewtypes": ["50"],
"library": "50"
},
"songs": {
"rule": "Container.Content(songs)",
"viewtypes": ["54", "50"],
"library": "54"
},
"files": {
"rule": "Container.Content(files)",
"viewtypes": ["50"],
"library": "50"
},
"sources": {
"rule": "Container.Content(sources)",
"viewtypes": ["50"],
"library": "50"
},
"addons": {
"rule": "Container.Content(addons)",
"viewtypes": ["50"],
"library": "50"
},
"none": {
"rule": "Container.Content()",
"viewtypes": ["50", "51", "52", "53", "55", "56"],
"library": "50"
}

}
}

xml:
<onclick>Runscript(script.skinvariables,action=buildviews,contentid=$INFO[Container.Content],pluginname=$INFO[Container.PluginName])</onclick>

Problem 1:

Image

Container.Content is episodes and Container.PluginName is plugin.video.iplayerwww

Clicking on the viewtype button doesn't open the dialog.

Problem 2:

Image

Container.Content is empty and Container.PluginName is plugin.video.amazon-test

Clicking on the viewtype button also doesn't open the dialog.

I'm sure there's something I'm missing but I can't work it out.

Thanks in advance.
Reply
#71
I also had a similar issue with empty content so I used a variable instead also I think episodes in the json files is under episodes_library so it doesn't match.

You might have to do the same for both.

xml:
contentid=$VAR[SkinVariablesContentVar]

xml:
<variable name="SkinVariablesContentVar">
<value condition="Container.Content(episodes)">episodes_library</value>
<value condition="!String.IsEmpty(Container.Content)">$INFO[Container.Content]</value>
<value condition="Container.Content() + Window.IsVisible(MyVideoNav.xml)">none-videos</value>
</variable>

Something like that?

EDIT: none-videos is what I used so you'd likely have to change that to none and remove the MyVideoNav condition.
Reply
#72
@Hitcher - What Mike said above re the variable is correct. You don't have any rule names which match the contentid that you're passing.

You can also use a variable like this to do more complex rules. For example, if you wanted a different rule for same content type in different windows such as music-none and video-none. Then your rule and variable is set to check the window too and pass the correct content id for the corresponding rule.
Arctic Fuse - Alpha now available. Support me on Ko-fi.
Reply
#73
Thanks to both of you for helping me sort it out.

In case anyone needs to know how I fixed it:

<onclick>Runscript(script.skinvariables,action=buildviews,contentid=$VAR[ContentID],pluginname=$INFO[Container.PluginName])</onclick>

xml:
<variable name="ContentID">
<value condition="!String.IsEmpty(Container.Content)">$INFO[Container.Content]</value>
<value condition="String.IsEmpty(Container.Content)">none</value>
</variable>

And I didn't even realise I had episodes listed as episodes_library. Rolleyes
Reply
#74
Hello @jurialmunkey!

So skin variables could be used to replace skinshortcuts? Will you be providing wiki documentation on these features? Very excited for the possibility. Thanks.

Regards,

Bart
Amber Maintainer
Main HTPC: Intel Core i7, 32GB, nVidia GTX1080, Windows 11 Soundbar: Samsung HW-Q950A TV: LG CX Kodi: 19.3 Skin: Amber
Reply
#75
@jurialmunkey any chance of getting this updated on the official repo please? I'd like to submit my skin but it's dependant on a newer version.

Thanks.
Reply

Logout Mark Read Team Forum Stats Members Help
script.skinvariables - Construct skin variables and perform other skin functions0