diff --git a/src/components/PackExplorer/HomeView/CreateProjectBtn.vue b/src/components/PackExplorer/HomeView/CreateProjectBtn.vue index ba44528d3..25c3e17ec 100644 --- a/src/components/PackExplorer/HomeView/CreateProjectBtn.vue +++ b/src/components/PackExplorer/HomeView/CreateProjectBtn.vue @@ -19,13 +19,13 @@ > mdi-plus - {{ t('packExplorer.noProjectView.createLocalProject') }} + {{ t('windows.createProject.title') }} - {{ t('packExplorer.noProjectView.createLocalProject') }} + {{ t('windows.createProject.title') }} @@ -71,7 +71,8 @@ export default { }, calculateAvailableWidth() { if (this.$refs.button) - this.availableWidth = this.$refs.button.$el.getBoundingClientRect().width + this.availableWidth = + this.$refs.button.$el.getBoundingClientRect().width }, }, } diff --git a/src/components/Projects/CreateProject/CreateCategories.ts b/src/components/Projects/CreateProject/CreateCategories.ts new file mode 100644 index 000000000..1823c8fab --- /dev/null +++ b/src/components/Projects/CreateProject/CreateCategories.ts @@ -0,0 +1,39 @@ +import GeneralTab from './Tabs/GeneralTab.vue' +import FilesTab from './Tabs/CreateFile/Tab.vue' +import ExperimentalGameplayTab from './Tabs/ExperimentalGameplay/Tab.vue' +import ProjectTypeTab from './Tabs/ProjectType/Tab.vue' +import PackTypeTab from './Tabs/PackTypeTab.vue' + +interface ICreateCategory { + icon: string + id: string + component: any +} + +export const createCategories: ICreateCategory[] = [ + { + icon: 'mdi-circle-outline', + id: 'general', + component: GeneralTab, + }, + { + icon: 'mdi-package-variant-closed', + id: 'projectType', + component: ProjectTypeTab, + }, + { + icon: 'mdi-wrench', + id: 'packType', + component: PackTypeTab, + }, + { + icon: 'mdi-test-tube', + id: 'experimentalGameplay', + component: ExperimentalGameplayTab, + }, + { + icon: 'mdi-file-outline', + id: 'files', + component: FilesTab, + }, +] diff --git a/src/components/Projects/CreateProject/CreateProject.ts b/src/components/Projects/CreateProject/CreateProject.ts index c309a90f7..023f81acc 100644 --- a/src/components/Projects/CreateProject/CreateProject.ts +++ b/src/components/Projects/CreateProject/CreateProject.ts @@ -1,6 +1,5 @@ import { App } from '/@/App' import { FileSystem } from '/@/components/FileSystem/FileSystem' -import CreateProjectComponent from './CreateProject.vue' import { CreatePack } from './Packs/Pack' import { CreateBP } from './Packs/BP' import { CreateRP } from './Packs/RP' @@ -19,12 +18,17 @@ import { getFormatVersions, getStableFormatVersion, } from '/@/components/Data/FormatVersions' -import { Project } from '../Project/Project' import { CreateDenoConfig } from './Files/DenoConfig' -import { IWindowState, NewBaseWindow } from '../../Windows/NewBaseWindow' -import { reactive } from 'vue' +import { reactive, watch } from 'vue' +import { translate } from '../../Locales/Manager' +import { createCategories } from './CreateCategories' +import { + IStepperWindowState, + StepperWindow, +} from '../../Windows/StepperWindow/StepperWindow' export interface ICreateProjectOptions { + projectType: 'bridgeFolder' | 'local' | 'comMojang' author: string | string[] description: string icon: File | null @@ -50,13 +54,12 @@ export interface IExperimentalToggle { description: string } -export interface ICreateProjectState extends IWindowState { - isCreatingProject: boolean +export interface ICreateProjectState extends IStepperWindowState { createOptions: ICreateProjectOptions availableTargetVersionsLoading: boolean } -export class CreateProjectWindow extends NewBaseWindow { - protected isFirstProject = false + +export class CreateProjectWindow extends StepperWindow { protected availableTargetVersions: string[] = [] protected stableVersion: string = '' protected packs: Record = < @@ -90,9 +93,9 @@ export class CreateProjectWindow extends NewBaseWindow { protected state: ICreateProjectState = reactive({ ...super.getState(), - isCreatingProject: false, createOptions: this.getDefaultOptions(), availableTargetVersionsLoading: true, + windowTitle: 'windows.createProject.title', }) get createOptions() { @@ -117,7 +120,7 @@ export class CreateProjectWindow extends NewBaseWindow { } constructor() { - super(CreateProjectComponent, false) + super({ keepAlive: true }) this.defineWindow() App.ready.once(async (app) => { @@ -139,24 +142,78 @@ export class CreateProjectWindow extends NewBaseWindow { App.packType.ready.once(() => { this.availablePackTypes = App.packType.all }) + + this.setupWindow() } get hasRequiredData() { - return ( - this.createOptions.packs.length > 1 && - this.projectNameRules.every( - (rule) => rule(this.createOptions.name) === true - ) && - this.createOptions.namespace.length > 0 && - this.createOptions.author.length > 0 && - this.createOptions.targetVersion.length > 0 + return createCategories.every(({ id }) => this.tabHasRequiredData(id)) + } + + tabHasRequiredData(tabId: string) { + switch (tabId) { + case 'general': + return ( + this.projectNameRules.every( + (rule) => rule(this.createOptions.name) === true + ) && + this.createOptions.namespace.length > 0 && + this.createOptions.author.length > 0 && + this.createOptions.targetVersion.length > 0 + ) + case 'packType': + return this.createOptions.packs.length > 1 + + default: + return true + } + } + + /** + * Sets up the steps for the stepper window and the confirm button + */ + setupWindow() { + createCategories.forEach((category) => { + this.addStep({ + icon: category.icon, + id: category.id, + color: 'accent', + name: translate( + 'windows.createProject.categories.' + category.id + ), + component: category.component, + }) + }) + + this.updateConfirmState({ + name: translate('windows.createProject.create'), + color: 'primary', + icon: 'mdi-plus', + isDisabled: true, + isLoading: false, + onConfirm: async () => { + this.state.confirm.isLoading = true + // TODO remove test code + // await this.createProject() + await new Promise((resolve) => { + setTimeout(() => resolve(), 1000) + }) + this.state.confirm.isLoading = false + + this.close() + }, + }) + + watch( + () => this.hasRequiredData, + () => (this.state.confirm.isDisabled = !this.hasRequiredData) ) } - open(isFirstProject = false) { + open() { this.state.createOptions = this.getDefaultOptions() + this.sidebar.setDefaultSelected() - this.isFirstProject = isFirstProject this.packCreateFiles.forEach( (createFile) => (createFile.isActive = true) ) @@ -168,16 +225,12 @@ export class CreateProjectWindow extends NewBaseWindow { const app = await App.getApp() const removeOldProject = - isUsingFileSystemPolyfill.value && - !app.hasNoProjects && - !this.isFirstProject + isUsingFileSystemPolyfill.value && !app.hasNoProjects // Save previous project name to delete it later - let previousProject: Project | undefined - if (!this.isFirstProject) - previousProject = app.isNoProjectSelected - ? app.projects[0] - : app.project + let previousProject = app.isNoProjectSelected + ? app.projects[0] + : app.project // Ask user whether we should save the current project if (removeOldProject) { @@ -229,6 +282,7 @@ export class CreateProjectWindow extends NewBaseWindow { static getDefaultOptions(): ICreateProjectOptions { return { + projectType: 'local', author: settingsState?.projects?.defaultAuthor ?? '', @@ -271,6 +325,7 @@ export class CreateProjectWindow extends NewBaseWindow { config = await app.project.fileSystem.readJSON('config.json') return { + projectType: 'local', author: config.author ?? '', description: config.description ?? '', icon: null, diff --git a/src/components/Projects/CreateProject/CreateProject.vue b/src/components/Projects/CreateProject/CreateProject.vue deleted file mode 100644 index 6b925167d..000000000 --- a/src/components/Projects/CreateProject/CreateProject.vue +++ /dev/null @@ -1,340 +0,0 @@ - - - - - diff --git a/src/components/Projects/CreateProject/ProjectTypes.ts b/src/components/Projects/CreateProject/ProjectTypes.ts new file mode 100644 index 000000000..1b952772b --- /dev/null +++ b/src/components/Projects/CreateProject/ProjectTypes.ts @@ -0,0 +1,14 @@ +export const projectTypes = [ + { + type: 'local', + icon: 'mdi-lock-open-outline', + }, + { + type: 'bridgeFolder', + icon: 'mdi-folder-open-outline', + }, + { + type: 'comMojang', + icon: 'mdi-minecraft', + }, +] diff --git a/src/components/Projects/CreateProject/Tabs/CreateFile/Tab.vue b/src/components/Projects/CreateProject/Tabs/CreateFile/Tab.vue new file mode 100644 index 000000000..e98edae70 --- /dev/null +++ b/src/components/Projects/CreateProject/Tabs/CreateFile/Tab.vue @@ -0,0 +1,29 @@ + + + diff --git a/src/components/Projects/CreateProject/CreateFile.vue b/src/components/Projects/CreateProject/Tabs/CreateFile/Toggle.vue similarity index 95% rename from src/components/Projects/CreateProject/CreateFile.vue rename to src/components/Projects/CreateProject/Tabs/CreateFile/Toggle.vue index 427237458..cd8fc8037 100644 --- a/src/components/Projects/CreateProject/CreateFile.vue +++ b/src/components/Projects/CreateProject/Tabs/CreateFile/Toggle.vue @@ -2,7 +2,7 @@