├── .gitattributes ├── .gitignore ├── .idea ├── app-inventor-modern.iml ├── codeStyles │ ├── Project.xml │ └── codeStyleConfig.xml ├── compiler.xml ├── gradle.xml ├── jarRepositories.xml ├── jsLibraryMappings.xml ├── misc.xml ├── modules.xml ├── vcs.xml └── workspace.xml ├── README.md ├── backend ├── .gitignore ├── index.js ├── package-lock.json ├── package.json └── prisma │ ├── prismaClient.js │ └── schema.prisma ├── build.gradle.kts ├── buildserver ├── build.gradle.kts └── src │ └── main │ └── kotlin │ ├── com │ └── google │ │ └── appinventor │ │ └── buildserver │ │ ├── AabCompiler.kt │ │ ├── AnimationXmlConstants.kt │ │ ├── BuildServer.kt │ │ ├── Compiler.kt │ │ ├── DexExecTask.kt │ │ ├── Execution.kt │ │ ├── FormPropertiesAnalyzer.kt │ │ ├── NonQueuingExecutor.kt │ │ ├── PathUtil.kt │ │ ├── Project.kt │ │ ├── ProjectBuilder.kt │ │ ├── Result.kt │ │ ├── Signatures.kt │ │ ├── YoungAndroidConstants.kt │ │ ├── resources │ │ ├── runtime.scm │ │ └── ya.png │ │ └── util │ │ ├── AARLibraries.kt │ │ ├── AARLibrary.kt │ │ ├── AabZipper.kt │ │ ├── BaseFileWrapper.kt │ │ ├── BaseLogger.kt │ │ └── NOPCompilationProgress.kt │ └── me │ └── pavi2410 │ └── buildserver │ ├── App.kt │ ├── Main.kt │ ├── Routing.kt │ └── constants.kt ├── frontend ├── .gitignore ├── bun.lockb ├── index.html ├── package.json ├── postcss.config.cjs ├── src │ ├── App.jsx │ ├── Blockly │ │ ├── BlocklyComponent.jsx │ │ └── index.jsx │ ├── api │ │ ├── auth.js │ │ └── projects.js │ ├── blocks │ │ ├── components.js │ │ ├── customBlocks.js │ │ ├── generator.js │ │ └── toolbox.js │ ├── components │ │ ├── BlocksEditor.jsx │ │ ├── Designer.tsx │ │ ├── Header.jsx │ │ └── ProjectCard.jsx │ ├── favicon.ico │ ├── hooks │ │ └── auth.jsx │ ├── index.css │ ├── logo.png │ ├── main.jsx │ ├── mocks │ │ ├── ButtonComponent.tsx │ │ ├── ContainerComponent.tsx │ │ ├── InputComponent.tsx │ │ ├── TextComponent.tsx │ │ └── index.tsx │ ├── pages │ │ ├── Home.jsx │ │ ├── Login.jsx │ │ ├── Main.jsx │ │ └── Project.jsx │ ├── state │ │ ├── store.js │ │ └── utils.js │ └── vite-env.d.ts ├── tsconfig.json ├── tsconfig.node.json └── vite.config.ts ├── gradle └── wrapper │ └── gradle-wrapper.properties ├── gradlew ├── gradlew.bat └── settings.gradle.kts /.gitattributes: -------------------------------------------------------------------------------- 1 | # 2 | # https://help.github.com/articles/dealing-with-line-endings/ 3 | # 4 | # These are explicitly windows files and should use crlf 5 | *.bat text eol=crlf 6 | 7 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # Compiled class file 2 | *.class 3 | 4 | # Log file 5 | *.log 6 | 7 | # BlueJ files 8 | *.ctxt 9 | 10 | # Mobile Tools for Java (J2ME) 11 | .mtj.tmp/ 12 | 13 | # Package Files # 14 | *.jar 15 | *.war 16 | *.nar 17 | *.ear 18 | *.zip 19 | *.tar.gz 20 | *.rar 21 | 22 | # virtual machine crash logs, see http://www.java.com/en/download/help/error_hotspot.xml 23 | hs_err_pid* 24 | 25 | # Ignore Gradle project-specific cache directory 26 | .gradle 27 | 28 | # Ignore Gradle build output directory 29 | build 30 | -------------------------------------------------------------------------------- /.idea/app-inventor-modern.iml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | -------------------------------------------------------------------------------- /.idea/codeStyles/Project.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 13 | 14 | 23 | 24 | 39 | 40 | 55 | 56 | -------------------------------------------------------------------------------- /.idea/codeStyles/codeStyleConfig.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 5 | -------------------------------------------------------------------------------- /.idea/compiler.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | -------------------------------------------------------------------------------- /.idea/gradle.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 20 | 21 | -------------------------------------------------------------------------------- /.idea/jarRepositories.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 9 | 10 | 14 | 15 | 19 | 20 | 24 | 25 | -------------------------------------------------------------------------------- /.idea/jsLibraryMappings.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | -------------------------------------------------------------------------------- /.idea/misc.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /.idea/modules.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /.idea/vcs.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | -------------------------------------------------------------------------------- /.idea/workspace.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 109 | setProp((props: typeof ContainerDefaultProps) => (props.direction = value), 500) 110 | } 111 | /> 112 | 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 |
27 | {" "} 30 | 31 |
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 | 54 | 55 | 56 | 57 | 58 | 59 | { 60 | projects.map((project, i) => ( 61 | 62 | 63 | 64 | 65 | 66 | )) 67 | } 68 | 69 |
NameDescriptionAction
{project.name}{project.description}
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") --------------------------------------------------------------------------------