mirror of
https://gitlab.com/lecarore/breakout71.git
synced 2025-04-20 12:15:06 -04:00
Added save mechanic
This commit is contained in:
parent
7aff5be9cd
commit
659d79bcd0
23 changed files with 333 additions and 20292 deletions
|
@ -11,8 +11,8 @@ android {
|
||||||
applicationId = "me.lecaro.breakout"
|
applicationId = "me.lecaro.breakout"
|
||||||
minSdk = 21
|
minSdk = 21
|
||||||
targetSdk = 34
|
targetSdk = 34
|
||||||
versionCode = 29035871
|
versionCode = 29036807
|
||||||
versionName = "29035871"
|
versionName = "29036807"
|
||||||
testInstrumentationRunner = "androidx.test.runner.AndroidJUnitRunner"
|
testInstrumentationRunner = "androidx.test.runner.AndroidJUnitRunner"
|
||||||
vectorDrawables {
|
vectorDrawables {
|
||||||
useSupportLibrary = true
|
useSupportLibrary = true
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
<?xml version="1.0" encoding ="utf-8"?>
|
<?xml version="1.0" encoding ="utf-8"?>
|
||||||
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
|
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
|
||||||
xmlns:tools="http://schemas.android.com/tools">
|
xmlns:tools="http://schemas.android.com/tools">
|
||||||
|
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
|
||||||
<application
|
<application
|
||||||
android:allowBackup="true"
|
android:allowBackup="true"
|
||||||
android:dataExtractionRules="@xml/data_extraction_rules"
|
android:dataExtractionRules="@xml/data_extraction_rules"
|
||||||
|
|
File diff suppressed because one or more lines are too long
|
@ -1,13 +1,40 @@
|
||||||
package me.lecaro.breakout
|
package me.lecaro.breakout
|
||||||
|
import android.app.Activity
|
||||||
|
import android.app.DownloadManager
|
||||||
|
import android.content.Context
|
||||||
|
import android.content.Intent
|
||||||
|
import android.net.Uri
|
||||||
import android.os.Bundle
|
import android.os.Bundle
|
||||||
|
import android.os.Environment
|
||||||
import android.util.Log
|
import android.util.Log
|
||||||
import android.view.Window
|
import android.view.Window
|
||||||
import android.view.WindowManager
|
import android.view.WindowManager
|
||||||
import android.webkit.ConsoleMessage
|
import android.webkit.ConsoleMessage
|
||||||
|
import android.webkit.DownloadListener
|
||||||
|
import android.webkit.ValueCallback
|
||||||
import android.webkit.WebChromeClient
|
import android.webkit.WebChromeClient
|
||||||
import android.webkit.WebView
|
import android.webkit.WebView
|
||||||
|
import android.widget.Toast
|
||||||
|
import java.io.File
|
||||||
|
import java.text.SimpleDateFormat
|
||||||
|
import java.util.Date
|
||||||
|
|
||||||
|
const val CHOOSE_FILE_REQUEST_CODE = 548459
|
||||||
class MainActivity : android.app.Activity() {
|
class MainActivity : android.app.Activity() {
|
||||||
|
|
||||||
|
override fun onActivityResult(requestCode: Int, resultCode: Int, data: Intent?) {
|
||||||
|
|
||||||
|
super.onActivityResult(requestCode, resultCode, data)
|
||||||
|
when (requestCode) {
|
||||||
|
CHOOSE_FILE_REQUEST_CODE -> {
|
||||||
|
if (resultCode == RESULT_OK) {
|
||||||
|
filePathCallback?.onReceiveValue(WebChromeClient.FileChooserParams.parseResult(resultCode, data))
|
||||||
|
filePathCallback = null
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
var filePathCallback: ValueCallback<Array<Uri>>? = null
|
||||||
override fun onCreate(savedInstanceState: Bundle?) {
|
override fun onCreate(savedInstanceState: Bundle?) {
|
||||||
super.onCreate(savedInstanceState)
|
super.onCreate(savedInstanceState)
|
||||||
requestWindowFeature(Window.FEATURE_NO_TITLE);
|
requestWindowFeature(Window.FEATURE_NO_TITLE);
|
||||||
|
@ -15,11 +42,13 @@ class MainActivity : android.app.Activity() {
|
||||||
WindowManager.LayoutParams.FLAG_FULLSCREEN,
|
WindowManager.LayoutParams.FLAG_FULLSCREEN,
|
||||||
WindowManager.LayoutParams.FLAG_FULLSCREEN
|
WindowManager.LayoutParams.FLAG_FULLSCREEN
|
||||||
);
|
);
|
||||||
// WebView.setWebContentsDebuggingEnabled(true)
|
|
||||||
val webView = WebView(this)
|
val webView = WebView(this)
|
||||||
webView.settings.javaScriptEnabled = true
|
webView.settings.javaScriptEnabled = true
|
||||||
webView.settings.domStorageEnabled = true
|
webView.settings.domStorageEnabled = true
|
||||||
|
webView.settings.setSupportZoom(false)
|
||||||
webView.loadUrl("file:///android_asset/index.html?isInWebView=true")
|
webView.loadUrl("file:///android_asset/index.html?isInWebView=true")
|
||||||
|
|
||||||
|
|
||||||
webView.webChromeClient = object : WebChromeClient() {
|
webView.webChromeClient = object : WebChromeClient() {
|
||||||
override fun onConsoleMessage(consoleMessage: ConsoleMessage): Boolean {
|
override fun onConsoleMessage(consoleMessage: ConsoleMessage): Boolean {
|
||||||
Log.d(
|
Log.d(
|
||||||
|
@ -28,7 +57,46 @@ class MainActivity : android.app.Activity() {
|
||||||
)
|
)
|
||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
|
override fun onShowFileChooser(webView: WebView?, filePathCallback: ValueCallback<Array<Uri>>?, fileChooserParams: FileChooserParams?): Boolean {
|
||||||
|
startActivityForResult(fileChooserParams?.createIntent(), CHOOSE_FILE_REQUEST_CODE)
|
||||||
|
this@MainActivity.filePathCallback = filePathCallback
|
||||||
|
return true
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
webView.setDownloadListener(DownloadListener { url, userAgent, contentDisposition, mimetype, contentLength ->
|
||||||
|
|
||||||
|
if (!url.startsWith("data:")) {
|
||||||
|
Log.w("DL","url ignored because it does not start with data:")
|
||||||
|
return@DownloadListener
|
||||||
|
}
|
||||||
|
val sdf = SimpleDateFormat("yyyy-M-dd-hh-mm")
|
||||||
|
val currentDate = sdf.format(Date())
|
||||||
|
// Extract filename from contentDisposition if available
|
||||||
|
|
||||||
|
if (url.startsWith("data:application/json;base64,")) {
|
||||||
|
Log.d("DL","saving application/json ")
|
||||||
|
val base64Data = url.substringAfterLast(',')
|
||||||
|
val decodedBytes = android.util.Base64.decode(base64Data, android.util.Base64.DEFAULT)
|
||||||
|
val jsonData = String(decodedBytes)
|
||||||
|
;
|
||||||
|
val dir = Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_DOWNLOADS)
|
||||||
|
val fileName = "breakout-71-save-$currentDate.b71"
|
||||||
|
val file = File(dir, fileName)
|
||||||
|
file.writeText(jsonData)
|
||||||
|
Toast.makeText(this, "Saved in $dir", Toast. LENGTH_LONG).show()
|
||||||
|
Log.d("DL","finished saving application/json ")
|
||||||
|
|
||||||
|
}else if (url.startsWith("data:video/webm;base64,")){
|
||||||
|
Log.d("DL","saving video/webm ")
|
||||||
|
// TODO
|
||||||
|
Log.d("DL","finished savign video/webm ")
|
||||||
|
}else{
|
||||||
|
Log.w("DL","unexpected type "+url)
|
||||||
|
}
|
||||||
|
|
||||||
|
})
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
setContentView(webView)
|
setContentView(webView)
|
||||||
}
|
}
|
||||||
|
|
2
dist/PWA/sw-b71.js
vendored
2
dist/PWA/sw-b71.js
vendored
|
@ -1,2 +1,2 @@
|
||||||
function e(e,t,n,r,a,i,c){try{var o=e[i](c),u=o.value}catch(e){n(e);return}o.done?t(u):Promise.resolve(u).then(r,a)}function t(t){return function(){var n=this,r=arguments;return new Promise(function(a,i){var c=t.apply(n,r);function o(t){e(c,a,i,o,u,"next",t)}function u(t){e(c,a,i,o,u,"throw",t)}o(void 0)})}}function n(e,t){var n,r,a,i,c={label:0,sent:function(){if(1&a[0])throw a[1];return a[1]},trys:[],ops:[]};return i={next:o(0),throw:o(1),return:o(2)},"function"==typeof Symbol&&(i[Symbol.iterator]=function(){return this}),i;function o(i){return function(o){return function(i){if(n)throw TypeError("Generator is already executing.");for(;c;)try{if(n=1,r&&(a=2&i[0]?r.return:i[0]?r.throw||((a=r.return)&&a.call(r),0):r.next)&&!(a=a.call(r,i[1])).done)return a;switch(r=0,a&&(i=[2&i[0],a.value]),i[0]){case 0:case 1:a=i;break;case 4:return c.label++,{value:i[1],done:!1};case 5:c.label++,r=i[1],i=[0];continue;case 7:i=c.ops.pop(),c.trys.pop();continue;default:if(!(a=(a=c.trys).length>0&&a[a.length-1])&&(6===i[0]||2===i[0])){c=0;continue}if(3===i[0]&&(!a||i[1]>a[0]&&i[1]<a[3])){c.label=i[1];break}if(6===i[0]&&c.label<a[1]){c.label=a[1],a=i;break}if(a&&c.label<a[2]){c.label=a[2],c.ops.push(i);break}a[2]&&c.ops.pop(),c.trys.pop();continue}i=t.call(e,c)}catch(e){i=[6,e],r=0}finally{n=a=0}if(5&i[0])throw i[1];return{value:i[0]?i[1]:void 0,done:!0}}([i,o])}}}var r="breakout-71-".concat("29035871"),a=["/"];self.addEventListener("install",function(e){e.waitUntil(t(function(){return n(this,function(e){switch(e.label){case 0:return[4,caches.open(r)];case 1:return e.sent().addAll(a),[2]}})})())}),self.addEventListener("activate",function(e){e.waitUntil(t(function(){return n(this,function(e){switch(e.label){case 0:return[4,caches.keys()];case 1:return[4,Promise.all(e.sent().map(function(e){if(e!==r)return caches.delete(e)}))];case 2:return e.sent(),[4,clients.claim()];case 3:return e.sent(),[2]}})})())}),self.addEventListener("fetch",function(e){if("navigate"===e.request.mode&&e.request.url.endsWith("/index.html?isPWA=true")){e.respondWith(caches.match("/"));return}});
|
function e(e,t,n,r,a,i,c){try{var o=e[i](c),u=o.value}catch(e){n(e);return}o.done?t(u):Promise.resolve(u).then(r,a)}function t(t){return function(){var n=this,r=arguments;return new Promise(function(a,i){var c=t.apply(n,r);function o(t){e(c,a,i,o,u,"next",t)}function u(t){e(c,a,i,o,u,"throw",t)}o(void 0)})}}function n(e,t){var n,r,a,i,c={label:0,sent:function(){if(1&a[0])throw a[1];return a[1]},trys:[],ops:[]};return i={next:o(0),throw:o(1),return:o(2)},"function"==typeof Symbol&&(i[Symbol.iterator]=function(){return this}),i;function o(i){return function(o){return function(i){if(n)throw TypeError("Generator is already executing.");for(;c;)try{if(n=1,r&&(a=2&i[0]?r.return:i[0]?r.throw||((a=r.return)&&a.call(r),0):r.next)&&!(a=a.call(r,i[1])).done)return a;switch(r=0,a&&(i=[2&i[0],a.value]),i[0]){case 0:case 1:a=i;break;case 4:return c.label++,{value:i[1],done:!1};case 5:c.label++,r=i[1],i=[0];continue;case 7:i=c.ops.pop(),c.trys.pop();continue;default:if(!(a=(a=c.trys).length>0&&a[a.length-1])&&(6===i[0]||2===i[0])){c=0;continue}if(3===i[0]&&(!a||i[1]>a[0]&&i[1]<a[3])){c.label=i[1];break}if(6===i[0]&&c.label<a[1]){c.label=a[1],a=i;break}if(a&&c.label<a[2]){c.label=a[2],c.ops.push(i);break}a[2]&&c.ops.pop(),c.trys.pop();continue}i=t.call(e,c)}catch(e){i=[6,e],r=0}finally{n=a=0}if(5&i[0])throw i[1];return{value:i[0]?i[1]:void 0,done:!0}}([i,o])}}}var r="breakout-71-".concat("29036807"),a=["/"];self.addEventListener("install",function(e){e.waitUntil(t(function(){return n(this,function(e){switch(e.label){case 0:return[4,caches.open(r)];case 1:return e.sent().addAll(a),[2]}})})())}),self.addEventListener("activate",function(e){e.waitUntil(t(function(){return n(this,function(e){switch(e.label){case 0:return[4,caches.keys()];case 1:return[4,Promise.all(e.sent().map(function(e){if(e!==r)return caches.delete(e)}))];case 2:return e.sent(),[4,clients.claim()];case 3:return e.sent(),[2]}})})())}),self.addEventListener("fetch",function(e){if("navigate"===e.request.mode&&e.request.url.endsWith("/index.html?isPWA=true")){e.respondWith(caches.match("/"));return}});
|
||||||
//# sourceMappingURL=sw-b71.js.map
|
//# sourceMappingURL=sw-b71.js.map
|
||||||
|
|
2
dist/PWA/sw-b71.js.map
vendored
2
dist/PWA/sw-b71.js.map
vendored
File diff suppressed because one or more lines are too long
209
dist/editor.1350aee5.js
vendored
209
dist/editor.1350aee5.js
vendored
File diff suppressed because one or more lines are too long
1
dist/editor.1350aee5.js.map
vendored
1
dist/editor.1350aee5.js.map
vendored
File diff suppressed because one or more lines are too long
16297
dist/editor.1ec04b8f.js
vendored
16297
dist/editor.1ec04b8f.js
vendored
File diff suppressed because it is too large
Load diff
1
dist/editor.1ec04b8f.js.map
vendored
1
dist/editor.1ec04b8f.js.map
vendored
File diff suppressed because one or more lines are too long
56
dist/editor.9680328c.css
vendored
56
dist/editor.9680328c.css
vendored
|
@ -1,56 +0,0 @@
|
||||||
body {
|
|
||||||
color: #fff;
|
|
||||||
background: #000;
|
|
||||||
}
|
|
||||||
|
|
||||||
#palette {
|
|
||||||
width: 80px;
|
|
||||||
position: fixed;
|
|
||||||
top: 0;
|
|
||||||
bottom: 0;
|
|
||||||
right: 0;
|
|
||||||
overflow: auto;
|
|
||||||
}
|
|
||||||
|
|
||||||
#palette button.active {
|
|
||||||
transform: scale(1.2);
|
|
||||||
}
|
|
||||||
|
|
||||||
#levels {
|
|
||||||
flex-wrap: wrap;
|
|
||||||
align-items: flex-start;
|
|
||||||
gap: 40px;
|
|
||||||
margin-right: 80px;
|
|
||||||
display: flex;
|
|
||||||
}
|
|
||||||
|
|
||||||
#levels .level-bricks-preview {
|
|
||||||
position: relative;
|
|
||||||
}
|
|
||||||
|
|
||||||
#levels input[type="number"] {
|
|
||||||
width: 50px;
|
|
||||||
}
|
|
||||||
|
|
||||||
#levels > div {
|
|
||||||
grid-template-columns: auto auto;
|
|
||||||
grid-template-areas: ". name"
|
|
||||||
"buttons bricks";
|
|
||||||
display: grid;
|
|
||||||
}
|
|
||||||
|
|
||||||
#levels > div > :first-child {
|
|
||||||
grid-area: name;
|
|
||||||
}
|
|
||||||
|
|
||||||
#levels > div > div:nth-child(2) {
|
|
||||||
flex-direction: column;
|
|
||||||
grid-area: buttons;
|
|
||||||
align-items: flex-end;
|
|
||||||
display: flex;
|
|
||||||
}
|
|
||||||
|
|
||||||
#levels > div > div:nth-child(3) {
|
|
||||||
grid-area: bricks;
|
|
||||||
}
|
|
||||||
/*# sourceMappingURL=editor.9680328c.css.map */
|
|
1
dist/editor.9680328c.css.map
vendored
1
dist/editor.9680328c.css.map
vendored
|
@ -1 +0,0 @@
|
||||||
{"mappings":"AAAA;;;;;AAKA;;;;;;;;;AAAA;;;;AAaA;;;;;;;;AAAA;;;;AAAA;;;;AAcE;;;;;;;AAKE;;;;AAIA;;;;;;;AAOA","sources":["src/level_editor/levels_editor.less"],"sourcesContent":["body {\n background: black;\n color: white;\n}\n\n#palette {\n position: fixed;\n top: 0;\n right: 0;\n width: 80px;\n bottom: 0;\n overflow: auto;\n\n button.active {\n transform: scale(1.2);\n }\n}\n\n#levels {\n display: flex;\n gap: 40px;\n align-items: flex-start;\n flex-wrap: wrap;\n margin-right: 80px;\n\n .level-bricks-preview {\n position: relative;\n }\n input[type=\"number\"] {\n width: 50px;\n }\n\n & > div {\n display: grid;\n grid-template-columns: auto auto;\n grid-template-areas: \". name\" \"buttons bricks\";\n\n & > *:nth-child(1) {\n grid-area: name;\n }\n\n & > div:nth-child(2) {\n grid-area: buttons;\n display: flex;\n flex-direction: column;\n align-items: flex-end;\n }\n\n & > div:nth-child(3) {\n grid-area: bricks;\n }\n }\n}\n"],"names":[],"version":3,"file":"editor.9680328c.css.map","sourceRoot":"/__parcel_source_root/"}
|
|
14
dist/editor.html
vendored
14
dist/editor.html
vendored
|
@ -1,14 +0,0 @@
|
||||||
<!doctype html>
|
|
||||||
<html lang="en">
|
|
||||||
<head><script src="/editor.1350aee5.js"></script>
|
|
||||||
<meta charset="UTF-8">
|
|
||||||
<title>Level editor</title>
|
|
||||||
<link rel="icon" href="data:image/svg+xml,<svg xmlns=%22http://www.w3.org/2000/svg%22 viewBox=%220 0 100 100%22><text y=%22.9em%22 font-size=%2290%22>🔨</text></svg>">
|
|
||||||
<link rel="stylesheet" href="/editor.9680328c.css">
|
|
||||||
</head>
|
|
||||||
<body>
|
|
||||||
<div id="app"></div>
|
|
||||||
|
|
||||||
<script src="/editor.1ec04b8f.js" defer=""></script>
|
|
||||||
</body>
|
|
||||||
</html>
|
|
3687
dist/index.html
vendored
3687
dist/index.html
vendored
File diff suppressed because one or more lines are too long
|
@ -1,5 +1,5 @@
|
||||||
// The version of the cache.
|
// The version of the cache.
|
||||||
const VERSION = "29035871";
|
const VERSION = "29036807";
|
||||||
|
|
||||||
// The name of the cache
|
// The name of the cache
|
||||||
const CACHE_NAME = `breakout-71-${VERSION}`;
|
const CACHE_NAME = `breakout-71-${VERSION}`;
|
||||||
|
|
|
@ -1 +1 @@
|
||||||
"29035871"
|
"29036807"
|
||||||
|
|
121
src/game.ts
121
src/game.ts
|
@ -52,12 +52,6 @@ import {
|
||||||
} from "./asyncAlert";
|
} from "./asyncAlert";
|
||||||
import { isOptionOn, options, toggleOption } from "./options";
|
import { isOptionOn, options, toggleOption } from "./options";
|
||||||
|
|
||||||
bombSVG.src =
|
|
||||||
"data:image/svg+xml;base64," +
|
|
||||||
btoa(`<svg width="144" height="144" viewBox="0 0 38.101 38.099" xmlns="http://www.w3.org/2000/svg">
|
|
||||||
<path d="m6.1528 26.516c-2.6992-3.4942-2.9332-8.281-.58305-11.981a10.454 10.454 0 017.3701-4.7582c1.962-.27726 4.1646.05953 5.8835.90027l.45013.22017.89782-.87417c.83748-.81464.91169-.87499 1.0992-.90271.40528-.058713.58876.03425 1.1971.6116l.55451.52679 1.0821-1.0821c1.1963-1.1963 1.383-1.3357 2.1039-1.5877.57898-.20223 1.5681-.19816 2.1691.00897 1.4613.50314 2.3673 1.7622 2.3567 3.2773-.0058.95654-.24464 1.5795-.90924 2.3746-.40936.48928-.55533.81057-.57898 1.2737-.02039.41018.1109.77714.42322 1.1792.30172.38816.3694.61323.2797.93044-.12803.45666-.56674.71598-1.0242.60507-.601-.14597-1.3031-1.3088-1.3969-2.3126-.09459-1.0161.19245-1.8682.92392-2.7432.42567-.50885.5643-.82851.5643-1.3031 0-.50151-.14026-.83177-.51211-1.2028-.50966-.50966-1.0968-.64829-1.781-.41996l-.37348.12477-2.1006 2.1006.52597.55696c.45421.48194.5325.58876.57898.78855.09622.41588.07502.45014-.88396 1.4548l-.87173.9125.26339.57979a10.193 10.193 0 01.9231 4.1001c.03996 2.046-.41996 3.8082-1.4442 5.537-.55044.928-1.0185 1.5013-1.8968 2.3241-.83503.78284-1.5526 1.2827-2.4904 1.7361-3.4266 1.657-7.4721 1.3422-10.549-.82035-.73473-.51782-1.7312-1.4621-2.2515-2.1357zm21.869-4.5584c-.0579-.19734-.05871-2.2662 0-2.4545.11906-.39142.57898-.63361 1.0038-.53005.23812.05708.54147.32455.6116.5382.06279.19163.06769 2.1805.0065 2.3811-.12558.40773-.61649.67602-1.0462.57164-.234-.05708-.51615-.30498-.57568-.50722m3.0417-2.6013c-.12313-.6222.37837-1.1049 1.0479-1.0079.18348.0261.25279.08399 1.0071.83911.75838.75838.81301.82362.84074 1.0112.10193.68499-.40365 1.1938-1.034 1.0405-.1949-.0473-.28786-.12558-1.0144-.85216-.7649-.76409-.80241-.81057-.84645-1.0316m.61323-3.0629a.85623.85623 0 01.59284-.99975c.28949-.09214 2.1814-.08318 2.3917.01141.38734.17369.6279.61078.53984.98181-.06035.25606-.35391.57327-.60181.64992-.25279.07747-2.2278.053-2.4097-.03017-.26013-.11906-.46318-.36125-.51374-.61323" fill="#fff" opacity="0.3"/>
|
|
||||||
</svg>`);
|
|
||||||
|
|
||||||
export function play() {
|
export function play() {
|
||||||
if (gameState.running) return;
|
if (gameState.running) return;
|
||||||
gameState.running = true;
|
gameState.running = true;
|
||||||
|
@ -261,8 +255,8 @@ gameCanvas.addEventListener("mouseup", (e) => {
|
||||||
pause(true);
|
pause(true);
|
||||||
} else {
|
} else {
|
||||||
play();
|
play();
|
||||||
if (isOptionOn("pointerLock")) {
|
if (isOptionOn("pointerLock") && gameCanvas.requestPointerLock) {
|
||||||
gameCanvas.requestPointerLock();
|
gameCanvas.requestPointerLock().then();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
@ -543,7 +537,6 @@ async function openSettingsPanel() {
|
||||||
for (const key of Object.keys(options) as OptionId[]) {
|
for (const key of Object.keys(options) as OptionId[]) {
|
||||||
if (options[key])
|
if (options[key])
|
||||||
actions.push({
|
actions.push({
|
||||||
disabled: options[key].disabled(),
|
|
||||||
icon: isOptionOn(key)
|
icon: isOptionOn(key)
|
||||||
? icons["icon:checkmark_checked"]
|
? icons["icon:checkmark_checked"]
|
||||||
: icons["icon:checkmark_unchecked"],
|
: icons["icon:checkmark_unchecked"],
|
||||||
|
@ -655,6 +648,116 @@ async function openSettingsPanel() {
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
|
|
||||||
|
actions.push({
|
||||||
|
text: t("main_menu.download_save_file"),
|
||||||
|
help: t("main_menu.download_save_file_help"),
|
||||||
|
async value() {
|
||||||
|
const localStorageContent: Record<string, string> = {};
|
||||||
|
|
||||||
|
for (let i = 0; i < localStorage.length; i++) {
|
||||||
|
const key = localStorage.key(i) as string;
|
||||||
|
const value = localStorage.getItem(key) as string;
|
||||||
|
|
||||||
|
// Store the key-value pair in the object
|
||||||
|
localStorageContent[key] = value;
|
||||||
|
}
|
||||||
|
|
||||||
|
const dlLink = document.createElement("a");
|
||||||
|
|
||||||
|
dlLink.setAttribute(
|
||||||
|
"href",
|
||||||
|
"data:application/json;base64," +
|
||||||
|
btoa(
|
||||||
|
JSON.stringify({
|
||||||
|
fileType: "B71-save-file",
|
||||||
|
appVersion,
|
||||||
|
localStorageContent,
|
||||||
|
}),
|
||||||
|
),
|
||||||
|
);
|
||||||
|
|
||||||
|
dlLink.setAttribute(
|
||||||
|
"download",
|
||||||
|
"b71-save-" +
|
||||||
|
new Date()
|
||||||
|
.toISOString()
|
||||||
|
.slice(0, 19)
|
||||||
|
.replace(/[^0-9]+/gi, "-") +
|
||||||
|
".b71",
|
||||||
|
);
|
||||||
|
document.body.appendChild(dlLink);
|
||||||
|
dlLink.click();
|
||||||
|
setTimeout(() => document.body.removeChild(dlLink), 1000);
|
||||||
|
},
|
||||||
|
});
|
||||||
|
|
||||||
|
actions.push({
|
||||||
|
text: t("main_menu.load_save_file"),
|
||||||
|
help: t("main_menu.load_save_file_help"),
|
||||||
|
async value() {
|
||||||
|
if (!document.getElementById("save_file_picker")) {
|
||||||
|
let input: HTMLInputElement = document.createElement("input");
|
||||||
|
input.setAttribute("type", "file");
|
||||||
|
input.setAttribute("id", "save_file_picker");
|
||||||
|
input.setAttribute("accept", ".b71");
|
||||||
|
input.style.position = "absolute";
|
||||||
|
input.style.left = "-1000px";
|
||||||
|
input.addEventListener("change", async (e) => {
|
||||||
|
try {
|
||||||
|
const file = input && input.files?.item(0);
|
||||||
|
if (file) {
|
||||||
|
const content = await new Promise<string>((resolve, reject) => {
|
||||||
|
const reader = new FileReader();
|
||||||
|
reader.onload = function () {
|
||||||
|
resolve(reader.result?.toString() || "");
|
||||||
|
};
|
||||||
|
reader.onerror = function () {
|
||||||
|
reject(reader.error);
|
||||||
|
};
|
||||||
|
|
||||||
|
// Read the file as a text string
|
||||||
|
|
||||||
|
reader.readAsText(file);
|
||||||
|
});
|
||||||
|
const {
|
||||||
|
fileType,
|
||||||
|
appVersion: fileVersion,
|
||||||
|
localStorageContent,
|
||||||
|
} = JSON.parse(content);
|
||||||
|
if (fileType !== "B71-save-file")
|
||||||
|
throw new Error("Not a B71 save file");
|
||||||
|
if (fileVersion > appVersion)
|
||||||
|
throw new Error(
|
||||||
|
"Please update your app first, this file is for version " +
|
||||||
|
fileVersion +
|
||||||
|
" or newer.",
|
||||||
|
);
|
||||||
|
localStorage.clear();
|
||||||
|
for (let key in localStorageContent) {
|
||||||
|
localStorage.setItem(key, localStorageContent[key]);
|
||||||
|
}
|
||||||
|
await asyncAlert({
|
||||||
|
title: t("main_menu.save_file_loaded"),
|
||||||
|
text: t("main_menu.save_file_loaded_help"),
|
||||||
|
actions: [{ text: t("main_menu.save_file_loaded_ok") }],
|
||||||
|
});
|
||||||
|
window.location.reload();
|
||||||
|
}
|
||||||
|
} catch (e: any) {
|
||||||
|
await asyncAlert({
|
||||||
|
title: t("main_menu.save_file_error"),
|
||||||
|
text: e.message,
|
||||||
|
actions: [{ text: t("main_menu.save_file_loaded_ok") }],
|
||||||
|
});
|
||||||
|
}
|
||||||
|
input.value = "";
|
||||||
|
});
|
||||||
|
document.body.appendChild(input);
|
||||||
|
}
|
||||||
|
document.getElementById("save_file_picker")?.click();
|
||||||
|
},
|
||||||
|
});
|
||||||
|
|
||||||
actions.push({
|
actions.push({
|
||||||
text: t("main_menu.language"),
|
text: t("main_menu.language"),
|
||||||
help: t("main_menu.language_help"),
|
help: t("main_menu.language_help"),
|
||||||
|
|
|
@ -622,6 +622,36 @@
|
||||||
</translation>
|
</translation>
|
||||||
</translations>
|
</translations>
|
||||||
</concept_node>
|
</concept_node>
|
||||||
|
<concept_node>
|
||||||
|
<name>download_save_file</name>
|
||||||
|
<description/>
|
||||||
|
<comment/>
|
||||||
|
<translations>
|
||||||
|
<translation>
|
||||||
|
<language>en-US</language>
|
||||||
|
<approved>false</approved>
|
||||||
|
</translation>
|
||||||
|
<translation>
|
||||||
|
<language>fr-FR</language>
|
||||||
|
<approved>false</approved>
|
||||||
|
</translation>
|
||||||
|
</translations>
|
||||||
|
</concept_node>
|
||||||
|
<concept_node>
|
||||||
|
<name>download_save_file_help</name>
|
||||||
|
<description/>
|
||||||
|
<comment/>
|
||||||
|
<translations>
|
||||||
|
<translation>
|
||||||
|
<language>en-US</language>
|
||||||
|
<approved>false</approved>
|
||||||
|
</translation>
|
||||||
|
<translation>
|
||||||
|
<language>fr-FR</language>
|
||||||
|
<approved>false</approved>
|
||||||
|
</translation>
|
||||||
|
</translations>
|
||||||
|
</concept_node>
|
||||||
<concept_node>
|
<concept_node>
|
||||||
<name>footer_html</name>
|
<name>footer_html</name>
|
||||||
<description/>
|
<description/>
|
||||||
|
@ -757,6 +787,36 @@
|
||||||
</translation>
|
</translation>
|
||||||
</translations>
|
</translations>
|
||||||
</concept_node>
|
</concept_node>
|
||||||
|
<concept_node>
|
||||||
|
<name>load_save_file</name>
|
||||||
|
<description/>
|
||||||
|
<comment/>
|
||||||
|
<translations>
|
||||||
|
<translation>
|
||||||
|
<language>en-US</language>
|
||||||
|
<approved>false</approved>
|
||||||
|
</translation>
|
||||||
|
<translation>
|
||||||
|
<language>fr-FR</language>
|
||||||
|
<approved>false</approved>
|
||||||
|
</translation>
|
||||||
|
</translations>
|
||||||
|
</concept_node>
|
||||||
|
<concept_node>
|
||||||
|
<name>load_save_file_help</name>
|
||||||
|
<description/>
|
||||||
|
<comment/>
|
||||||
|
<translations>
|
||||||
|
<translation>
|
||||||
|
<language>en-US</language>
|
||||||
|
<approved>false</approved>
|
||||||
|
</translation>
|
||||||
|
<translation>
|
||||||
|
<language>fr-FR</language>
|
||||||
|
<approved>false</approved>
|
||||||
|
</translation>
|
||||||
|
</translations>
|
||||||
|
</concept_node>
|
||||||
<concept_node>
|
<concept_node>
|
||||||
<name>mobile</name>
|
<name>mobile</name>
|
||||||
<description/>
|
<description/>
|
||||||
|
@ -967,6 +1027,66 @@
|
||||||
</translation>
|
</translation>
|
||||||
</translations>
|
</translations>
|
||||||
</concept_node>
|
</concept_node>
|
||||||
|
<concept_node>
|
||||||
|
<name>save_file_error</name>
|
||||||
|
<description/>
|
||||||
|
<comment/>
|
||||||
|
<translations>
|
||||||
|
<translation>
|
||||||
|
<language>en-US</language>
|
||||||
|
<approved>false</approved>
|
||||||
|
</translation>
|
||||||
|
<translation>
|
||||||
|
<language>fr-FR</language>
|
||||||
|
<approved>false</approved>
|
||||||
|
</translation>
|
||||||
|
</translations>
|
||||||
|
</concept_node>
|
||||||
|
<concept_node>
|
||||||
|
<name>save_file_loaded</name>
|
||||||
|
<description/>
|
||||||
|
<comment/>
|
||||||
|
<translations>
|
||||||
|
<translation>
|
||||||
|
<language>en-US</language>
|
||||||
|
<approved>false</approved>
|
||||||
|
</translation>
|
||||||
|
<translation>
|
||||||
|
<language>fr-FR</language>
|
||||||
|
<approved>false</approved>
|
||||||
|
</translation>
|
||||||
|
</translations>
|
||||||
|
</concept_node>
|
||||||
|
<concept_node>
|
||||||
|
<name>save_file_loaded_help</name>
|
||||||
|
<description/>
|
||||||
|
<comment/>
|
||||||
|
<translations>
|
||||||
|
<translation>
|
||||||
|
<language>en-US</language>
|
||||||
|
<approved>false</approved>
|
||||||
|
</translation>
|
||||||
|
<translation>
|
||||||
|
<language>fr-FR</language>
|
||||||
|
<approved>false</approved>
|
||||||
|
</translation>
|
||||||
|
</translations>
|
||||||
|
</concept_node>
|
||||||
|
<concept_node>
|
||||||
|
<name>save_file_loaded_ok</name>
|
||||||
|
<description/>
|
||||||
|
<comment/>
|
||||||
|
<translations>
|
||||||
|
<translation>
|
||||||
|
<language>en-US</language>
|
||||||
|
<approved>false</approved>
|
||||||
|
</translation>
|
||||||
|
<translation>
|
||||||
|
<language>fr-FR</language>
|
||||||
|
<approved>false</approved>
|
||||||
|
</translation>
|
||||||
|
</translations>
|
||||||
|
</concept_node>
|
||||||
<concept_node>
|
<concept_node>
|
||||||
<name>sounds</name>
|
<name>sounds</name>
|
||||||
<description/>
|
<description/>
|
||||||
|
|
|
@ -37,6 +37,8 @@
|
||||||
"level_up.upgrade_perk_to_level": " lvl {{level}}",
|
"level_up.upgrade_perk_to_level": " lvl {{level}}",
|
||||||
"main_menu.basic": "Basic graphics",
|
"main_menu.basic": "Basic graphics",
|
||||||
"main_menu.basic_help": "Fewer particles and flashes, better performance.",
|
"main_menu.basic_help": "Fewer particles and flashes, better performance.",
|
||||||
|
"main_menu.download_save_file": "Download save file",
|
||||||
|
"main_menu.download_save_file_help": "Get a transferable .b71 file with your score and stats",
|
||||||
"main_menu.footer_html": " <p> <span>Made in France by <a href=\"https://lecaro.me\">Renan LE CARO</a>.</span> \n <a href=\"https://breakout.lecaro.me/privacy.html\" target=\"_blank\">Privacy Policy</a>\n <a href=\"https://f-droid.org/en/packages/me.lecaro.breakout/\" target=\"_blank\">F-Droid</a>\n <a href=\"https://play.google.com/store/apps/details?id=me.lecaro.breakout\" target=\"_blank\">Google Play</a>\n <a href=\"https://renanlecaro.itch.io/breakout71\" target=\"_blank\">itch.io</a> \n <a href=\"https://gitlab.com/lecarore/breakout71\" target=\"_blank\">Gitlab</a>\n <a href=\"https://breakout.lecaro.me/\" target=\"_blank\">Web version</a>\n <a href=\"https://news.ycombinator.com/item?id=43183131\" target=\"_blank\">HackerNews</a>\n <span>v.{{appVersion}}</span></p>",
|
"main_menu.footer_html": " <p> <span>Made in France by <a href=\"https://lecaro.me\">Renan LE CARO</a>.</span> \n <a href=\"https://breakout.lecaro.me/privacy.html\" target=\"_blank\">Privacy Policy</a>\n <a href=\"https://f-droid.org/en/packages/me.lecaro.breakout/\" target=\"_blank\">F-Droid</a>\n <a href=\"https://play.google.com/store/apps/details?id=me.lecaro.breakout\" target=\"_blank\">Google Play</a>\n <a href=\"https://renanlecaro.itch.io/breakout71\" target=\"_blank\">itch.io</a> \n <a href=\"https://gitlab.com/lecarore/breakout71\" target=\"_blank\">Gitlab</a>\n <a href=\"https://breakout.lecaro.me/\" target=\"_blank\">Web version</a>\n <a href=\"https://news.ycombinator.com/item?id=43183131\" target=\"_blank\">HackerNews</a>\n <span>v.{{appVersion}}</span></p>",
|
||||||
"main_menu.fullscreen": "Fullscreen",
|
"main_menu.fullscreen": "Fullscreen",
|
||||||
"main_menu.fullscreen_exit": "Exit Fullscreen",
|
"main_menu.fullscreen_exit": "Exit Fullscreen",
|
||||||
|
@ -46,6 +48,8 @@
|
||||||
"main_menu.kid_help": "Start future runs with \"slower ball\".",
|
"main_menu.kid_help": "Start future runs with \"slower ball\".",
|
||||||
"main_menu.language": "Language",
|
"main_menu.language": "Language",
|
||||||
"main_menu.language_help": "Choose the game's language",
|
"main_menu.language_help": "Choose the game's language",
|
||||||
|
"main_menu.load_save_file": "Load save file",
|
||||||
|
"main_menu.load_save_file_help": "Select a .b71 file on your device",
|
||||||
"main_menu.mobile": "Mobile mode",
|
"main_menu.mobile": "Mobile mode",
|
||||||
"main_menu.mobile_help": "Leaves space for your thumb under the puck.",
|
"main_menu.mobile_help": "Leaves space for your thumb under the puck.",
|
||||||
"main_menu.pointer_lock": "Mouse pointer lock",
|
"main_menu.pointer_lock": "Mouse pointer lock",
|
||||||
|
@ -60,6 +64,10 @@
|
||||||
"main_menu.reset_instruction": "You will loose all progress you made in the game, are you sure ?",
|
"main_menu.reset_instruction": "You will loose all progress you made in the game, are you sure ?",
|
||||||
"main_menu.resume": "Resume",
|
"main_menu.resume": "Resume",
|
||||||
"main_menu.resume_help": "Return to your run",
|
"main_menu.resume_help": "Return to your run",
|
||||||
|
"main_menu.save_file_error": "Error loading save file",
|
||||||
|
"main_menu.save_file_loaded": "Save file loaded",
|
||||||
|
"main_menu.save_file_loaded_help": "The app will now reload to apply your save",
|
||||||
|
"main_menu.save_file_loaded_ok": "Ok",
|
||||||
"main_menu.sounds": "Game sounds",
|
"main_menu.sounds": "Game sounds",
|
||||||
"main_menu.sounds_help": "Can slow down some phones.",
|
"main_menu.sounds_help": "Can slow down some phones.",
|
||||||
"main_menu.title": "Breakout 71",
|
"main_menu.title": "Breakout 71",
|
||||||
|
|
|
@ -37,6 +37,8 @@
|
||||||
"level_up.upgrade_perk_to_level": " niveau {{level}}",
|
"level_up.upgrade_perk_to_level": " niveau {{level}}",
|
||||||
"main_menu.basic": "Graphismes simplifiés",
|
"main_menu.basic": "Graphismes simplifiés",
|
||||||
"main_menu.basic_help": "Moins de particules et effets, meilleures performances.",
|
"main_menu.basic_help": "Moins de particules et effets, meilleures performances.",
|
||||||
|
"main_menu.download_save_file": "Sauvegarder mes progrès",
|
||||||
|
"main_menu.download_save_file_help": "Obtenir un fichier de sauvegarde .b71 transférable",
|
||||||
"main_menu.footer_html": " <p> <span>Programmé en France par <a href=\"https://lecaro.me\">Renan LE CARO</a>.</span> <a href=\"https://breakout.lecaro.me/privacy.html\" target=\"_blank\">Politique de confidentialité</a> <a href=\"https://f-droid.org/en/packages/me.lecaro.breakout/\" target=\"_blank\">F-Droid</a> <a href=\"https://play.google.com/store/apps/details?id=me.lecaro.breakout\" target=\"_blank\">Google Play</a> <a href=\"https://renanlecaro.itch.io/breakout71\" target=\"_blank\">itch.io</a> <a href=\"https://gitlab.com/lecarore/breakout71\" target=\"_blank\">Gitlab</a> <a href=\"https://breakout.lecaro.me/\" target=\"_blank\">Version web</a> <a href=\"https://news.ycombinator.com/item?id=43183131\" target=\"_blank\">HackerNews</a> <span>v.{{appVersion}}</span></p>",
|
"main_menu.footer_html": " <p> <span>Programmé en France par <a href=\"https://lecaro.me\">Renan LE CARO</a>.</span> <a href=\"https://breakout.lecaro.me/privacy.html\" target=\"_blank\">Politique de confidentialité</a> <a href=\"https://f-droid.org/en/packages/me.lecaro.breakout/\" target=\"_blank\">F-Droid</a> <a href=\"https://play.google.com/store/apps/details?id=me.lecaro.breakout\" target=\"_blank\">Google Play</a> <a href=\"https://renanlecaro.itch.io/breakout71\" target=\"_blank\">itch.io</a> <a href=\"https://gitlab.com/lecarore/breakout71\" target=\"_blank\">Gitlab</a> <a href=\"https://breakout.lecaro.me/\" target=\"_blank\">Version web</a> <a href=\"https://news.ycombinator.com/item?id=43183131\" target=\"_blank\">HackerNews</a> <span>v.{{appVersion}}</span></p>",
|
||||||
"main_menu.fullscreen": "Plein écran",
|
"main_menu.fullscreen": "Plein écran",
|
||||||
"main_menu.fullscreen_exit": "Quitter le plein écran",
|
"main_menu.fullscreen_exit": "Quitter le plein écran",
|
||||||
|
@ -46,6 +48,8 @@
|
||||||
"main_menu.kid_help": "Balle plus lente",
|
"main_menu.kid_help": "Balle plus lente",
|
||||||
"main_menu.language": "Langue",
|
"main_menu.language": "Langue",
|
||||||
"main_menu.language_help": "Changer la langue d'affichage",
|
"main_menu.language_help": "Changer la langue d'affichage",
|
||||||
|
"main_menu.load_save_file": "Charger une sauvegarde",
|
||||||
|
"main_menu.load_save_file_help": "Sélectionnez un fichier .b71 sur votre appareil ",
|
||||||
"main_menu.mobile": "Mode mobile",
|
"main_menu.mobile": "Mode mobile",
|
||||||
"main_menu.mobile_help": "Laisse un espace pour le pouce sous le palet.",
|
"main_menu.mobile_help": "Laisse un espace pour le pouce sous le palet.",
|
||||||
"main_menu.pointer_lock": "Verrouillage du pointeur de la souris",
|
"main_menu.pointer_lock": "Verrouillage du pointeur de la souris",
|
||||||
|
@ -60,6 +64,10 @@
|
||||||
"main_menu.reset_instruction": "Vous perdrez tous les progrès que vous avez faits dans le jeu, êtes-vous sûr ?",
|
"main_menu.reset_instruction": "Vous perdrez tous les progrès que vous avez faits dans le jeu, êtes-vous sûr ?",
|
||||||
"main_menu.resume": "Retourner à la partie",
|
"main_menu.resume": "Retourner à la partie",
|
||||||
"main_menu.resume_help": "Continuer la partie en cours",
|
"main_menu.resume_help": "Continuer la partie en cours",
|
||||||
|
"main_menu.save_file_error": "Erreur lors du chargement du fichier de sauvegarde",
|
||||||
|
"main_menu.save_file_loaded": "Sauvegarde chargée",
|
||||||
|
"main_menu.save_file_loaded_help": "L'appli va redémarrer",
|
||||||
|
"main_menu.save_file_loaded_ok": "Ok",
|
||||||
"main_menu.sounds": "Sons du jeu",
|
"main_menu.sounds": "Sons du jeu",
|
||||||
"main_menu.sounds_help": "Ralentis certains téléphones.",
|
"main_menu.sounds_help": "Ralentis certains téléphones.",
|
||||||
"main_menu.title": "Breakout 71",
|
"main_menu.title": "Breakout 71",
|
||||||
|
|
|
@ -8,40 +8,32 @@ export const options = {
|
||||||
default: true,
|
default: true,
|
||||||
name: t("main_menu.sounds"),
|
name: t("main_menu.sounds"),
|
||||||
help: t("main_menu.sounds_help"),
|
help: t("main_menu.sounds_help"),
|
||||||
disabled: () => false,
|
|
||||||
},
|
},
|
||||||
"mobile-mode": {
|
"mobile-mode": {
|
||||||
default: window.innerHeight > window.innerWidth,
|
default: window.innerHeight > window.innerWidth,
|
||||||
name: t("main_menu.mobile"),
|
name: t("main_menu.mobile"),
|
||||||
help: t("main_menu.mobile_help"),
|
help: t("main_menu.mobile_help"),
|
||||||
disabled: () => false,
|
|
||||||
},
|
},
|
||||||
basic: {
|
basic: {
|
||||||
default: false,
|
default: false,
|
||||||
name: t("main_menu.basic"),
|
name: t("main_menu.basic"),
|
||||||
help: t("main_menu.basic_help"),
|
help: t("main_menu.basic_help"),
|
||||||
disabled: () => false,
|
|
||||||
},
|
},
|
||||||
pointerLock: {
|
pointerLock: {
|
||||||
default: false,
|
default: false,
|
||||||
name: t("main_menu.pointer_lock"),
|
name: t("main_menu.pointer_lock"),
|
||||||
help: t("main_menu.pointer_lock_help"),
|
help: t("main_menu.pointer_lock_help"),
|
||||||
disabled: () => !document.body.requestPointerLock,
|
|
||||||
},
|
},
|
||||||
easy: {
|
easy: {
|
||||||
default: false,
|
default: false,
|
||||||
name: t("main_menu.kid"),
|
name: t("main_menu.kid"),
|
||||||
help: t("main_menu.kid_help"),
|
help: t("main_menu.kid_help"),
|
||||||
disabled: () => false,
|
|
||||||
},
|
},
|
||||||
// Could not get the sharing to work without loading androidx and all the modern android things so for now I'll just disable sharing in the android app
|
// Could not get the sharing to work without loading androidx and all the modern android things so for now I'll just disable sharing in the android app
|
||||||
record: {
|
record: {
|
||||||
default: false,
|
default: false,
|
||||||
name: t("main_menu.record"),
|
name: t("main_menu.record"),
|
||||||
help: t("main_menu.record_help"),
|
help: t("main_menu.record_help"),
|
||||||
disabled() {
|
|
||||||
return window.location.search.includes("isInWebView=true");
|
|
||||||
},
|
|
||||||
},
|
},
|
||||||
} as const satisfies { [k: string]: OptionDef };
|
} as const satisfies { [k: string]: OptionDef };
|
||||||
|
|
||||||
|
|
|
@ -16,6 +16,13 @@ export const ctx = gameCanvas.getContext("2d", {
|
||||||
alpha: false,
|
alpha: false,
|
||||||
}) as CanvasRenderingContext2D;
|
}) as CanvasRenderingContext2D;
|
||||||
export const bombSVG = document.createElement("img");
|
export const bombSVG = document.createElement("img");
|
||||||
|
|
||||||
|
bombSVG.src =
|
||||||
|
"data:image/svg+xml;base64," +
|
||||||
|
btoa(`<svg width="144" height="144" viewBox="0 0 38.101 38.099" xmlns="http://www.w3.org/2000/svg">
|
||||||
|
<path d="m6.1528 26.516c-2.6992-3.4942-2.9332-8.281-.58305-11.981a10.454 10.454 0 017.3701-4.7582c1.962-.27726 4.1646.05953 5.8835.90027l.45013.22017.89782-.87417c.83748-.81464.91169-.87499 1.0992-.90271.40528-.058713.58876.03425 1.1971.6116l.55451.52679 1.0821-1.0821c1.1963-1.1963 1.383-1.3357 2.1039-1.5877.57898-.20223 1.5681-.19816 2.1691.00897 1.4613.50314 2.3673 1.7622 2.3567 3.2773-.0058.95654-.24464 1.5795-.90924 2.3746-.40936.48928-.55533.81057-.57898 1.2737-.02039.41018.1109.77714.42322 1.1792.30172.38816.3694.61323.2797.93044-.12803.45666-.56674.71598-1.0242.60507-.601-.14597-1.3031-1.3088-1.3969-2.3126-.09459-1.0161.19245-1.8682.92392-2.7432.42567-.50885.5643-.82851.5643-1.3031 0-.50151-.14026-.83177-.51211-1.2028-.50966-.50966-1.0968-.64829-1.781-.41996l-.37348.12477-2.1006 2.1006.52597.55696c.45421.48194.5325.58876.57898.78855.09622.41588.07502.45014-.88396 1.4548l-.87173.9125.26339.57979a10.193 10.193 0 01.9231 4.1001c.03996 2.046-.41996 3.8082-1.4442 5.537-.55044.928-1.0185 1.5013-1.8968 2.3241-.83503.78284-1.5526 1.2827-2.4904 1.7361-3.4266 1.657-7.4721 1.3422-10.549-.82035-.73473-.51782-1.7312-1.4621-2.2515-2.1357zm21.869-4.5584c-.0579-.19734-.05871-2.2662 0-2.4545.11906-.39142.57898-.63361 1.0038-.53005.23812.05708.54147.32455.6116.5382.06279.19163.06769 2.1805.0065 2.3811-.12558.40773-.61649.67602-1.0462.57164-.234-.05708-.51615-.30498-.57568-.50722m3.0417-2.6013c-.12313-.6222.37837-1.1049 1.0479-1.0079.18348.0261.25279.08399 1.0071.83911.75838.75838.81301.82362.84074 1.0112.10193.68499-.40365 1.1938-1.034 1.0405-.1949-.0473-.28786-.12558-1.0144-.85216-.7649-.76409-.80241-.81057-.84645-1.0316m.61323-3.0629a.85623.85623 0 01.59284-.99975c.28949-.09214 2.1814-.08318 2.3917.01141.38734.17369.6279.61078.53984.98181-.06035.25606-.35391.57327-.60181.64992-.25279.07747-2.2278.053-2.4097-.03017-.26013-.11906-.46318-.36125-.51374-.61323" fill="#fff" opacity="0.3"/>
|
||||||
|
</svg>`);
|
||||||
|
|
||||||
export const background = document.createElement("img");
|
export const background = document.createElement("img");
|
||||||
export const backgroundCanvas = document.createElement("canvas");
|
export const backgroundCanvas = document.createElement("canvas");
|
||||||
|
|
||||||
|
|
1
src/types.d.ts
vendored
1
src/types.d.ts
vendored
|
@ -248,6 +248,5 @@ export type OptionDef = {
|
||||||
default: boolean;
|
default: boolean;
|
||||||
name: string;
|
name: string;
|
||||||
help: string;
|
help: string;
|
||||||
disabled: () => boolean;
|
|
||||||
};
|
};
|
||||||
export type OptionId = keyof typeof options;
|
export type OptionId = keyof typeof options;
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue