Compare commits
10 commits
03c0ec74c0
...
94b5d2aeca
Author | SHA1 | Date | |
---|---|---|---|
94b5d2aeca | |||
eef403f0cb | |||
cdd0ac3531 | |||
38f4fa9774 | |||
81f421b9c0 | |||
2787aee01a | |||
f83bf386cd | |||
b8dbee59ad | |||
be0786db68 | |||
444b92d1e7 |
9 changed files with 774 additions and 143 deletions
84
README.md
84
README.md
|
@ -1,7 +1,6 @@
|
||||||
# Android App (build via docker/podman)
|
# Calender App
|
||||||
|
|
||||||
The goal of this repo, is to create a container that can serve to produce an "empty android Application" (i.e `app.apk` file).
|
simple calender app
|
||||||
As such the philosophy is to keep the process "simple" as to now make the understanding too difficult.
|
|
||||||
|
|
||||||
## usage
|
## usage
|
||||||
|
|
||||||
|
@ -12,82 +11,7 @@ As such the philosophy is to keep the process "simple" as to now make the unders
|
||||||
./build-android-app.sh
|
./build-android-app.sh
|
||||||
```
|
```
|
||||||
|
|
||||||
2. follow the configuration
|
|
||||||
3. upon success the apk file created is in app/result/app.apk and can be installed via `adb`
|
|
||||||
```
|
|
||||||
adb install -r app/result/app.apk
|
|
||||||
```
|
|
||||||
|
|
||||||
## basic ideas
|
## Screenshots
|
||||||
|
|
||||||
* work within container (debian based image)
|

|
||||||
* use Makefile as a build tool
|
|
||||||
|
|
||||||
## benefits of this (compared to AndroidStudio)
|
|
||||||
|
|
||||||
* no need to install rather bloated hell of software (i.e AndroidStudio) and all
|
|
||||||
* less hidding of internals (i.e Makefile allows to see how app.apk is made)
|
|
||||||
* small app.apk file
|
|
||||||
* oftentimes faster compile time (as compared with AndroidStudio Gradle builds)
|
|
||||||
* quick "webview" which can serve as starting point for people that can to PWA and websites
|
|
||||||
* Assisted initial configuration provides access to configure almost all types of [Android app permissions](app/.Makefile.scripts/make--app-config.sh#L127)
|
|
||||||
* no need to have Kotlin, Gradle setup
|
|
||||||
/
|
|
||||||
## basic info
|
|
||||||
|
|
||||||
This repo should allow to generate an empty "android app". by simply cloning this repo and
|
|
||||||
```
|
|
||||||
./build-android-app.sh
|
|
||||||
```
|
|
||||||
It does so via:
|
|
||||||
|
|
||||||
1. building a container (in any of the runtime/daemons it finds: i.e. docker,podman,etc..)
|
|
||||||
2. running this container having the `./app` folder being mounted within as `/app`
|
|
||||||
3. executing the [`app/Makefile`](app/Makefile) which will then:
|
|
||||||
4. either work with the configuration stored in an `app/app-config.sh` in case such file exists or
|
|
||||||
5. if not go through a `whiptail` text menu wizzard to configure a new empty app. (Makefile recipe: `./app-config.sh`)
|
|
||||||
6. it will then download the required android sdk files as necessary (Makefile recipe: `./android-sdk/installed`)
|
|
||||||
7. go through the further steps to setup the blank app.
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
## files and purpose
|
|
||||||
|
|
||||||
Upon `clone` of this repo the `app` folder is setup with these files:
|
|
||||||
```
|
|
||||||
# The (GNU) Makefile which...
|
|
||||||
app/Makefile
|
|
||||||
# ... has recipes that call scripts in folder....
|
|
||||||
app/.Makefile.scripts
|
|
||||||
# .. which creates an `app-config.sh`, a file to keep
|
|
||||||
# the configuration (app name,lable,api-levels,permissions etc)...
|
|
||||||
app/.Makefile.scripts/make--app-config.sh
|
|
||||||
# .. which creates an `AndroidManifest.xml`
|
|
||||||
app/.Makefile.scripts/make--AndroidManifest.xml
|
|
||||||
# .. which creates an `AppActivity.java` file (which just setup a Webview and loads `assets/index.html`)
|
|
||||||
app/.Makefile.scripts/make--AppActivity.java.sh
|
|
||||||
# .. which installs the necessary Android SDK in the correct versions
|
|
||||||
app/.Makefile.scripts/make--android-sdk.sh
|
|
||||||
app/assets
|
|
||||||
# the index.html file
|
|
||||||
app/assets/index.html
|
|
||||||
app/res
|
|
||||||
app/res/drawable
|
|
||||||
# the icon of the app
|
|
||||||
app/res/drawable/appicon.xml
|
|
||||||
```
|
|
||||||
|
|
||||||
Upon further `./build-android-app.sh` execution more folders will appear
|
|
||||||
```
|
|
||||||
# a folder in which the Android-sdk stuff (installed via sdkmanager) is stored
|
|
||||||
android-sdk
|
|
||||||
# folders used during build...
|
|
||||||
# ... for temporary files
|
|
||||||
bin/
|
|
||||||
obj/
|
|
||||||
result/
|
|
||||||
# app configuration resulting from text whiptail menu
|
|
||||||
app-config.sh
|
|
||||||
# the Manifest file as resulted from data from app-config.sh
|
|
||||||
AndroidManifest.xml
|
|
||||||
```
|
|
||||||
|
|
|
@ -8,31 +8,21 @@ test -f app-config.sh && {
|
||||||
echo "package $APP_PACKAGE;"
|
echo "package $APP_PACKAGE;"
|
||||||
|
|
||||||
cat << 'APPACTIVITYJAVA'
|
cat << 'APPACTIVITYJAVA'
|
||||||
|
|
||||||
import android.provider.Settings ;
|
import android.provider.Settings ;
|
||||||
import android.content.Intent;
|
import android.content.Intent;
|
||||||
import android.util.Log;
|
import android.util.Log;
|
||||||
import android.util.Base64;
|
|
||||||
import java.util.Objects;
|
|
||||||
import android.app.Activity;
|
import android.app.Activity;
|
||||||
import android.os.Bundle;
|
import android.os.Bundle;
|
||||||
import android.os.CountDownTimer;
|
|
||||||
import android.os.Environment;
|
import android.os.Environment;
|
||||||
import android.text.method.ScrollingMovementMethod;
|
|
||||||
import android.view.*;
|
|
||||||
//import android.view.MenuItem;
|
//import android.view.MenuItem;
|
||||||
import android.view.ViewGroup.*;
|
import android.view.*;
|
||||||
import android.widget.*;
|
// for WebView,WebMessage,WebMessagePort,
|
||||||
//import android.widget.Toast;
|
|
||||||
//import android.widget.TextView;
|
|
||||||
import android.webkit.*;
|
import android.webkit.*;
|
||||||
import android.net.Uri;
|
import android.net.Uri;
|
||||||
import org.json.JSONObject;
|
import org.json.JSONObject;
|
||||||
//import android.webkit.WebView;
|
|
||||||
//import android.webkit.WebMessage;
|
|
||||||
//import android.webkit.WebMessagePort;
|
|
||||||
import java.io.InputStream;
|
import java.io.InputStream;
|
||||||
import java.io.File;
|
import java.io.File;
|
||||||
|
import java.util.Objects;
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
@ -70,6 +60,9 @@ public class AppActivity extends Activity {
|
||||||
myWebSettings.setBuiltInZoomControls(true);
|
myWebSettings.setBuiltInZoomControls(true);
|
||||||
myWebSettings.setDisplayZoomControls(false);
|
myWebSettings.setDisplayZoomControls(false);
|
||||||
myWebSettings.setJavaScriptEnabled(true);
|
myWebSettings.setJavaScriptEnabled(true);
|
||||||
|
myWebSettings.setDomStorageEnabled(true);
|
||||||
|
myWebSettings.setDatabaseEnabled(true);
|
||||||
|
myWebSettings.setDatabasePath("/data/data/" + myWebView.getContext().getPackageName() + "/databases/");
|
||||||
myWebView.addJavascriptInterface(this, "myJavaScriptInterface");
|
myWebView.addJavascriptInterface(this, "myJavaScriptInterface");
|
||||||
// load the html from assets file
|
// load the html from assets file
|
||||||
String html = readFileFromAssets("index.html");
|
String html = readFileFromAssets("index.html");
|
||||||
|
@ -85,4 +78,3 @@ public class AppActivity extends Activity {
|
||||||
return "this is good";
|
return "this is good";
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
APPACTIVITYJAVA
|
|
||||||
|
|
15
app/Makefile
15
app/Makefile
|
@ -47,23 +47,28 @@ include Makefile.app-config
|
||||||
|
|
||||||
|
|
||||||
# make the resources "R.java" thing
|
# make the resources "R.java" thing
|
||||||
./src/PACKAGE/R.java : $(shell find ./res -type f) app-config.sh ./AndroidManifest.xml ./android-sdk/installed
|
./src/$(PACKAGE)/R.java : $(shell find ./res -type f) app-config.sh ./AndroidManifest.xml ./android-sdk/installed | ./src/$(PACKAGE)
|
||||||
$(BUILDTOOLS)/aapt package \
|
$(BUILDTOOLS)/aapt package \
|
||||||
-v -f -m -S ./res -J ./src -M ./AndroidManifest.xml \
|
-v -f -m -S ./res -J ./src -M ./AndroidManifest.xml \
|
||||||
-I $(ANDROID_JAR)
|
-I $(ANDROID_JAR)
|
||||||
|
|
||||||
# generate the AppActivity.java (template)
|
# generate the AppActivity.java (template
|
||||||
./src/package/AppActivity.java: app-config.sh
|
# the "|" denotes an "order-only" prerequiste (as in https://stackoverflow.com/a/58040049/1711186)
|
||||||
|
./src/$(PACKAGE)/AppActivity.java: app-config.sh | ./src/$(PACKAGE)
|
||||||
./.Makefile.scripts/make--AppActivity.java.sh > $@
|
./.Makefile.scripts/make--AppActivity.java.sh > $@
|
||||||
|
|
||||||
|
./src/$(PACKAGE):
|
||||||
|
mkdir -p $@
|
||||||
|
|
||||||
# install the necessary android sdks
|
# install the necessary android sdks
|
||||||
./android-sdk/installed: app-config.sh
|
./android-sdk/installed: app-config.sh ./.Makefile.scripts/make--android-sdk.sh
|
||||||
./.Makefile.scripts/make--android-sdk.sh
|
./.Makefile.scripts/make--android-sdk.sh
|
||||||
|
|
||||||
# generate the AndroidManifest.xml
|
# generate the AndroidManifest.xml
|
||||||
./AndroidManifest.xml: app-config.sh
|
./AndroidManifest.xml: app-config.sh ./.Makefile.scripts/make--AndroidManifest.xml
|
||||||
./.Makefile.scripts/make--AndroidManifest.xml
|
./.Makefile.scripts/make--AndroidManifest.xml
|
||||||
|
|
||||||
|
# !!this step (when/if) run will trigger a restart of the "make" as the rules tartget is included
|
||||||
Makefile.app-config: app-config.sh Makefile
|
Makefile.app-config: app-config.sh Makefile
|
||||||
source app-config.sh; \
|
source app-config.sh; \
|
||||||
tee $@ << MAKEFILE_APP_CONFIG
|
tee $@ << MAKEFILE_APP_CONFIG
|
||||||
|
|
|
@ -4,50 +4,286 @@
|
||||||
<meta charset="UTF-8">
|
<meta charset="UTF-8">
|
||||||
<meta content="width=device-width,initial-scale=1.0" name="viewport">
|
<meta content="width=device-width,initial-scale=1.0" name="viewport">
|
||||||
</head>
|
</head>
|
||||||
<style>
|
<style>
|
||||||
@keyframes wobble {
|
* {
|
||||||
0% {
|
font-family: sans;
|
||||||
transform: scale(0.1);
|
box-sizing:border-box;
|
||||||
/* transform: rotate(-5deg);
|
}
|
||||||
transform: rotate(5deg);*/
|
body,html{
|
||||||
opacity:0.0
|
margin:0;
|
||||||
}
|
padding:0
|
||||||
22% {
|
}
|
||||||
transform: scale(2.0);
|
|
||||||
/*/ transform: rotate(-5deg);*/
|
.infinityScroll{
|
||||||
opacity:1.0
|
height:50vh;
|
||||||
}
|
overflow:scroll;
|
||||||
99% {
|
border:1px solid red;
|
||||||
transform: scale(1.0);
|
position:relative;
|
||||||
/*/ transform: rotate(-5deg);*/
|
}
|
||||||
opacity:0.0
|
.space{
|
||||||
}
|
background:linear-gradient(white, blue);
|
||||||
|
height:300%;
|
||||||
|
opacity:0.5;
|
||||||
}
|
}
|
||||||
</style>
|
</style>
|
||||||
<body style=" background: radial-gradient(#111, #000);">
|
<style>
|
||||||
<h1> SUPER</h1>
|
* {
|
||||||
<script>
|
font-family: sans;
|
||||||
var count=0;
|
}
|
||||||
window.addEventListener("load",()=>{
|
:root {
|
||||||
function insert(){
|
touch-action: pan-x pan-y;
|
||||||
count++;
|
height: 100%
|
||||||
var h2 = document.createElement("h2");
|
}
|
||||||
h2.textContent=" "+ count + ". javascript works"
|
body{
|
||||||
h2.style.color="#"+Math.random().toString(16).slice(3,9);
|
background-color:#ffa;
|
||||||
// h2.style.transform="rotate("+((Math.random()*3600)|0)/10+"deg)";
|
margin:0
|
||||||
h2.style.fontSize=""+Math.random()*20+"pt";
|
}
|
||||||
h2.style.textAlign="center";
|
.monthview {
|
||||||
h2.style.animation="wobble 5s ease-in-out infinite alternate"
|
background-color:rgba(255,255,255,0.5);
|
||||||
document.body.insertBefore(h2,document.body.children[(document.body.children.length*Math.random())|0])
|
border:2px solid rgba(0,0,0,0.5);
|
||||||
// h2.scrollIntoView({"behavior":"smooth"});
|
border-radius: 10%;
|
||||||
if(document.body.children.length>15){
|
margin:5px;
|
||||||
document.body.children[(document.body.children.length*Math.random())|0].remove();
|
min-height: 20vw;
|
||||||
|
/*margin:5px;*/
|
||||||
|
/* scroll-snap-align: center;*/
|
||||||
|
overflow:hidden;
|
||||||
|
}
|
||||||
|
.label{
|
||||||
|
background-color:#a44;
|
||||||
|
color:#fff;
|
||||||
|
font-size:10vw;
|
||||||
|
text-align:center;
|
||||||
|
}
|
||||||
|
|
||||||
|
.days{
|
||||||
|
display: grid;
|
||||||
|
width: 100%;
|
||||||
|
grid-template-columns: repeat(7, 1fr);
|
||||||
|
}
|
||||||
|
|
||||||
|
.days div {
|
||||||
|
text-align:center;
|
||||||
|
height: 2cm;
|
||||||
|
align:content;
|
||||||
|
border:1px solid grey;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
#mainDiv{
|
||||||
|
box-sizing:border-box;
|
||||||
|
margin:0;
|
||||||
|
/* scroll-snap-type: y mandatory;*/
|
||||||
|
height:100vh;
|
||||||
|
overflow:scroll;
|
||||||
|
border: 1px solid red;
|
||||||
|
margin:0;
|
||||||
|
width:100vw;
|
||||||
|
}
|
||||||
|
.orig{
|
||||||
|
|
||||||
|
border: 3px solid blue;
|
||||||
|
}
|
||||||
|
.weekend{
|
||||||
|
color:red;
|
||||||
|
background-color:white;
|
||||||
|
}
|
||||||
|
|
||||||
|
</style>
|
||||||
|
<body>
|
||||||
|
<div id="mainDiv" class="infinityScroll"></div>
|
||||||
|
|
||||||
|
<script>
|
||||||
|
// goals:
|
||||||
|
// 1. no/huge limits
|
||||||
|
// 1.1. scroll basis is a number (and hence scroll can continues as long as number can increase/descrease)
|
||||||
|
// 2. both directions
|
||||||
|
// 3. resetability
|
||||||
|
|
||||||
|
// answers
|
||||||
|
// todo: at center of scroll will be a div containing the number
|
||||||
|
// todo: onnce scrolling settled, the position reached is the new center
|
||||||
|
|
||||||
|
// questions
|
||||||
|
// Q1: what is to be scrolled ?
|
||||||
|
// A1: elements that are set to `.infinityScroll` class
|
||||||
|
// Q2: how is the scroll to infinity implemented (exponential stuff)
|
||||||
|
|
||||||
|
window.addEventListener("load",()=>{
|
||||||
|
|
||||||
|
var locale = window.navigator.userLanguage || window.navigator.language || "en";
|
||||||
|
|
||||||
|
|
||||||
|
function createMonthView(date = new Date()){
|
||||||
|
var monthviewDiv = document.createElement("div")
|
||||||
|
monthviewDiv.className = "monthview";
|
||||||
|
var labelDiv = document.createElement("div");
|
||||||
|
labelDiv.textContent = date.toLocaleString(locale,{"month":"long","year":"numeric"})
|
||||||
|
labelDiv.className = "label"
|
||||||
|
monthviewDiv.appendChild(labelDiv);
|
||||||
|
var daysDiv = document.createElement("div");
|
||||||
|
daysDiv.className="days";
|
||||||
|
monthviewDiv.appendChild(daysDiv);
|
||||||
|
// mainDiv.appendChild(monthviewDiv);
|
||||||
|
monthviewDiv.scrollIntoView();
|
||||||
|
// var weekendDiv = document.createElement("div");
|
||||||
|
// weekendDiv.className = "weekend";
|
||||||
|
// daysDiv.appendChild(weekendDiv);
|
||||||
|
var day = new Date(date);
|
||||||
|
day.setDate(1);
|
||||||
|
while(day.getMonth() == date.getMonth()){
|
||||||
|
var dayDiv = document.createElement("div");
|
||||||
|
dayDiv.className = "day";
|
||||||
|
var column = day.getDay();
|
||||||
|
column = column == 0 ? 7: column;
|
||||||
|
if(column>=6){
|
||||||
|
dayDiv.classList.add("weekend");
|
||||||
}
|
}
|
||||||
setTimeout(()=>{window.requestAnimationFrame(insert);},100);
|
dayDiv.style.gridColumn = column;
|
||||||
|
dayDiv.textContent = day.getDate()
|
||||||
|
daysDiv.appendChild(dayDiv);
|
||||||
|
day.setDate(day.getDate()+1);
|
||||||
|
}
|
||||||
|
return monthviewDiv;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
function makeInfinityScroll(element){
|
||||||
|
element.nn=element.nn||{"position":0};
|
||||||
|
var mdate;
|
||||||
|
//var before = document.createElement("div");
|
||||||
|
//var after = document.createElement("div");
|
||||||
|
//after.style.backgroundColor="blue";
|
||||||
|
//var center = document.createElement("div");
|
||||||
|
//before.className = after.className = "space";
|
||||||
|
//after.style.background="linear-gradient(yellow,red)";
|
||||||
|
//center.textContent="center "+element.nn.position;
|
||||||
|
//center.style.border="1px solid red";
|
||||||
|
//center = createMonthView();
|
||||||
|
//center.nnindex=0;
|
||||||
|
//element.appendChild(after);
|
||||||
|
|
||||||
|
for(var i = -3; i< 3; i++){
|
||||||
|
mdate = new Date();
|
||||||
|
mdate.setMonth(mdate.getMonth()+i);
|
||||||
|
var nextMonth=createMonthView(mdate);
|
||||||
|
nextMonth.nnindex=i;
|
||||||
|
element.appendChild(nextMonth);
|
||||||
|
nextMonth.classList.add('orig');
|
||||||
|
}
|
||||||
|
|
||||||
|
element.children[3].scrollIntoView({block:"center"});
|
||||||
|
|
||||||
|
|
||||||
|
setTimeout(()=>{
|
||||||
|
|
||||||
|
//console.log(element.firstChild,element.firstChild.nnindex);
|
||||||
|
var beforeind=0;
|
||||||
|
console.log("fc",element,element.firstChild);
|
||||||
|
if(element.firstChild.nnindex){
|
||||||
|
beforeind = element.firstChild.nnindex
|
||||||
|
}
|
||||||
|
mdate = new Date();
|
||||||
|
mdate.setMonth(mdate.getMonth()+beforeind-1);
|
||||||
|
var newBefore = createMonthView(mdate);
|
||||||
|
newBefore.nnindex=beforeind-1;
|
||||||
|
// newBefore.className="space";
|
||||||
|
console.log("prio "+element.scrollTop,""+element.scrollHeight,element.clientHeight);
|
||||||
|
// var savscrolltop = element.scrollTop;
|
||||||
|
element.insertBefore(newBefore,element.firstChild);
|
||||||
|
// element.scrollTop=savscrolltop-newBefore.clientHeight;
|
||||||
|
|
||||||
|
// var beforeind=0;
|
||||||
|
// console.log("fc",element,element.firstChild);
|
||||||
|
// if(element.firstChild.nnindex){
|
||||||
|
// beforeind = element.firstChild.nnindex
|
||||||
|
// }
|
||||||
|
// mdate = new Date();
|
||||||
|
// mdate.setMonth(mdate.getMonth()+beforeind-1);
|
||||||
|
// var newBefore = createMonthView(mdate);
|
||||||
|
// newBefore.nnindex=beforeind-1;
|
||||||
|
//// newBefore.className="space";
|
||||||
|
// console.log("prio "+element.scrollTop,""+element.scrollHeight,element.clientHeight);
|
||||||
|
// var savscrolltop = element.scrollTop;
|
||||||
|
// element.insertBefore(newBefore,element.firstChild);
|
||||||
|
// element.scrollTop=savscrolltop-newBefore.clientHeight;
|
||||||
|
//
|
||||||
|
// console.log("POST "+element.scrollTop,""+element.scrollHeight,element.clientHeight);
|
||||||
|
//
|
||||||
|
},100000);
|
||||||
|
|
||||||
|
|
||||||
|
element.addEventListener("scroll",()=>{
|
||||||
|
if(element.scrollUpdateSchedule!=1){
|
||||||
|
element.scrollUpdateSchedule=1;
|
||||||
|
|
||||||
|
requestAnimationFrame(()=>{
|
||||||
|
element.scrollUpdateSchedule=0;
|
||||||
|
//if(element.scrollTop/element.scrollHeight < 0.2){
|
||||||
|
// console.log("ch",element.clientHeight,element.scrollTop);
|
||||||
|
if(element.scrollTop < 3* element.clientHeight)
|
||||||
|
{
|
||||||
|
console.log(element.scrollTop)
|
||||||
|
//console.log(element.firstChild,element.firstChild.nnindex);
|
||||||
|
var beforeind=0;
|
||||||
|
if(element.firstChild.nnindex){
|
||||||
|
beforeind = element.firstChild.nnindex
|
||||||
|
}
|
||||||
|
mdate = new Date();
|
||||||
|
mdate.setMonth(mdate.getMonth()+beforeind-1);
|
||||||
|
var newBefore = createMonthView(mdate);
|
||||||
|
newBefore.nnindex=beforeind-1;
|
||||||
|
// newBefore.className="space";
|
||||||
|
console.log("prio"+element.scrollTop,element.scrollHeight);
|
||||||
|
element.insertBefore(newBefore,element.firstChild);
|
||||||
|
console.log("POST"+element.scrollTop,element.scrollHeight);
|
||||||
|
|
||||||
|
// while(element.scrollHeight>200*element.clientHeight){
|
||||||
|
// element.children[element.children.length-1].remove();
|
||||||
|
// console.log("REMOVED"+element.scrollTop);
|
||||||
|
// }
|
||||||
|
|
||||||
}
|
}
|
||||||
insert();
|
});
|
||||||
|
}
|
||||||
},false);
|
},false);
|
||||||
</script>
|
}
|
||||||
</body>
|
/////-- if(element.scrollTop > element.scrollHeight - 4 * element.clientHeight)
|
||||||
|
/////-- {
|
||||||
|
/////-- //var afterind = element.children[element.children.length].nnindex || 0;
|
||||||
|
/////-- var afterind=0;
|
||||||
|
/////-- if(element.children[element.children.length-1].nnindex){
|
||||||
|
/////-- afterind = element.children[element.children.length-1].nnindex;
|
||||||
|
/////-- }
|
||||||
|
/////-- var newAfter = document.createElement("div");
|
||||||
|
/////--// newBefore.className="space";
|
||||||
|
/////-- newAfter.innerHTML=new Array(200).fill("a").map((a,i)=>{return afterind+"-"+i;}).join("<br>");
|
||||||
|
/////-- newAfter.nnindex=afterind+1;
|
||||||
|
/////-- console.log("prio"+element.scrollTop);
|
||||||
|
/////-- element.appendChild(newAfter);
|
||||||
|
/////-- console.log("POST"+element.scrollTop);
|
||||||
|
/////--
|
||||||
|
/////--
|
||||||
|
/////--// while(element.scrollHeight>200*element.clientHeight){
|
||||||
|
/////--// element.children[0].remove();
|
||||||
|
/////--// console.log("REMOVED"+element.scrollTop);
|
||||||
|
/////--// }
|
||||||
|
/////--
|
||||||
|
/////--
|
||||||
|
/////-- }
|
||||||
|
/////--// console.log(Date.now(),"Udpate",element.scrollTop);
|
||||||
|
/////-- console.log(Date.now(),"Udpate",element.scrollTop/element.scrollHeight,"AAA",element.scrollTop,">",element.scrollHeight - 4 * element.clientHeight,element.scrollHeight);
|
||||||
|
/////-- element.scrollUpdateSchedule=0;
|
||||||
|
/////-- });
|
||||||
|
/////-- }
|
||||||
|
// console.log(element.scrollTop);
|
||||||
|
// },false);
|
||||||
|
// }
|
||||||
|
|
||||||
|
document.querySelectorAll('.infinityScroll').forEach(makeInfinityScroll);
|
||||||
|
|
||||||
|
},false);
|
||||||
|
|
||||||
|
window.addEventListener("error",(error)=>{ document.body.innerHTML = "<h1>error</h1><pre>" + error.filename + "\nline:" + error.lineno + "\n"+error.message +"</pre>"; },false);
|
||||||
|
</script>
|
||||||
|
</body>
|
||||||
</html>
|
</html>
|
||||||
|
|
182
app/assets/index.html.1
Normal file
182
app/assets/index.html.1
Normal file
|
@ -0,0 +1,182 @@
|
||||||
|
<!DOCTYPE html>
|
||||||
|
<html>
|
||||||
|
<head>
|
||||||
|
<meta charset="UTF-8">
|
||||||
|
<meta content="width=device-width,initial-scale=1.0" name="viewport">
|
||||||
|
</head>
|
||||||
|
<style>
|
||||||
|
:root {
|
||||||
|
touch-action: pan-x pan-y;
|
||||||
|
height: 100%
|
||||||
|
}
|
||||||
|
@keyframes wobble {
|
||||||
|
0% {
|
||||||
|
transform: scale(0.1);
|
||||||
|
opacity:0.0
|
||||||
|
}
|
||||||
|
100% {
|
||||||
|
transform: scale(1.0);
|
||||||
|
opacity:1.0
|
||||||
|
}
|
||||||
|
}
|
||||||
|
body{
|
||||||
|
background-color:#ffa;
|
||||||
|
}
|
||||||
|
div {
|
||||||
|
margin: 0em;
|
||||||
|
padding: 2em;
|
||||||
|
}
|
||||||
|
#target {
|
||||||
|
background: white;
|
||||||
|
border: 1px solid black;
|
||||||
|
}
|
||||||
|
</style>
|
||||||
|
<!--<body onload="init();" style="touch-action:none">-->
|
||||||
|
<body onload="init();">
|
||||||
|
<div id="target">
|
||||||
|
Touch and Hold with 2 pointers, then pinch in or out.<br />
|
||||||
|
The background color will change to pink if the pinch is opening (Zoom In)
|
||||||
|
or changes to lightblue if the pinch is closing (Zoom out).
|
||||||
|
</div>
|
||||||
|
<!-- UI for logging/debugging -->
|
||||||
|
<button id="log" onclick="enableLog(event);">Start/Stop event logging</button>
|
||||||
|
<button id="clearlog" onclick="clearLog(event);">Clear the log</button>
|
||||||
|
<p></p>
|
||||||
|
<output></output>
|
||||||
|
|
||||||
|
<a href="https://server.alexmahr.de/calender">calender</a>
|
||||||
|
<h1>Webview</h1>
|
||||||
|
<pre id="output">output</pre>
|
||||||
|
<script>
|
||||||
|
window.addEventListener("error",(error)=>{
|
||||||
|
document.body.innerHTML = "<h1>error</h1><pre>" +
|
||||||
|
error.filename +
|
||||||
|
"\nline:" + error.lineno +
|
||||||
|
"\n"+error.message +"</pre>";
|
||||||
|
},false);
|
||||||
|
|
||||||
|
['touchstart','touchmove','touchend'].forEach((evname)=>{
|
||||||
|
window.addEventListener(evname,(ev)=>{
|
||||||
|
output.textContent+=evname+"\n" ;
|
||||||
|
ev.preventDefault();
|
||||||
|
},false);
|
||||||
|
});
|
||||||
|
window.addEventListener("load",()=>{
|
||||||
|
var count = localStorage.getItem("app-opened-count")|| 0;
|
||||||
|
count++;
|
||||||
|
localStorage.setItem("app-opened-count",count);
|
||||||
|
var h2 = document.createElement("h2");
|
||||||
|
h2.textContent = "Javascript works! (app was opened " + count + " times)";
|
||||||
|
h2.style.animation="wobble 1s ease-in-out 0s 1 forwards normal running"
|
||||||
|
document.body.appendChild(h2);
|
||||||
|
},false);
|
||||||
|
|
||||||
|
// Global vars to cache event state
|
||||||
|
const evCache = [];
|
||||||
|
let prevDiff = -1;
|
||||||
|
|
||||||
|
function init() {
|
||||||
|
// Install event handlers for the pointer target
|
||||||
|
const el = document.getElementById("target");
|
||||||
|
el.onpointerdown = pointerdownHandler;
|
||||||
|
el.onpointermove = pointermoveHandler;
|
||||||
|
|
||||||
|
// Use same handler for pointer{up,cancel,out,leave} events since
|
||||||
|
// the semantics for these events - in this app - are the same.
|
||||||
|
el.onpointerup = pointerupHandler;
|
||||||
|
el.onpointercancel = pointerupHandler;
|
||||||
|
el.onpointerout = pointerupHandler;
|
||||||
|
el.onpointerleave = pointerupHandler;
|
||||||
|
}
|
||||||
|
function pointerdownHandler(ev) {
|
||||||
|
// The pointerdown event signals the start of a touch interaction.
|
||||||
|
// This event is cached to support 2-finger gestures
|
||||||
|
evCache.push(ev);
|
||||||
|
log("pointerDown", ev);
|
||||||
|
}
|
||||||
|
function pointermoveHandler(ev) {
|
||||||
|
// This function implements a 2-pointer horizontal pinch/zoom gesture.
|
||||||
|
//
|
||||||
|
// If the distance between the two pointers has increased (zoom in),
|
||||||
|
// the target element's background is changed to "pink" and if the
|
||||||
|
// distance is decreasing (zoom out), the color is changed to "lightblue".
|
||||||
|
//
|
||||||
|
// This function sets the target element's border to "dashed" to visually
|
||||||
|
// indicate the pointer's target received a move event.
|
||||||
|
log("pointerMove", ev);
|
||||||
|
ev.target.style.border = "dashed";
|
||||||
|
|
||||||
|
// Find this event in the cache and update its record with this event
|
||||||
|
const index = evCache.findIndex(
|
||||||
|
(cachedEv) => cachedEv.pointerId === ev.pointerId,
|
||||||
|
);
|
||||||
|
evCache[index] = ev;
|
||||||
|
|
||||||
|
// If two pointers are down, check for pinch gestures
|
||||||
|
if (evCache.length === 2) {
|
||||||
|
// Calculate the distance between the two pointers
|
||||||
|
const curDiff = Math.abs(evCache[0].clientX - evCache[1].clientX);
|
||||||
|
|
||||||
|
if (prevDiff > 0) {
|
||||||
|
if (curDiff > prevDiff) {
|
||||||
|
// The distance between the two pointers has increased
|
||||||
|
log("Pinch moving OUT -> Zoom in", ev);
|
||||||
|
ev.target.style.background = "pink";
|
||||||
|
}
|
||||||
|
if (curDiff < prevDiff) {
|
||||||
|
// The distance between the two pointers has decreased
|
||||||
|
log("Pinch moving IN -> Zoom out", ev);
|
||||||
|
ev.target.style.background = "lightblue";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Cache the distance for the next move event
|
||||||
|
prevDiff = curDiff;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
function pointerupHandler(ev) {
|
||||||
|
log(ev.type, ev);
|
||||||
|
// Remove this pointer from the cache and reset the target's
|
||||||
|
// background and border
|
||||||
|
removeEvent(ev);
|
||||||
|
ev.target.style.background = "white";
|
||||||
|
ev.target.style.border = "1px solid black";
|
||||||
|
|
||||||
|
// If the number of pointers down is less than two then reset diff tracker
|
||||||
|
if (evCache.length < 2) {
|
||||||
|
prevDiff = -1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
function removeEvent(ev) {
|
||||||
|
// Remove this event from the target's cache
|
||||||
|
const index = evCache.findIndex(
|
||||||
|
(cachedEv) => cachedEv.pointerId === ev.pointerId,
|
||||||
|
);
|
||||||
|
evCache.splice(index, 1);
|
||||||
|
}
|
||||||
|
// Log events flag
|
||||||
|
let logEvents = false;
|
||||||
|
|
||||||
|
// Logging/debugging functions
|
||||||
|
function enableLog(ev) {
|
||||||
|
logEvents = !logEvents;
|
||||||
|
}
|
||||||
|
|
||||||
|
function log(prefix, ev) {
|
||||||
|
if (!logEvents) return;
|
||||||
|
const o = document.getElementsByTagName("output")[0];
|
||||||
|
o.innerText += `${prefix}:
|
||||||
|
pointerID = ${ev.pointerId}
|
||||||
|
pointerType = ${ev.pointerType}
|
||||||
|
isPrimary = ${ev.isPrimary}
|
||||||
|
`;
|
||||||
|
}
|
||||||
|
|
||||||
|
function clearLog(event) {
|
||||||
|
const o = document.getElementsByTagName("output")[0];
|
||||||
|
o.textContent = "";
|
||||||
|
}
|
||||||
|
|
||||||
|
</script>
|
||||||
|
</body>
|
||||||
|
</html>
|
182
app/assets/index.html.1.html
Normal file
182
app/assets/index.html.1.html
Normal file
|
@ -0,0 +1,182 @@
|
||||||
|
<!DOCTYPE html>
|
||||||
|
<html>
|
||||||
|
<head>
|
||||||
|
<meta charset="UTF-8">
|
||||||
|
<meta content="width=device-width,initial-scale=1.0" name="viewport">
|
||||||
|
</head>
|
||||||
|
<style>
|
||||||
|
:root {
|
||||||
|
touch-action: pan-x pan-y;
|
||||||
|
height: 100%
|
||||||
|
}
|
||||||
|
@keyframes wobble {
|
||||||
|
0% {
|
||||||
|
transform: scale(0.1);
|
||||||
|
opacity:0.0
|
||||||
|
}
|
||||||
|
100% {
|
||||||
|
transform: scale(1.0);
|
||||||
|
opacity:1.0
|
||||||
|
}
|
||||||
|
}
|
||||||
|
body{
|
||||||
|
background-color:#ffa;
|
||||||
|
}
|
||||||
|
div {
|
||||||
|
margin: 0em;
|
||||||
|
padding: 2em;
|
||||||
|
}
|
||||||
|
#target {
|
||||||
|
background: white;
|
||||||
|
border: 1px solid black;
|
||||||
|
}
|
||||||
|
</style>
|
||||||
|
<!--<body onload="init();" style="touch-action:none">-->
|
||||||
|
<body onload="init();">
|
||||||
|
<div id="target">
|
||||||
|
Touch and Hold with 2 pointers, then pinch in or out.<br />
|
||||||
|
The background color will change to pink if the pinch is opening (Zoom In)
|
||||||
|
or changes to lightblue if the pinch is closing (Zoom out).
|
||||||
|
</div>
|
||||||
|
<!-- UI for logging/debugging -->
|
||||||
|
<button id="log" onclick="enableLog(event);">Start/Stop event logging</button>
|
||||||
|
<button id="clearlog" onclick="clearLog(event);">Clear the log</button>
|
||||||
|
<p></p>
|
||||||
|
<output></output>
|
||||||
|
|
||||||
|
<a href="https://server.alexmahr.de/calender">calender</a>
|
||||||
|
<h1>Webview</h1>
|
||||||
|
<pre id="output">output</pre>
|
||||||
|
<script>
|
||||||
|
window.addEventListener("error",(error)=>{
|
||||||
|
document.body.innerHTML = "<h1>error</h1><pre>" +
|
||||||
|
error.filename +
|
||||||
|
"\nline:" + error.lineno +
|
||||||
|
"\n"+error.message +"</pre>";
|
||||||
|
},false);
|
||||||
|
|
||||||
|
['touchstart','touchmove','touchend'].forEach((evname)=>{
|
||||||
|
window.addEventListener(evname,(ev)=>{
|
||||||
|
output.textContent+=evname+"\n" ;
|
||||||
|
ev.preventDefault();
|
||||||
|
},false);
|
||||||
|
});
|
||||||
|
window.addEventListener("load",()=>{
|
||||||
|
var count = localStorage.getItem("app-opened-count")|| 0;
|
||||||
|
count++;
|
||||||
|
localStorage.setItem("app-opened-count",count);
|
||||||
|
var h2 = document.createElement("h2");
|
||||||
|
h2.textContent = "Javascript works! (app was opened " + count + " times)";
|
||||||
|
h2.style.animation="wobble 1s ease-in-out 0s 1 forwards normal running"
|
||||||
|
document.body.appendChild(h2);
|
||||||
|
},false);
|
||||||
|
|
||||||
|
// Global vars to cache event state
|
||||||
|
const evCache = [];
|
||||||
|
let prevDiff = -1;
|
||||||
|
|
||||||
|
function init() {
|
||||||
|
// Install event handlers for the pointer target
|
||||||
|
const el = document.getElementById("target");
|
||||||
|
el.onpointerdown = pointerdownHandler;
|
||||||
|
el.onpointermove = pointermoveHandler;
|
||||||
|
|
||||||
|
// Use same handler for pointer{up,cancel,out,leave} events since
|
||||||
|
// the semantics for these events - in this app - are the same.
|
||||||
|
el.onpointerup = pointerupHandler;
|
||||||
|
el.onpointercancel = pointerupHandler;
|
||||||
|
el.onpointerout = pointerupHandler;
|
||||||
|
el.onpointerleave = pointerupHandler;
|
||||||
|
}
|
||||||
|
function pointerdownHandler(ev) {
|
||||||
|
// The pointerdown event signals the start of a touch interaction.
|
||||||
|
// This event is cached to support 2-finger gestures
|
||||||
|
evCache.push(ev);
|
||||||
|
log("pointerDown", ev);
|
||||||
|
}
|
||||||
|
function pointermoveHandler(ev) {
|
||||||
|
// This function implements a 2-pointer horizontal pinch/zoom gesture.
|
||||||
|
//
|
||||||
|
// If the distance between the two pointers has increased (zoom in),
|
||||||
|
// the target element's background is changed to "pink" and if the
|
||||||
|
// distance is decreasing (zoom out), the color is changed to "lightblue".
|
||||||
|
//
|
||||||
|
// This function sets the target element's border to "dashed" to visually
|
||||||
|
// indicate the pointer's target received a move event.
|
||||||
|
log("pointerMove", ev);
|
||||||
|
ev.target.style.border = "dashed";
|
||||||
|
|
||||||
|
// Find this event in the cache and update its record with this event
|
||||||
|
const index = evCache.findIndex(
|
||||||
|
(cachedEv) => cachedEv.pointerId === ev.pointerId,
|
||||||
|
);
|
||||||
|
evCache[index] = ev;
|
||||||
|
|
||||||
|
// If two pointers are down, check for pinch gestures
|
||||||
|
if (evCache.length === 2) {
|
||||||
|
// Calculate the distance between the two pointers
|
||||||
|
const curDiff = Math.abs(evCache[0].clientX - evCache[1].clientX);
|
||||||
|
|
||||||
|
if (prevDiff > 0) {
|
||||||
|
if (curDiff > prevDiff) {
|
||||||
|
// The distance between the two pointers has increased
|
||||||
|
log("Pinch moving OUT -> Zoom in", ev);
|
||||||
|
ev.target.style.background = "pink";
|
||||||
|
}
|
||||||
|
if (curDiff < prevDiff) {
|
||||||
|
// The distance between the two pointers has decreased
|
||||||
|
log("Pinch moving IN -> Zoom out", ev);
|
||||||
|
ev.target.style.background = "lightblue";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Cache the distance for the next move event
|
||||||
|
prevDiff = curDiff;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
function pointerupHandler(ev) {
|
||||||
|
log(ev.type, ev);
|
||||||
|
// Remove this pointer from the cache and reset the target's
|
||||||
|
// background and border
|
||||||
|
removeEvent(ev);
|
||||||
|
ev.target.style.background = "white";
|
||||||
|
ev.target.style.border = "1px solid black";
|
||||||
|
|
||||||
|
// If the number of pointers down is less than two then reset diff tracker
|
||||||
|
if (evCache.length < 2) {
|
||||||
|
prevDiff = -1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
function removeEvent(ev) {
|
||||||
|
// Remove this event from the target's cache
|
||||||
|
const index = evCache.findIndex(
|
||||||
|
(cachedEv) => cachedEv.pointerId === ev.pointerId,
|
||||||
|
);
|
||||||
|
evCache.splice(index, 1);
|
||||||
|
}
|
||||||
|
// Log events flag
|
||||||
|
let logEvents = false;
|
||||||
|
|
||||||
|
// Logging/debugging functions
|
||||||
|
function enableLog(ev) {
|
||||||
|
logEvents = !logEvents;
|
||||||
|
}
|
||||||
|
|
||||||
|
function log(prefix, ev) {
|
||||||
|
if (!logEvents) return;
|
||||||
|
const o = document.getElementsByTagName("output")[0];
|
||||||
|
o.innerText += `${prefix}:
|
||||||
|
pointerID = ${ev.pointerId}
|
||||||
|
pointerType = ${ev.pointerType}
|
||||||
|
isPrimary = ${ev.isPrimary}
|
||||||
|
`;
|
||||||
|
}
|
||||||
|
|
||||||
|
function clearLog(event) {
|
||||||
|
const o = document.getElementsByTagName("output")[0];
|
||||||
|
o.textContent = "";
|
||||||
|
}
|
||||||
|
|
||||||
|
</script>
|
||||||
|
</body>
|
||||||
|
</html>
|
105
app/assets/pinch.js
Normal file
105
app/assets/pinch.js
Normal file
|
@ -0,0 +1,105 @@
|
||||||
|
// Global vars to cache event state
|
||||||
|
const evCache = [];
|
||||||
|
let prevDiff = -1;
|
||||||
|
|
||||||
|
function init() {
|
||||||
|
// Install event handlers for the pointer target
|
||||||
|
const el = document.getElementById("target");
|
||||||
|
el.onpointerdown = pointerdownHandler;
|
||||||
|
el.onpointermove = pointermoveHandler;
|
||||||
|
|
||||||
|
// Use same handler for pointer{up,cancel,out,leave} events since
|
||||||
|
// the semantics for these events - in this app - are the same.
|
||||||
|
el.onpointerup = pointerupHandler;
|
||||||
|
el.onpointercancel = pointerupHandler;
|
||||||
|
el.onpointerout = pointerupHandler;
|
||||||
|
el.onpointerleave = pointerupHandler;
|
||||||
|
}
|
||||||
|
function pointerdownHandler(ev) {
|
||||||
|
// The pointerdown event signals the start of a touch interaction.
|
||||||
|
// This event is cached to support 2-finger gestures
|
||||||
|
evCache.push(ev);
|
||||||
|
log("pointerDown", ev);
|
||||||
|
}
|
||||||
|
function pointermoveHandler(ev) {
|
||||||
|
// This function implements a 2-pointer horizontal pinch/zoom gesture.
|
||||||
|
//
|
||||||
|
// If the distance between the two pointers has increased (zoom in),
|
||||||
|
// the target element's background is changed to "pink" and if the
|
||||||
|
// distance is decreasing (zoom out), the color is changed to "lightblue".
|
||||||
|
//
|
||||||
|
// This function sets the target element's border to "dashed" to visually
|
||||||
|
// indicate the pointer's target received a move event.
|
||||||
|
log("pointerMove", ev);
|
||||||
|
ev.target.style.border = "dashed";
|
||||||
|
|
||||||
|
// Find this event in the cache and update its record with this event
|
||||||
|
const index = evCache.findIndex(
|
||||||
|
(cachedEv) => cachedEv.pointerId === ev.pointerId,
|
||||||
|
);
|
||||||
|
evCache[index] = ev;
|
||||||
|
|
||||||
|
// If two pointers are down, check for pinch gestures
|
||||||
|
if (evCache.length === 2) {
|
||||||
|
// Calculate the distance between the two pointers
|
||||||
|
const curDiff = Math.abs(evCache[0].clientX - evCache[1].clientX);
|
||||||
|
|
||||||
|
if (prevDiff > 0) {
|
||||||
|
if (curDiff > prevDiff) {
|
||||||
|
// The distance between the two pointers has increased
|
||||||
|
log("Pinch moving OUT -> Zoom in", ev);
|
||||||
|
ev.target.style.background = "pink";
|
||||||
|
}
|
||||||
|
if (curDiff < prevDiff) {
|
||||||
|
// The distance between the two pointers has decreased
|
||||||
|
log("Pinch moving IN -> Zoom out", ev);
|
||||||
|
ev.target.style.background = "lightblue";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Cache the distance for the next move event
|
||||||
|
prevDiff = curDiff;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
function pointerupHandler(ev) {
|
||||||
|
log(ev.type, ev);
|
||||||
|
// Remove this pointer from the cache and reset the target's
|
||||||
|
// background and border
|
||||||
|
removeEvent(ev);
|
||||||
|
ev.target.style.background = "white";
|
||||||
|
ev.target.style.border = "1px solid black";
|
||||||
|
|
||||||
|
// If the number of pointers down is less than two then reset diff tracker
|
||||||
|
if (evCache.length < 2) {
|
||||||
|
prevDiff = -1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
function removeEvent(ev) {
|
||||||
|
// Remove this event from the target's cache
|
||||||
|
const index = evCache.findIndex(
|
||||||
|
(cachedEv) => cachedEv.pointerId === ev.pointerId,
|
||||||
|
);
|
||||||
|
evCache.splice(index, 1);
|
||||||
|
}
|
||||||
|
// Log events flag
|
||||||
|
let logEvents = false;
|
||||||
|
|
||||||
|
// Logging/debugging functions
|
||||||
|
function enableLog(ev) {
|
||||||
|
logEvents = !logEvents;
|
||||||
|
}
|
||||||
|
|
||||||
|
function log(prefix, ev) {
|
||||||
|
if (!logEvents) return;
|
||||||
|
const o = document.getElementsByTagName("output")[0];
|
||||||
|
o.innerText += `${prefix}:
|
||||||
|
pointerID = ${ev.pointerId}
|
||||||
|
pointerType = ${ev.pointerType}
|
||||||
|
isPrimary = ${ev.isPrimary}
|
||||||
|
`;
|
||||||
|
}
|
||||||
|
|
||||||
|
function clearLog(event) {
|
||||||
|
const o = document.getElementsByTagName("output")[0];
|
||||||
|
o.textContent = "";
|
||||||
|
}
|
|
@ -36,7 +36,11 @@ RUN <<EOF
|
||||||
cat > /bin/makefile-bash-wrapper.sh << 'WRAPPER'
|
cat > /bin/makefile-bash-wrapper.sh << 'WRAPPER'
|
||||||
#!/bin/bash
|
#!/bin/bash
|
||||||
printf $'\033[0;32m''#----------------------------------------\n'$'\033[0m' >&2
|
printf $'\033[0;32m''#----------------------------------------\n'$'\033[0m' >&2
|
||||||
bash "$@"
|
bash -e "$@" || {
|
||||||
|
EXITCODE=$?
|
||||||
|
printf $'\033[0;31m''ERROR EXITCODE='"$EXITCODE"'\n'$'\033[0m' >&2
|
||||||
|
exit $EXITCODE
|
||||||
|
}
|
||||||
printf '\n\n\n\n' >&2
|
printf '\n\n\n\n' >&2
|
||||||
WRAPPER
|
WRAPPER
|
||||||
chmod u+x /bin/makefile-bash-wrapper.sh
|
chmod u+x /bin/makefile-bash-wrapper.sh
|
||||||
|
@ -44,6 +48,7 @@ EOF
|
||||||
DOCKERFILEEOF
|
DOCKERFILEEOF
|
||||||
}
|
}
|
||||||
|
|
||||||
|
printf $'\033[0;33m'"$(date -Iseconds) starting build"'$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$\n'$'\033[0m'
|
||||||
diff Dockerfile <(DockerfileContent) 2>/dev/null > /dev/null || {
|
diff Dockerfile <(DockerfileContent) 2>/dev/null > /dev/null || {
|
||||||
test -f Dockerfile && {
|
test -f Dockerfile && {
|
||||||
read -p 'reset/start Dockerfile[Y/n]' YES
|
read -p 'reset/start Dockerfile[Y/n]' YES
|
||||||
|
|
BIN
screenshots/screenshot.01.avif
Normal file
BIN
screenshots/screenshot.01.avif
Normal file
Binary file not shown.
After Width: | Height: | Size: 3.8 KiB |
Loading…
Add table
Reference in a new issue