Skip to content

Commit

Permalink
Allow user to set App Name
Browse files Browse the repository at this point in the history
- Add XML Parser TagSoup to set the App Name in `config.xml`
- Add UI components to receive App Name input
  • Loading branch information
venkat24 committed Sep 3, 2017
1 parent 6ba94af commit 1ed764a
Show file tree
Hide file tree
Showing 7 changed files with 107 additions and 22 deletions.
3 changes: 3 additions & 0 deletions codeworld-server/codeworld-server.cabal
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@ Executable codeworld-server
base64-bytestring,
bytestring,
codeworld-compiler,
containers,
cryptonite,
data-default,
directory,
Expand All @@ -35,6 +36,8 @@ Executable codeworld-server
regex-tdfa,
snap-core,
snap-server,
strict,
tagsoup,
temporary,
text,
unix
Expand Down
54 changes: 39 additions & 15 deletions codeworld-server/src/AndroidExport.hs
Original file line number Diff line number Diff line change
Expand Up @@ -18,38 +18,62 @@

module AndroidExport where

import System.Process
import System.Directory
import System.FilePath
import Data.Maybe
import qualified Data.Map as M
import System.Process
import System.Directory
import System.FilePath
import qualified System.IO.Strict as ST
import Text.HTML.TagSoup

import Util

buildAndroid :: BuildMode -> ProgramId -> IO()
buildAndroid mode programId = do
buildAndroid :: BuildMode -> ProgramId -> AppProps -> IO ()
buildAndroid mode programId appProps = do
let appName = fromJust $ M.lookup "appName" appProps
initCordovaProject mode programId
copySource mode programId
setAppName mode programId appName
buildApk mode programId
return ()


initCordovaProject :: BuildMode -> ProgramId -> IO ()
initCordovaProject mode programId = do
let rootDir = androidRootDir mode
checkIfRootExists <- doesDirectoryExist rootDir
if not checkIfRootExists
then do
createDirectory $ androidRootDir mode
else return ()
let buildDir = androidBuildDir mode programId
checkIfBuildExists <- doesDirectoryExist buildDir
case checkIfBuildExists of
True -> return ()
False -> do
if not checkIfBuildExists
then do
checkIfParentExists <- doesDirectoryExist $ androidRootDir mode </> sourceParent programId
case checkIfParentExists of
True -> return ()
False -> do
if not checkIfParentExists
then do
createDirectory $ androidRootDir mode </> sourceParent programId
copyDirIfExists "android-template" (androidRootDir mode </> sourceBase programId)
return ()
else return ()
else return ()

copySource :: BuildMode -> ProgramId -> IO ()
copySource mode programId = do
copyFile (buildRootDir mode </> targetFile programId) (androidBuildDir mode programId </> "www" </> "js" </> "runjs.js")
copySource mode programId =
copyFile
(buildRootDir mode </> targetFile programId)
(androidBuildDir mode programId </> "www" </> "js" </> "runjs.js")

setAppName :: BuildMode -> ProgramId -> String -> IO ()
setAppName mode programId appName = do
let configFileName = androidBuildDir mode programId </> "config.xml"
configContents <- ST.readFile configFileName
let tagSoup = parseTags configContents
let newNameTag = [TagOpen "name" [], TagText appName]
writeFile configFileName (renderTags $ newSoup tagSoup newNameTag)
where newSoup soup insertTag = takeWhile nameId soup
++ insertTag
++ drop 2 (dropWhile nameId soup)
nameId = (~/= ("<name>"::String))

buildApk :: BuildMode -> ProgramId -> IO ()
buildApk mode programId = do
Expand Down
6 changes: 5 additions & 1 deletion codeworld-server/src/Main.hs
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,7 @@ import qualified Data.ByteString.Lazy as LB
import Data.Char (isSpace)
import Data.List
import Data.Maybe
import qualified Data.Map.Strict as M
import Data.Monoid
import qualified Data.Text as T
import qualified Data.Text.IO as T
Expand Down Expand Up @@ -361,6 +362,8 @@ exportAndroidHandler :: Snap()
exportAndroidHandler = do
mode <- getBuildMode
Just source <- getParam "source"
maybeAppName <- getParam "appName"
let appName = BC.unpack $ fromMaybe (BC.pack "CodeWorld App") maybeAppName
let programId = sourceToProgramId source
deployId = sourceToDeployId source
success <- liftIO $ do
Expand All @@ -369,7 +372,8 @@ exportAndroidHandler = do
writeDeployLink mode deployId programId
compileIfNeeded mode programId
unless success $ modifyResponse $ setResponseCode 500
liftIO $ buildAndroid mode programId
let appProps = M.fromList [("appName", appName)]
liftIO $ buildAndroid mode programId appProps
let result = CompileResult (unProgramId programId) (unDeployId deployId)
writeLBS (encode result)

Expand Down
3 changes: 3 additions & 0 deletions codeworld-server/src/Util.hs
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,7 @@ import qualified Data.ByteString.Base64 as B64
import qualified Data.ByteString.Lazy as LB
import Data.Maybe
import Data.Monoid
import qualified Data.Map.Strict as M
import Data.Text (Text)
import qualified Data.Text as T
import qualified Data.Text.Encoding as T
Expand All @@ -48,6 +49,8 @@ newtype DeployId = DeployId { unDeployId :: Text } deriving Eq
newtype DirId = DirId { unDirId :: Text} deriving Eq
newtype ShareId = ShareId { unShareId :: Text } deriving Eq

type AppProps = M.Map String String

autocompletePath :: FilePath
autocompletePath = "web/codeworld-base.txt"

Expand Down
9 changes: 9 additions & 0 deletions web/css/codeworld.css
Original file line number Diff line number Diff line change
Expand Up @@ -157,6 +157,15 @@ body {
cursor: pointer;
}

button {
border: none;
}

button:disabled,
button[disabled] {
background-color: #cccccc !important;
}

.cw-button {
border-radius: 4px;
cursor: pointer;
Expand Down
2 changes: 1 addition & 1 deletion web/env.html
Original file line number Diff line number Diff line change
Expand Up @@ -97,7 +97,7 @@
<a id="shareButton" class="cw-button yellow" style="display:none" onclick="share()"><i class="mdi mdi-18px mdi-share"></i>&nbsp; Share</a>
<a id="inspectButton" class="cw-button cyan" style="display:none" onclick="inspect()"><i class="mdi mdi-18px mdi-magnify"></i>&nbsp; Inspect</a>
<a class="cw-button red" onclick="stop()"><i class="mdi mdi-18px mdi-stop"></i>&nbsp; Stop</a>
<a class="cw-button green" onclick="exportAndroid()"><i class="mdi mdi-18px mdi-android"></i>&nbsp; Android</a>
<button id="exportAndroidButton" style="display: none" class="cw-button green" onclick="exportAndroid()"><i class="mdi mdi-18px mdi-android"></i>&nbsp; Android</button>
<a class="cw-button green" onclick="compile()"><i class="mdi mdi-18px mdi-play"></i>&nbsp; Run</a>
</div>
</div>
Expand Down
52 changes: 47 additions & 5 deletions web/js/codeworld.js
Original file line number Diff line number Diff line change
Expand Up @@ -690,11 +690,13 @@ function run(hash, dhash, msg, error) {
runner.contentWindow.location.replace(loc);
if (!!navigator.mediaDevices && !!navigator.mediaDevices.getUserMedia) {
document.getElementById('startRecButton').style.display = '';
document.getElementById('exportAndroidButton').style.display = '';
}
} else {
runner.contentWindow.location.replace('about:blank');
document.getElementById('runner').style.display = 'none';
document.getElementById('startRecButton').style.display = 'none';
document.getElementById('exportAndroidButton').style.display = 'none';
}

if (hash || msg) {
Expand Down Expand Up @@ -732,14 +734,51 @@ function goto(line, col) {
}

function exportAndroid() {
sweetAlert({
title: "App Information",
text: "App Name",
type: "input",
showCancelButton: true,
confirmButtonText: "Build App",
closeOnConfirm: false,
inputPlaceholder: "CodeWorld App"
},
function(inputValue){
if (inputValue === false) {
return false;
}
if (inputValue === "") {
swal.showInputError("Please enter a name for your app");
return false;
}
compileAndExportAndroid({
appName: inputValue,
});
sweetAlert({
title: "Please Wait",
text: "Your app is being built",
imageUrl: "https://upload.wikimedia.org/wikipedia/commons/b/b1/Loading_icon.gif",
showConfirmButton: false,
allowOutsideClick: false,
allowEscapeKey: false
});
});
}

function compileAndExportAndroid(appProps) {
var src = window.codeworldEditor.getValue();
var data = new FormData();
data.append('source', src);
data.append('mode', window.buildMode);
for(var prop in appProps) {
data.append(prop, appProps[prop]);
}
document.getElementById('exportAndroidButton').disabled = true;

sendHttp('POST', 'exportAndroid', data, function(request) {
if(request.status != 200) {
alert("Android build FAILED");
sweetAlert("Android Build Failed", "Something went wrong!", "error");
document.getElementById('exportAndroidButton').disabled = false;
return;
}
var response = JSON.parse(request.response);
Expand All @@ -748,17 +787,19 @@ function exportAndroid() {
var data = new FormData();
data.append('hash', hash);
data.append('mode', window.buildMode);
var props = {};
var props = {};
props.responseType = "blob";

sendHttpWithProps('POST', 'getAndroid', data, props, function(request) {
if(request.status != 200) {
alert("Android fetch FAILED");
sweetAlert("Android Fetch Failed", "Something went wrong!", "error");
document.getElementById('exportAndroidButton').disabled = false;
return;
}
console.log("Success");
swal("App Built!", "Your CodeWorld app will now be downloaded", "success");

var blob = request.response;
var d = new Date();
var d = new Date();
var filename = 'codeworld_app_'
+ d.toDateString().split(' ').join('_') + '_'
+ d.getHours() +':'+ d.getMinutes() +':'+ d.getSeconds()
Expand All @@ -774,6 +815,7 @@ function exportAndroid() {
window.URL.revokeObjectURL(url);

a.remove();
document.getElementById('exportAndroidButton').disabled = false;
});

});
Expand Down

0 comments on commit 1ed764a

Please sign in to comment.