本文主要是介绍scratch3.0 scratch-gui中集成自定义用户系统1(第四章),希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!
scratch3.0系列章节列表
scratch3.0二次开发scratch3.0基本介绍(第一章)
scratch3.0二次开发运行scratch-gui项目并了解工程结构(第二章)
scratch3.0二次自定义品牌logo(第三章)
scratch3.0 scratch-gui中集成自定义用户系统1(第四章)
scratch3.0 scratch-gui中集成自定义用户系统2(第五章)
scratch3.0 scratch-gui中集成自定义用户系统3(第六章)
scratch3.0 scratch-gui中集成自定义用户系统4(第七章)
scratch3.0 scratch-gui中集成自定义用户系统5(第八章)
scratch3.0 scratch-gui中集成自定义用户系统6(第九章)
scratch3.0 scratch-gui中集成作品系统1(第九章)
scratch3.0 scratch-gui中集成作品系统2(第十章)
scratch3.0 scratch-gui中集成作品系统3(第十一章)
scratch3.0 scratch-gui加载自定义初始化角色(第十二章)
scratch3.0 scratch-gui打开自己平台云端作品(第十三章)
写在前面
该系列文章是为具有开发能力的朋友写作的,目的是帮助他们在刮擦3.0的基础上开发一套完整的集刮擦3.0编程工具,用户社区和作品云端存储及分享,品牌集成于一体的刮擦编程平台。如果您不是开发者,但想要拥有自己的教育平台和品牌,也欢迎学习交流和洽谈合作。
所以如果您是想学习scratch少儿编程课程,那请忽略该系列的文章。
前言
前面我们将scratch-gui工程成功建造运行起来,并且成功植入了我们的品牌徽标,这让我们对整个项目有了初步的认识。
现在我们已经有了scratch编程工具,但是我们还剩下两个主要的后台,用户社区后台和GUI的存储后台。目前Scratch3.0团队还没有发现社区替换和GUI的存储部分是否有开源计划,考虑到Scratch2.0的重新初始化开源,3.0社区初始化开源的可能也不大。
scratch-www项目提供了用户社区的功能,但是需要通过接口去分析它的后台的数据存储的结构,我觉得比较麻烦,不如我们自己来开发一个,集成到我们的编程工具scratch-gui中。
所以接下来我们的工作是自己来提供相关的两个前提平台,并与GUI集成到一起。
约会用户登录状态
我们先一步一步来,先做一个比较简单的用户系统,再一步一步迭代。
这一章,我们先来改造一下前面的scratch-gui,约会用户登录状态的检测。
在进入项目时,检测用户是否登录,如果用户未登录,则在右上角显示登录按钮,否则显示用户头像和姓名等基本信息。
先在reduser目录中创建user-state.js文件,用作记录用户的信息。
添加如下内容:
import keyMirror from 'keymirror';const UserState = keyMirror({NOT_LOGINED: null,LOGINED: null});const UserStates = Object.keys(UserState)const initialState = {error: null,userData: null,loginState: UserState.NOT_LOGINED};const getIsLogined = loginState => (loginState === UserState.LOGINED);const reducer = function (state, action) {if (typeof state === 'undefined') state = initialState;}export {reducer as default,initialState as userStateInitialState,UserState,UserStates,getIsLogined};
在reducers/gui.js中,作为项目的用户相关的初始化信息。
在reducer/gui.js中日期用户状态:
import userStateReducer, {userStateInitialState} from './user-state';```加入到initialState中:```const guiInitialState = {alerts: alertsInitialState,assetDrag: assetDragInitialState,blockDrag: blockDragInitialState,cards: cardsInitialState,colorPicker: colorPickerInitialState,connectionModal: connectionModalInitialState,customProcedures: customProceduresInitialState,editorTab: editorTabInitialState,mode: modeInitialState,hoveredTarget: hoveredTargetInitialState,stageSize: stageSizeInitialState,menus: menuInitialState,micIndicator: micIndicatorInitialState,modals: modalsInitialState,monitors: monitorsInitialState,monitorLayout: monitorLayoutInitialState,projectChanged: projectChangedInitialState,projectState: projectStateInitialState,projectTitle: projectTitleInitialState,fontsLoaded: fontsLoadedInitialState,restoreDeletion: restoreDeletionInitialState,targets: targetsInitialState,timeout: timeoutInitialState,toolbox: toolboxInitialState,vm: vmInitialState,vmStatus: vmStatusInitialState,userState: userStateInitialState};```将reducer加入到guiReducer中:```const guiReducer = combineReducers({alerts: alertsReducer,assetDrag: assetDragReducer,blockDrag: blockDragReducer,cards: cardsReducer,colorPicker: colorPickerReducer,connectionModal: connectionModalReducer,customProcedures: customProceduresReducer,editorTab: editorTabReducer,mode: modeReducer,hoveredTarget: hoveredTargetReducer,stageSize: stageSizeReducer,menus: menuReducer,micIndicator: micIndicatorReducer,modals: modalReducer,monitors: monitorReducer,monitorLayout: monitorLayoutReducer,projectChanged: projectChangedReducer,projectState: projectStateReducer,projectTitle: projectTitleReducer,fontsLoaded: fontsLoadedReducer,restoreDeletion: restoreDeletionReducer,targets: targetReducer,timeout: timeoutReducer,toolbox: toolboxReducer,vm: vmReducer,vmStatus: vmStatusReducer,userState: userStateReducer});
下面去container / gui.jsx中为里面定义的GUI Component添加loginState这个道具,使用标识用户是否登录:
GUI.propTypes = {assetHost: PropTypes.string,children: PropTypes.node,cloudHost: PropTypes.string,error: PropTypes.oneOfType([PropTypes.object, PropTypes.string]),fetchingProject: PropTypes.bool,intl: intlShape,isError: PropTypes.bool,isLoading: PropTypes.bool,isScratchDesktop: PropTypes.bool,isShowingProject: PropTypes.bool,loadingStateVisible: PropTypes.bool,onProjectLoaded: PropTypes.func,onSeeCommunity: PropTypes.func,onStorageInit: PropTypes.func,onUpdateProjectId: PropTypes.func,onUpdateProjectTitle: PropTypes.func,onUpdateReduxProjectTitle: PropTypes.func,onVmInit: PropTypes.func,projectHost: PropTypes.string,projectId: PropTypes.oneOfType([PropTypes.string, PropTypes.number]),projectTitle: PropTypes.string,telemetryModalVisible: PropTypes.bool,vm: PropTypes.instanceOf(VM).isRequired,loginState: PropTypes.bool};
这个`loginState`道具的状态值来自于user-state.js中getIsLogined中检测当前的loginState(指状态中的)是否等于UserState.LOGINED:
const mapStateToProps = state => {const loadingState = state.scratchGui.projectState.loadingState;const loginState = state.scratchGui.userState.loginState;return {activeTabIndex: state.scratchGui.editorTab.activeTabIndex,alertsVisible: state.scratchGui.alerts.visible,backdropLibraryVisible: state.scratchGui.modals.backdropLibrary,blocksTabVisible: state.scratchGui.editorTab.activeTabIndex === BLOCKS_TAB_INDEX,cardsVisible: state.scratchGui.cards.visible,connectionModalVisible: state.scratchGui.modals.connectionModal,costumeLibraryVisible: state.scratchGui.modals.costumeLibrary,costumesTabVisible: state.scratchGui.editorTab.activeTabIndex === COSTUMES_TAB_INDEX,error: state.scratchGui.projectState.error,isError: getIsError(loadingState),isFullScreen: state.scratchGui.mode.isFullScreen,isPlayerOnly: state.scratchGui.mode.isPlayerOnly,isRtl: state.locales.isRtl,isShowingProject: getIsShowingProject(loadingState),loadingStateVisible: state.scratchGui.modals.loadingProject,projectId: state.scratchGui.projectState.projectId,soundsTabVisible: state.scratchGui.editorTab.activeTabIndex === SOUNDS_TAB_INDEX,targetIsStage: (state.scratchGui.targets.stage &&state.scratchGui.targets.stage.id === state.scratchGui.targets.editingTarget),telemetryModalVisible: state.scratchGui.modals.telemetryModal,tipsLibraryVisible: state.scratchGui.modals.tipsLibrary,vm: state.scratchGui.vm,loginState: getIsLogined(loginState)};};
现在container / gui.jsx中定义的Component GUI具有登录状态属性了,我们要把它传到menu-bar中,因为我们要在menu-bar中去控制右上角的显示状态。
在这个GUI组件中使用了components / gui / gui.jsx定义的GUIComponent这个组件,GUIComponent定义了整个项目的基本样式结构中,可以找到对MenuBar的使用。
首先,在GUIComponent的定义中日期之前定义的`loginState`:
const GUIComponent = props => {const {accountNavOpen,activeTabIndex,alertsVisible,authorId,authorThumbnailUrl,authorUsername,basePath,backdropLibraryVisible,backpackHost,backpackVisible,blocksTabVisible,cardsVisible,canCreateNew,canEditTitle,canRemix,canSave,canCreateCopy,canShare,canUseCloud,children,connectionModalVisible,costumeLibraryVisible,costumesTabVisible,enableCommunity,intl,isCreating,isFullScreen,isPlayerOnly,isRtl,isShared,loading,renderLogin,onClickAccountNav,onCloseAccountNav,onLogOut,onOpenRegistration,onToggleLoginOpen,onUpdateProjectTitle,onActivateCostumesTab,onActivateSoundsTab,onActivateTab,onClickLogo,onExtensionButtonClick,onProjectTelemetryEvent,onRequestCloseBackdropLibrary,onRequestCloseCostumeLibrary,onRequestCloseTelemetryModal,onSeeCommunity,onShare,onTelemetryModalCancel,onTelemetryModalOptIn,onTelemetryModalOptOut,showComingSoon,soundsTabVisible,stageSizeMode,targetIsStage,telemetryModalVisible,tipsLibraryVisible,vm,loginState,...componentProps} = omit(props, 'dispatch');...
再在使用MenuBar的地方也为MenuBar定义`loginState`属性,它的值就是GUIComponent传进来的`loginState`的值:
<MenuBaraccountNavOpen={accountNavOpen}authorId={authorId}authorThumbnailUrl={authorThumbnailUrl}authorUsername={authorUsername}canCreateCopy={canCreateCopy}canCreateNew={canCreateNew}canEditTitle={canEditTitle}canRemix={canRemix}canSave={canSave}canShare={canShare}className={styles.menuBarPosition}enableCommunity={enableCommunity}isShared={isShared}renderLogin={renderLogin}showComingSoon={showComingSoon}onClickAccountNav={onClickAccountNav}onClickLogo={onClickLogo}onCloseAccountNav={onCloseAccountNav}onLogOut={onLogOut}onOpenRegistration={onOpenRegistration}onProjectTelemetryEvent={onProjectTelemetryEvent}onSeeCommunity={onSeeCommunity}onShare={onShare}onToggleLoginOpen={onToggleLoginOpen}onUpdateProjectTitle={onUpdateProjectTitle}loginState={loginState}/>
最后修改components / menu-bar.jsx中的MenuBar组件的显示,将右上角替换成:
<React.Fragment>{this.props.loginState ? (<React.Fragment><MenuBarItemTooltip id="mystuff"><divclassName={classNames(styles.menuBarItem,styles.hoverable,styles.mystuffButton)}><imgclassName={styles.mystuffIcon}src={mystuffIcon}/></div></MenuBarItemTooltip><MenuBarItemTooltipid="account-nav"place={this.props.isRtl ? 'right' : 'left'}><divclassName={classNames(styles.menuBarItem,styles.hoverable,styles.accountNavMenu)}><imgclassName={styles.profileIcon}src={profileIcon}/><span>{'scratch-cat'}</span><imgclassName={styles.dropdownCaretIcon}src={dropdownCaret}/></div></MenuBarItemTooltip></React.Fragment>) : <button >Login</button>}</React.Fragment>
如果用户已登录,就显示头像和姓名的样式(具体的用户信息需要跟后台打通,我们后面再实现):

否则显示登录按钮:

我们可以通过修改reducers / user-state.js中的loginState的初始值来查看效果:
loginState: UserState.NOT_LOGINED
loginState: UserState.LOGINED
这个值我们会在后面根据用户登录的token去获取。
为了与项目整体风格一致,我们修改这个登录按钮的样式,在菜单栏目录中添加login-button.css和login-button.jsx文件,内容分别如下:
@import "../../css/colors.css";.login-button {background: $data-primary;}
import classNames from 'classnames';import {FormattedMessage} from 'react-intl';import PropTypes from 'prop-types';import React from 'react';import Button from '../button/button.jsx';import styles from './login-button.css';const LoginButton = ({className,onClick}) => (<ButtonclassName={classNames(className,styles.loginButton)}onClick={onClick}><FormattedMessagedefaultMessage="Login"description="Label for login"id="gui.menuBar.login"/></Button>);LoginButton.propTypes = {className: PropTypes.string,onClick: PropTypes.func};LoginButton.defaultProps = {onClick: () => {}};export default LoginButton;
然后在menu-bar.jsx中如下使用:
<LoginButton className={styles.menuBarButton} />
这样看起来就好看多了:

好了,这里接收完成后,我们接下来就可以实现一个后台系统,然后对接后台系统登录和获取用户信息了。
上一章节链接:https://blog.csdn.net/tank_ft/article/details/104039006
下一章节链接:https://blog.csdn.net/tank_ft/article/details/104197077
这篇关于scratch3.0 scratch-gui中集成自定义用户系统1(第四章)的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!