= ContainerDefaultProps) {
20 | const {
21 | id,
22 | connectors: {
23 | drag,
24 | connect
25 | }
26 | } = useNode()
27 | return (
28 | connect(drag(ref))}
30 | style={{
31 | display: "flex",
32 | flexDirection: props.direction,
33 | height: props.height,
34 | width: props.width,
35 | backgroundColor: props.backgroundColor,
36 | padding: props.padding
37 | }}
38 | >
39 | {props.children || "I'm empty"}
40 |
41 | )
42 | }
43 |
44 | const ContainerSettings = () => {
45 | const {
46 | props,
47 | actions: { setProp },
48 | } = useNode((node) => ({
49 | props: node.data.props
50 | }))
51 |
52 | return (
53 |
54 | {
59 | setProp((props: typeof ContainerDefaultProps) => (props.backgroundColor = color), 500)
60 | }}
61 | />
62 |
67 | setProp((props: typeof ContainerDefaultProps) => (props.padding = value), 500)
68 | }
69 | />
70 |
75 | setProp((props: typeof ContainerDefaultProps) => (props.height = e.currentTarget.value), 500)
76 | }
77 | />
78 |
83 | setProp((props: typeof ContainerDefaultProps) => (props.width = e.currentTarget.value), 500)
84 | }
85 | />
86 |
113 | )
114 | }
115 |
116 | ContainerComponent.craft = {
117 | props: ContainerDefaultProps,
118 | related: {
119 | settings: ContainerSettings,
120 | },
121 | }
122 |
--------------------------------------------------------------------------------
/frontend/src/mocks/InputComponent.tsx:
--------------------------------------------------------------------------------
1 | import { Input } from "@mantine/core"
2 | import { useNode } from "@craftjs/core"
3 | import React from "react"
4 |
5 | export const InputComponent = ({ text }: { text: string }) => {
6 | const {
7 | connectors: {
8 | connect,
9 | drag
10 | }
11 | } = useNode()
12 |
13 | return (
14 | connect(drag(ref))}>
15 |
16 |
17 | )
18 | }
19 |
--------------------------------------------------------------------------------
/frontend/src/mocks/TextComponent.tsx:
--------------------------------------------------------------------------------
1 | import { ColorInput, NumberInput, Stack, Text, TextInput } from "@mantine/core"
2 | import { useNode } from "@craftjs/core"
3 | import React from "react"
4 | import { Property } from "csstype"
5 |
6 | const TextDefaultProps: Partial<{
7 | color: Property.Color;
8 | backgroundColor: Property.BackgroundColor;
9 | padding: Property.Padding;
10 | height: Property.Height;
11 | width: Property.Width;
12 | text: string;
13 | fontSize: number;
14 | }> = {
15 | padding: 4,
16 | text: "Hello K2",
17 | }
18 |
19 | export function TextComponent (props: React.PropsWithChildren = TextDefaultProps) {
20 | const {
21 | connectors: {
22 | connect,
23 | drag
24 | }
25 | } = useNode()
26 |
27 | return (
28 | connect(drag(ref))}>
29 |
36 | {props.text}
37 |
38 |
39 | )
40 | }
41 |
42 | const TextSettings = () => {
43 | const {
44 | props,
45 | actions: { setProp },
46 | } = useNode((node) => ({
47 | props: node.data.props
48 | }))
49 |
50 | return (
51 |
52 | {
57 | setProp((props: typeof TextDefaultProps) => (props.color = color), 500)
58 | }}
59 | />
60 | {
65 | setProp((props: typeof TextDefaultProps) => (props.backgroundColor = color), 500)
66 | }}
67 | />
68 |
73 | setProp((props: typeof TextDefaultProps) => (props.padding = value), 500)
74 | }
75 | />
76 |
81 | setProp((props: typeof TextDefaultProps) => (props.height = e.currentTarget.value), 500)
82 | }
83 | />
84 |
89 | setProp((props: typeof TextDefaultProps) => (props.width = e.currentTarget.value), 500)
90 | }
91 | />
92 |
97 | setProp((props: typeof TextDefaultProps) => (props.text = e.currentTarget.value), 500)
98 | }
99 | />
100 |
105 | setProp((props: typeof TextDefaultProps) => (props.fontSize = value), 500)
106 | }
107 | />
108 |
109 | )
110 | }
111 |
112 | TextComponent.craft = {
113 | props: TextDefaultProps,
114 | related: {
115 | settings: TextSettings,
116 | },
117 | }
118 |
--------------------------------------------------------------------------------
/frontend/src/mocks/index.tsx:
--------------------------------------------------------------------------------
1 | import { TextComponent } from "@/mocks/TextComponent"
2 | import { ButtonComponent } from "@/mocks/ButtonComponent"
3 | import { InputComponent } from "@/mocks/InputComponent"
4 | import { ContainerComponent } from "@/mocks/ContainerComponent"
5 | import { Element } from "@craftjs/core"
6 | import React from "react"
7 |
8 | export const mocks: Record = {
9 | Text: {
10 | componentElement: TextComponent,
11 | defaultInstance:
12 | },
13 | Button: {
14 | componentElement: ButtonComponent,
15 | defaultInstance:
16 | },
17 | Input: {
18 | componentElement: InputComponent,
19 | defaultInstance:
20 | },
21 | Container: {
22 | componentElement: ContainerComponent,
23 | defaultInstance:
24 | },
25 | }
26 |
27 | export const componentCategories = {
28 | "Basic": ["Text", "Button", "Input"],
29 | "Layout": ["Container"]
30 | }
31 |
--------------------------------------------------------------------------------
/frontend/src/pages/Home.jsx:
--------------------------------------------------------------------------------
1 | import { Button } from "@mantine/core";
2 | import { Link } from "react-router-dom";
3 |
4 | export default function Home() {
5 | return (
6 | <>
7 | Welcome to App Inventor Modern!
8 |
9 | >
10 | )
11 | }
--------------------------------------------------------------------------------
/frontend/src/pages/Login.jsx:
--------------------------------------------------------------------------------
1 | import { useLocation, useNavigate } from "react-router-dom";
2 | import { useAuth } from "@/hooks/auth";
3 |
4 | export default function Login() {
5 | let navigate = useNavigate();
6 | let location = useLocation();
7 | let auth = useAuth();
8 |
9 | let from = location.state?.from?.pathname || "/";
10 |
11 | function handleSubmit(event) {
12 | event.preventDefault();
13 |
14 | let formData = new FormData(event.currentTarget);
15 | let username = formData.get("username")
16 |
17 | auth.signin(username, () => {
18 | navigate(from, { replace: true });
19 | });
20 | }
21 |
22 | return (
23 |
24 |
You must log in to view the page at {from}
25 |
26 |
32 |
33 | );
34 | }
--------------------------------------------------------------------------------
/frontend/src/pages/Main.jsx:
--------------------------------------------------------------------------------
1 | import { AppShell, Button, Group, SegmentedControl, SimpleGrid, Stack, Table } from "@mantine/core"
2 | import { projects } from "@/api/projects"
3 | import ProjectCard from "@/components/ProjectCard"
4 | import Header from "@/components/Header"
5 | import { useState } from "react"
6 |
7 | export default function Main() {
8 | const [viewType, setViewType] = useState("grid")
9 |
10 | return (
11 | ({
15 | main: { backgroundColor: theme.colorScheme === "dark" ? theme.colors.dark[8] : theme.colors.gray[0] },
16 | })}
17 | >
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
28 |
31 |
32 |
37 |
38 |
39 |
40 |
41 |
42 |
43 | )
44 | }
45 |
46 | function ProjectsView({ viewType }) {
47 |
48 | if (viewType === "table") {
49 | return (
50 |
51 |
52 |
53 | Name |
54 | Description |
55 | Action |
56 |
57 |
58 |
59 | {
60 | projects.map((project, i) => (
61 |
62 | {project.name} |
63 | {project.description} |
64 | |
65 |
66 | ))
67 | }
68 |
69 |
70 | )
71 | }
72 |
73 | return (
74 |
75 | {
76 | projects.map((project, i) => (
77 |
78 | ))
79 | }
80 |
81 | )
82 | }
83 |
84 |
--------------------------------------------------------------------------------
/frontend/src/pages/Project.jsx:
--------------------------------------------------------------------------------
1 | import { AppShell, Tabs } from "@mantine/core"
2 | import { projects } from "@/api/projects"
3 | import Header from "@/components/Header"
4 | import { useParams } from "react-router-dom"
5 | import { useMemo, useState } from "react"
6 | import { MdDesignServices } from "react-icons/md"
7 | import { HiOutlinePuzzle } from "react-icons/hi"
8 | import BlocksEditor from "@/components/BlocksEditor"
9 | import Designer from "@/components/Designer"
10 | import { initialWorkspaceJson } from "@/blocks/toolbox"
11 |
12 | export default function () {
13 | const params = useParams()
14 | const projectId = params.id
15 | const project = useMemo(() => projects.find(project => project.id === projectId), [projectId])
16 |
17 | const [designerState, setDesignerState] = useState(null)
18 | const [blocksState, setBlocksState] = useState(initialWorkspaceJson)
19 |
20 | return (
21 | ({
25 | main: { backgroundColor: theme.colorScheme === "dark" ? theme.colors.dark[8] : theme.colors.gray[0] },
26 | })}
27 | >
28 |
29 |
30 |
31 |
32 | {/* keepMounted is false because otherwise Blockly wouldn't fit perfectly as the container has display:none */}
33 |
34 |
35 | }>Designer
36 | }>BlocksEditor
37 |
38 |
39 |
40 |
41 |
42 |
43 |
44 |
45 |
46 |
47 |
48 |
49 |
50 | )
51 | }
52 |
--------------------------------------------------------------------------------
/frontend/src/state/store.js:
--------------------------------------------------------------------------------
1 | import { useCallback } from 'react'
2 | import create from 'zustand'
3 | import { log, immer, pipe } from './utils'
4 |
5 | const createStore = pipe(immer, log, create)
6 |
7 | export const useStore = createStore(
8 | (set, get) => ({
9 | layout: {
10 | rootId: 'Screen1',
11 | selected: [],
12 | components: {
13 | 'Screen1': {
14 | id: 'Screen1',
15 | type: 'Screen',
16 | children: []
17 | }
18 | }
19 | },
20 | addComponent(item, parentId, order = Infinity) {
21 | set(state => {
22 | const generatedId = genComponentId(item.type)
23 | state.layout.components[generatedId] = { ...item, id: generatedId, children: [] }
24 | state.layout.components[parentId].children.splice(order, 0, generatedId)
25 | })
26 | },
27 | removeComponent(id) {
28 | set(state => {
29 | state.layout.components = state.layout.components.filter(item => item.id !== id)
30 | // TODO: maybe store parentId inside nodes
31 | state.layout.components.forEach(c => {
32 | c.children = c.children.filter(child => child !== id)
33 | })
34 | })
35 | },
36 | moveComponent(id, parentId, newParentId, newIndex) {
37 | /* Algorithm:
38 | 1. Find the component to move
39 | 2. Remove it from the existing parent
40 | 3. Add it to the new parent
41 | */
42 | set(state => {
43 | const component = state.layout.components.find(c => c.id === id)
44 | const parent = state.layout.components.find(c => c.id === parentId)
45 | const newParent = state.layout.components.find(c => c.id === newParentId)
46 | const index = parent.children.indexOf(id)
47 | parent.children.splice(index, 1)
48 | newParent.children.splice(newIndex, 0, id)
49 | })
50 | },
51 | selectComponent(id, multiple = false) {
52 | set(state => {
53 | if (multiple) {
54 | state.layout.selected.push(id)
55 | } else {
56 | state.layout.selected = [id]
57 | }
58 | })
59 | }
60 | })
61 | )
62 |
63 | export function useSelector(selector, deps) {
64 | return useStore(useCallback(selector, deps))
65 | }
66 |
67 | const idMap = {}
68 |
69 | function genComponentId(type) {
70 | if (!idMap[type]) {
71 | idMap[type] = 0
72 | }
73 | idMap[type]++
74 | return `${type}${idMap[type]}`
75 | }
--------------------------------------------------------------------------------
/frontend/src/state/utils.js:
--------------------------------------------------------------------------------
1 | import { produce } from 'immer'
2 |
3 | export function log(config) {
4 | return (set, get, api) => config(args => {
5 | console.groupCollapsed()
6 | console.log("🔴 applying", args)
7 | set(args)
8 | console.log("🔴 new state", get())
9 | console.groupEnd()
10 | }, get, api)
11 | }
12 |
13 | export function immer(config) {
14 | return (set, get, api) => config((partial, replace) => {
15 | const nextState = typeof partial === 'function'
16 | ? produce(partial)
17 | : partial
18 | return set(nextState, replace)
19 | }, get, api)
20 | }
21 |
22 | export function pipe(...fns) {
23 | return (x) => fns.reduce((v, f) => f(v), x)
24 | }
25 |
--------------------------------------------------------------------------------
/frontend/src/vite-env.d.ts:
--------------------------------------------------------------------------------
1 | ///
2 |
--------------------------------------------------------------------------------
/frontend/tsconfig.json:
--------------------------------------------------------------------------------
1 | {
2 | "compilerOptions": {
3 | "target": "ESNext",
4 | "useDefineForClassFields": true,
5 | "lib": ["DOM", "DOM.Iterable", "ESNext"],
6 | "allowJs": true,
7 | "skipLibCheck": true,
8 | "esModuleInterop": false,
9 | "allowSyntheticDefaultImports": true,
10 | "strict": true,
11 | "forceConsistentCasingInFileNames": true,
12 | "module": "ESNext",
13 | "moduleResolution": "Node",
14 | "resolveJsonModule": true,
15 | "isolatedModules": true,
16 | "noEmit": true,
17 | "jsx": "react-jsx",
18 | "paths": {
19 | "@/*": ["./src/*"]
20 | }
21 | },
22 | "include": ["src"],
23 | "references": [{ "path": "./tsconfig.node.json" }]
24 | }
25 |
--------------------------------------------------------------------------------
/frontend/tsconfig.node.json:
--------------------------------------------------------------------------------
1 | {
2 | "compilerOptions": {
3 | "composite": true,
4 | "module": "ESNext",
5 | "moduleResolution": "Node",
6 | "allowSyntheticDefaultImports": true
7 | },
8 | "include": ["vite.config.ts"]
9 | }
10 |
--------------------------------------------------------------------------------
/frontend/vite.config.ts:
--------------------------------------------------------------------------------
1 | import { defineConfig } from 'vite'
2 | import react from '@vitejs/plugin-react'
3 | import { fileURLToPath, URL } from "url";
4 |
5 | // https://vitejs.dev/config/
6 | export default defineConfig({
7 | plugins: [react()],
8 | resolve: {
9 | alias: {
10 | "@": fileURLToPath(new URL("./src", import.meta.url)),
11 | },
12 | },
13 | })
14 |
--------------------------------------------------------------------------------
/gradle/wrapper/gradle-wrapper.properties:
--------------------------------------------------------------------------------
1 | distributionBase=GRADLE_USER_HOME
2 | distributionPath=wrapper/dists
3 | distributionUrl=https\://services.gradle.org/distributions/gradle-7.4-bin.zip
4 | zipStoreBase=GRADLE_USER_HOME
5 | zipStorePath=wrapper/dists
6 |
--------------------------------------------------------------------------------
/gradlew:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env sh
2 |
3 | #
4 | # Copyright 2015 the original author or authors.
5 | #
6 | # Licensed under the Apache License, Version 2.0 (the "License");
7 | # you may not use this file except in compliance with the License.
8 | # You may obtain a copy of the License at
9 | #
10 | # https://www.apache.org/licenses/LICENSE-2.0
11 | #
12 | # Unless required by applicable law or agreed to in writing, software
13 | # distributed under the License is distributed on an "AS IS" BASIS,
14 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15 | # See the License for the specific language governing permissions and
16 | # limitations under the License.
17 | #
18 |
19 | ##############################################################################
20 | ##
21 | ## Gradle start up script for UN*X
22 | ##
23 | ##############################################################################
24 |
25 | # Attempt to set APP_HOME
26 | # Resolve links: $0 may be a link
27 | PRG="$0"
28 | # Need this for relative symlinks.
29 | while [ -h "$PRG" ] ; do
30 | ls=`ls -ld "$PRG"`
31 | link=`expr "$ls" : '.*-> \(.*\)$'`
32 | if expr "$link" : '/.*' > /dev/null; then
33 | PRG="$link"
34 | else
35 | PRG=`dirname "$PRG"`"/$link"
36 | fi
37 | done
38 | SAVED="`pwd`"
39 | cd "`dirname \"$PRG\"`/" >/dev/null
40 | APP_HOME="`pwd -P`"
41 | cd "$SAVED" >/dev/null
42 |
43 | APP_NAME="Gradle"
44 | APP_BASE_NAME=`basename "$0"`
45 |
46 | # Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
47 | DEFAULT_JVM_OPTS='"-Xmx64m" "-Xms64m"'
48 |
49 | # Use the maximum available, or set MAX_FD != -1 to use that value.
50 | MAX_FD="maximum"
51 |
52 | warn () {
53 | echo "$*"
54 | }
55 |
56 | die () {
57 | echo
58 | echo "$*"
59 | echo
60 | exit 1
61 | }
62 |
63 | # OS specific support (must be 'true' or 'false').
64 | cygwin=false
65 | msys=false
66 | darwin=false
67 | nonstop=false
68 | case "`uname`" in
69 | CYGWIN* )
70 | cygwin=true
71 | ;;
72 | Darwin* )
73 | darwin=true
74 | ;;
75 | MINGW* )
76 | msys=true
77 | ;;
78 | NONSTOP* )
79 | nonstop=true
80 | ;;
81 | esac
82 |
83 | CLASSPATH=$APP_HOME/gradle/wrapper/gradle-wrapper.jar
84 |
85 |
86 | # Determine the Java command to use to start the JVM.
87 | if [ -n "$JAVA_HOME" ] ; then
88 | if [ -x "$JAVA_HOME/jre/sh/java" ] ; then
89 | # IBM's JDK on AIX uses strange locations for the executables
90 | JAVACMD="$JAVA_HOME/jre/sh/java"
91 | else
92 | JAVACMD="$JAVA_HOME/bin/java"
93 | fi
94 | if [ ! -x "$JAVACMD" ] ; then
95 | die "ERROR: JAVA_HOME is set to an invalid directory: $JAVA_HOME
96 |
97 | Please set the JAVA_HOME variable in your environment to match the
98 | location of your Java installation."
99 | fi
100 | else
101 | JAVACMD="java"
102 | which java >/dev/null 2>&1 || die "ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.
103 |
104 | Please set the JAVA_HOME variable in your environment to match the
105 | location of your Java installation."
106 | fi
107 |
108 | # Increase the maximum file descriptors if we can.
109 | if [ "$cygwin" = "false" -a "$darwin" = "false" -a "$nonstop" = "false" ] ; then
110 | MAX_FD_LIMIT=`ulimit -H -n`
111 | if [ $? -eq 0 ] ; then
112 | if [ "$MAX_FD" = "maximum" -o "$MAX_FD" = "max" ] ; then
113 | MAX_FD="$MAX_FD_LIMIT"
114 | fi
115 | ulimit -n $MAX_FD
116 | if [ $? -ne 0 ] ; then
117 | warn "Could not set maximum file descriptor limit: $MAX_FD"
118 | fi
119 | else
120 | warn "Could not query maximum file descriptor limit: $MAX_FD_LIMIT"
121 | fi
122 | fi
123 |
124 | # For Darwin, add options to specify how the application appears in the dock
125 | if $darwin; then
126 | GRADLE_OPTS="$GRADLE_OPTS \"-Xdock:name=$APP_NAME\" \"-Xdock:icon=$APP_HOME/media/gradle.icns\""
127 | fi
128 |
129 | # For Cygwin or MSYS, switch paths to Windows format before running java
130 | if [ "$cygwin" = "true" -o "$msys" = "true" ] ; then
131 | APP_HOME=`cygpath --path --mixed "$APP_HOME"`
132 | CLASSPATH=`cygpath --path --mixed "$CLASSPATH"`
133 |
134 | JAVACMD=`cygpath --unix "$JAVACMD"`
135 |
136 | # We build the pattern for arguments to be converted via cygpath
137 | ROOTDIRSRAW=`find -L / -maxdepth 1 -mindepth 1 -type d 2>/dev/null`
138 | SEP=""
139 | for dir in $ROOTDIRSRAW ; do
140 | ROOTDIRS="$ROOTDIRS$SEP$dir"
141 | SEP="|"
142 | done
143 | OURCYGPATTERN="(^($ROOTDIRS))"
144 | # Add a user-defined pattern to the cygpath arguments
145 | if [ "$GRADLE_CYGPATTERN" != "" ] ; then
146 | OURCYGPATTERN="$OURCYGPATTERN|($GRADLE_CYGPATTERN)"
147 | fi
148 | # Now convert the arguments - kludge to limit ourselves to /bin/sh
149 | i=0
150 | for arg in "$@" ; do
151 | CHECK=`echo "$arg"|egrep -c "$OURCYGPATTERN" -`
152 | CHECK2=`echo "$arg"|egrep -c "^-"` ### Determine if an option
153 |
154 | if [ $CHECK -ne 0 ] && [ $CHECK2 -eq 0 ] ; then ### Added a condition
155 | eval `echo args$i`=`cygpath --path --ignore --mixed "$arg"`
156 | else
157 | eval `echo args$i`="\"$arg\""
158 | fi
159 | i=`expr $i + 1`
160 | done
161 | case $i in
162 | 0) set -- ;;
163 | 1) set -- "$args0" ;;
164 | 2) set -- "$args0" "$args1" ;;
165 | 3) set -- "$args0" "$args1" "$args2" ;;
166 | 4) set -- "$args0" "$args1" "$args2" "$args3" ;;
167 | 5) set -- "$args0" "$args1" "$args2" "$args3" "$args4" ;;
168 | 6) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" ;;
169 | 7) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" ;;
170 | 8) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" ;;
171 | 9) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" "$args8" ;;
172 | esac
173 | fi
174 |
175 | # Escape application args
176 | save () {
177 | for i do printf %s\\n "$i" | sed "s/'/'\\\\''/g;1s/^/'/;\$s/\$/' \\\\/" ; done
178 | echo " "
179 | }
180 | APP_ARGS=`save "$@"`
181 |
182 | # Collect all arguments for the java command, following the shell quoting and substitution rules
183 | eval set -- $DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS "\"-Dorg.gradle.appname=$APP_BASE_NAME\"" -classpath "\"$CLASSPATH\"" org.gradle.wrapper.GradleWrapperMain "$APP_ARGS"
184 |
185 | exec "$JAVACMD" "$@"
186 |
--------------------------------------------------------------------------------
/gradlew.bat:
--------------------------------------------------------------------------------
1 | @rem
2 | @rem Copyright 2015 the original author or authors.
3 | @rem
4 | @rem Licensed under the Apache License, Version 2.0 (the "License");
5 | @rem you may not use this file except in compliance with the License.
6 | @rem You may obtain a copy of the License at
7 | @rem
8 | @rem https://www.apache.org/licenses/LICENSE-2.0
9 | @rem
10 | @rem Unless required by applicable law or agreed to in writing, software
11 | @rem distributed under the License is distributed on an "AS IS" BASIS,
12 | @rem WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | @rem See the License for the specific language governing permissions and
14 | @rem limitations under the License.
15 | @rem
16 |
17 | @if "%DEBUG%" == "" @echo off
18 | @rem ##########################################################################
19 | @rem
20 | @rem Gradle startup script for Windows
21 | @rem
22 | @rem ##########################################################################
23 |
24 | @rem Set local scope for the variables with windows NT shell
25 | if "%OS%"=="Windows_NT" setlocal
26 |
27 | set DIRNAME=%~dp0
28 | if "%DIRNAME%" == "" set DIRNAME=.
29 | set APP_BASE_NAME=%~n0
30 | set APP_HOME=%DIRNAME%
31 |
32 | @rem Resolve any "." and ".." in APP_HOME to make it shorter.
33 | for %%i in ("%APP_HOME%") do set APP_HOME=%%~fi
34 |
35 | @rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
36 | set DEFAULT_JVM_OPTS="-Xmx64m" "-Xms64m"
37 |
38 | @rem Find java.exe
39 | if defined JAVA_HOME goto findJavaFromJavaHome
40 |
41 | set JAVA_EXE=java.exe
42 | %JAVA_EXE% -version >NUL 2>&1
43 | if "%ERRORLEVEL%" == "0" goto execute
44 |
45 | echo.
46 | echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.
47 | echo.
48 | echo Please set the JAVA_HOME variable in your environment to match the
49 | echo location of your Java installation.
50 |
51 | goto fail
52 |
53 | :findJavaFromJavaHome
54 | set JAVA_HOME=%JAVA_HOME:"=%
55 | set JAVA_EXE=%JAVA_HOME%/bin/java.exe
56 |
57 | if exist "%JAVA_EXE%" goto execute
58 |
59 | echo.
60 | echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME%
61 | echo.
62 | echo Please set the JAVA_HOME variable in your environment to match the
63 | echo location of your Java installation.
64 |
65 | goto fail
66 |
67 | :execute
68 | @rem Setup the command line
69 |
70 | set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar
71 |
72 |
73 | @rem Execute Gradle
74 | "%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %*
75 |
76 | :end
77 | @rem End local scope for the variables with windows NT shell
78 | if "%ERRORLEVEL%"=="0" goto mainEnd
79 |
80 | :fail
81 | rem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of
82 | rem the _cmd.exe /c_ return code!
83 | if not "" == "%GRADLE_EXIT_CONSOLE%" exit 1
84 | exit /b 1
85 |
86 | :mainEnd
87 | if "%OS%"=="Windows_NT" endlocal
88 |
89 | :omega
90 |
--------------------------------------------------------------------------------
/settings.gradle.kts:
--------------------------------------------------------------------------------
1 | /*
2 | * This file was generated by the Gradle 'init' task.
3 | *
4 | * The settings file is used to specify which projects to include in your build.
5 | *
6 | * Detailed information about configuring a multi-project build in Gradle can be found
7 | * in the user manual at https://docs.gradle.org/6.8/userguide/multi_project_builds.html
8 | */
9 |
10 | rootProject.name = "app-inventor-modern"
11 |
12 | include(":buildserver")
--------------------------------------------------------------------------------