@@ -1722,6 +1722,7 @@ export class ProjectView
17221722 await this . loadTutorialCustomTsAsync ( ) ;
17231723 await this . loadTutorialTemplateCodeAsync ( ) ;
17241724 await this . loadTutorialBlockConfigsAsync ( ) ;
1725+ await this . loadTutorialHiddenCategoriesAsync ( ) ;
17251726
17261727 const main = pkg . getEditorPkg ( pkg . mainPkg ) ;
17271728
@@ -2017,8 +2018,11 @@ export class ProjectView
20172018 if ( ! header || ! header . tutorial ) {
20182019 return ;
20192020 }
2020- else if ( ! header . tutorial . templateCode || header . tutorial . templateLoaded ) {
2021- if ( header . tutorial . mergeCarryoverCode && header . tutorial . mergeHeaderId ) {
2021+ const hasCodeCarryover = header . tutorial . mergeCarryoverCode && header . tutorial . mergeHeaderId ;
2022+ const hideReplaceMyCode = header . tutorial . metadata ?. hideReplaceMyCode || pxt . appTarget . appTheme . hideReplaceMyCode ;
2023+
2024+ if ( ! header . tutorial . templateCode && ! ( hasCodeCarryover && hideReplaceMyCode ) || header . tutorial . templateLoaded ) {
2025+ if ( hasCodeCarryover ) {
20222026 pxt . warn ( lf ( "Refusing to carry code between tutorials because the loaded tutorial \"{0}\" does not contain a template code block." , header . tutorial . tutorial ) ) ;
20232027 }
20242028 return ;
@@ -2029,33 +2033,36 @@ export class ProjectView
20292033 // Mark that the template has been loaded so that we don't overwrite the
20302034 // user code if the tutorial is re-opened
20312035 header . tutorial . templateLoaded = true ;
2036+
20322037 let currentText = await workspace . getTextAsync ( header . id ) ;
20332038
2034- // If we're starting in the asset editor, always load into TS
2035- const preferredEditor = header . tutorial . metadata ?. preferredEditor ;
2036- if ( preferredEditor && filenameForEditor ( preferredEditor ) === pxt . ASSETS_FILE ) {
2037- currentText [ pxt . MAIN_TS ] = template ;
2038- }
2039+ if ( template ) {
2040+ // If we're starting in the asset editor, always load into TS
2041+ const preferredEditor = header . tutorial . metadata ?. preferredEditor ;
2042+ if ( preferredEditor && filenameForEditor ( preferredEditor ) === pxt . ASSETS_FILE ) {
2043+ currentText [ pxt . MAIN_TS ] = template ;
2044+ }
20392045
2040- const projectname = projectNameForEditor ( preferredEditor || header . editor ) ;
2046+ const projectname = projectNameForEditor ( preferredEditor || header . editor ) ;
20412047
2042- if ( projectname === pxt . PYTHON_PROJECT_NAME && header . tutorial . templateLanguage === "python" ) {
2043- currentText [ pxt . MAIN_PY ] = template ;
2044- }
2045- else if ( projectname === pxt . JAVASCRIPT_PROJECT_NAME ) {
2046- currentText [ pxt . MAIN_TS ] = template ;
2047- }
2048- else if ( projectname === pxt . PYTHON_PROJECT_NAME ) {
2049- const pyCode = await compiler . decompilePythonSnippetAsync ( template )
2050- if ( pyCode ) {
2051- currentText [ pxt . MAIN_PY ] = pyCode ;
2048+ if ( projectname === pxt . PYTHON_PROJECT_NAME && header . tutorial . templateLanguage === "python" ) {
2049+ currentText [ pxt . MAIN_PY ] = template ;
20522050 }
2053- }
2054- else {
2055- const resp = await compiler . decompileBlocksSnippetAsync ( template )
2056- const blockXML = resp . outfiles [ pxt . MAIN_BLOCKS ] ;
2057- if ( blockXML ) {
2058- currentText [ pxt . MAIN_BLOCKS ] = blockXML
2051+ else if ( projectname === pxt . JAVASCRIPT_PROJECT_NAME ) {
2052+ currentText [ pxt . MAIN_TS ] = template ;
2053+ }
2054+ else if ( projectname === pxt . PYTHON_PROJECT_NAME ) {
2055+ const pyCode = await compiler . decompilePythonSnippetAsync ( template )
2056+ if ( pyCode ) {
2057+ currentText [ pxt . MAIN_PY ] = pyCode ;
2058+ }
2059+ }
2060+ else {
2061+ const resp = await compiler . decompileBlocksSnippetAsync ( template )
2062+ const blockXML = resp . outfiles [ pxt . MAIN_BLOCKS ] ;
2063+ if ( blockXML ) {
2064+ currentText [ pxt . MAIN_BLOCKS ] = blockXML
2065+ }
20592066 }
20602067 }
20612068
@@ -2157,6 +2164,27 @@ export class ProjectView
21572164 return Promise . resolve ( ) ;
21582165 }
21592166
2167+ private async loadTutorialHiddenCategoriesAsync ( ) : Promise < void > {
2168+ const mainPkg = pkg . mainEditorPkg ( ) ;
2169+ const header = mainPkg . header ;
2170+ if ( ! header || ! header . tutorial || ! header . tutorial . hiddenNamespaces ) {
2171+ return ;
2172+ }
2173+
2174+ await mainPkg . updateConfigAsync ( config => {
2175+ if ( ! config . toolboxFilter ) {
2176+ config . toolboxFilter = {
2177+ namespaces : { } ,
2178+ blocks : { }
2179+ } ;
2180+ }
2181+
2182+ for ( const category of header . tutorial . hiddenNamespaces ) {
2183+ config . toolboxFilter . namespaces [ category ] = "hidden" ;
2184+ }
2185+ } ) ;
2186+ }
2187+
21602188 async resetTutorialTemplateCode ( keepAssets : boolean ) : Promise < void > {
21612189 const mainPkg = pkg . mainEditorPkg ( ) ;
21622190 const header = mainPkg . header ;
0 commit comments