This commit is contained in:
Renan LE CARO 2025-04-20 13:41:12 +02:00
parent b3949d8c41
commit c88540488d
9 changed files with 78 additions and 77 deletions

View file

@ -29,8 +29,8 @@ android {
applicationId = "me.lecaro.breakout" applicationId = "me.lecaro.breakout"
minSdk = 21 minSdk = 21
targetSdk = 34 targetSdk = 34
versionCode = 29085783 versionCode = 29085797
versionName = "29085783" versionName = "29085797"
testInstrumentationRunner = "androidx.test.runner.AndroidJUnitRunner" testInstrumentationRunner = "androidx.test.runner.AndroidJUnitRunner"
vectorDrawables { vectorDrawables {
useSupportLibrary = true useSupportLibrary = true

File diff suppressed because one or more lines are too long

View file

@ -48,16 +48,22 @@ class MainActivity : android.app.Activity() {
private fun downloadFile(url: String) { private fun downloadFile(url: String) {
try { try {
if (!url.startsWith("data:application/json;charset=utf-8,")) {
Log.w("DL", "url ignored because it does not start with data:")
return
}
val sdf = SimpleDateFormat("yyyy-M-dd-hh-mm") val sdf = SimpleDateFormat("yyyy-M-dd-hh-mm")
val currentDate = sdf.format(Date()) val currentDate = sdf.format(Date())
val urlEncoded = url.substring("data:application/json;charset=utf-8,".length)
val str = URLDecoder.decode(urlEncoded, StandardCharsets.UTF_8.name())
writeFileAndShare(str, "breakout-71-save-$currentDate.json", "application/json") if (url.startsWith("data:application/json;charset=utf-8,")) {
val urlEncoded = url.substring("data:application/json;charset=utf-8,".length)
val str = URLDecoder.decode(urlEncoded, StandardCharsets.UTF_8.name())
writeFileAndShare(str.toByteArray(), "breakout-71-save-$currentDate.json", "application/json")
}
if (url.startsWith("data:video/webm;base64,")) {
val base64Data = url.substring("data:video/webm;base64,".length)
val decodedBytes = android.util.Base64.decode(base64Data, android.util.Base64.DEFAULT)
writeFileAndShare(decodedBytes, "breakout-71-capture-$currentDate.webm", "video/webm")
}
} catch (e: Exception) { } catch (e: Exception) {
Log.e("DL", "Error ${e.message}") Log.e("DL", "Error ${e.message}")
@ -65,7 +71,7 @@ class MainActivity : android.app.Activity() {
} }
} }
fun writeFileAndShare(jsonData: String, fileName: String, mime: String) { fun writeFileAndShare(bytes:ByteArray, fileName: String, mime: String) {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.Q) { if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.Q) {
// android 10 // android 10
@ -80,7 +86,7 @@ class MainActivity : android.app.Activity() {
) )
uri?.let { uri?.let {
contentResolver.openOutputStream(it)?.use { outputStream -> contentResolver.openOutputStream(it)?.use { outputStream ->
outputStream.write(jsonData.toByteArray()) outputStream.write(bytes)
} }
} }
@ -94,7 +100,7 @@ class MainActivity : android.app.Activity() {
} else { } else {
val file = File(getExternalFilesDir(null), fileName) val file = File(getExternalFilesDir(null), fileName)
file.writeText(jsonData) file.writeBytes(bytes)
val uri = FileProvider.getUriForFile( val uri = FileProvider.getUriForFile(
this, this,
"$packageName.fileprovider", // Adjust if your authority is different "$packageName.fileprovider", // Adjust if your authority is different

45
dist/index.html vendored

File diff suppressed because one or more lines are too long

View file

@ -1,5 +1,5 @@
// The version of the cache. // The version of the cache.
const VERSION = "29085783"; const VERSION = "29085797";
// The name of the cache // The name of the cache
const CACHE_NAME = `breakout-71-${VERSION}`; const CACHE_NAME = `breakout-71-${VERSION}`;

View file

@ -1 +1 @@
"29085783" "29085797"

View file

@ -423,4 +423,4 @@ export function getCornerOffset(gameState: GameState) {
} }
export const isInWebView = !!window.location.href.includes("isInWebView=true"); export const isInWebView = !!window.location.href.includes("isInWebView=true");
console.log({isInWebView}) console.log({ isInWebView });

View file

@ -89,6 +89,7 @@ export function startRecordingGame(gameState: GameState) {
const recordedChunks: Blob[] = []; const recordedChunks: Blob[] = [];
const instance = new MediaRecorder(captureStream, { const instance = new MediaRecorder(captureStream, {
// Required for less mushy result
videoBitsPerSecond: 3500000, videoBitsPerSecond: 3500000,
}); });
mediaRecorder = instance; mediaRecorder = instance;
@ -136,7 +137,6 @@ export function startRecordingGame(gameState: GameState) {
size: (blob.size / 1000000).toFixed(2), size: (blob.size / 1000000).toFixed(2),
}); });
targetDiv.appendChild(a); targetDiv.appendChild(a);
}; };
} }

View file

@ -1,77 +1,73 @@
// Settings // Settings
import {toast} from "./toast";
import {t} from "./i18n/i18n";
let cachedSettings: { [key: string]: unknown } = {}; let cachedSettings: { [key: string]: unknown } = {};
try { try {
for (let key in localStorage) { for (let key in localStorage) {
try { try {
cachedSettings[key] = JSON.parse(localStorage.getItem(key) || "null"); cachedSettings[key] = JSON.parse(localStorage.getItem(key) || "null");
} catch (e) { } catch (e) {
console.warn(e); console.warn(e);
}
} }
}
} catch (e) { } catch (e) {
console.warn(e); console.warn(e);
} }
export function getSettingValue<T>(key: string, defaultValue: T) { export function getSettingValue<T>(key: string, defaultValue: T) {
return (cachedSettings[key] as T) ?? defaultValue; return (cachedSettings[key] as T) ?? defaultValue;
} }
// We avoid using localstorage synchronously for perf reasons // We avoid using localstorage synchronously for perf reasons
let needsSaving: Set<string> = new Set(); let needsSaving: Set<string> = new Set();
export function setSettingValue<T>(key: string, value: T) { export function setSettingValue<T>(key: string, value: T) {
needsSaving.add(key); needsSaving.add(key);
cachedSettings[key] = value; cachedSettings[key] = value;
} }
export function commitSettingsChangesToLocalStorage() { export function commitSettingsChangesToLocalStorage() {
try { try {
for (let key of needsSaving) { for (let key of needsSaving) {
localStorage.setItem(key, JSON.stringify(cachedSettings[key])); localStorage.setItem(key, JSON.stringify(cachedSettings[key]));
}
needsSaving.clear();
} catch (e) {
console.warn(e);
} }
needsSaving.clear();
} catch (e) {
console.warn(e);
}
} }
setInterval(() => commitSettingsChangesToLocalStorage(), 500); setInterval(() => commitSettingsChangesToLocalStorage(), 500);
export function getTotalScore() { export function getTotalScore() {
return getSettingValue("breakout_71_total_score", 0); return getSettingValue("breakout_71_total_score", 0);
} }
export function getCurrentMaxCoins() { export function getCurrentMaxCoins() {
return Math.pow(2, getSettingValue("max_coins", 2)) * 200; return Math.pow(2, getSettingValue("max_coins", 2)) * 200;
} }
export function getCurrentMaxParticles() { export function getCurrentMaxParticles() {
return getCurrentMaxCoins(); return getCurrentMaxCoins();
} }
export function cycleMaxCoins() { export function cycleMaxCoins() {
setSettingValue("max_coins", (getSettingValue("max_coins", 2) + 1) % 7); setSettingValue("max_coins", (getSettingValue("max_coins", 2) + 1) % 7);
} }
let asked = false; let asked = false;
export async function askForPersistentStorage() { export async function askForPersistentStorage() {
if (asked) return; if (asked) return;
asked = true; asked = true;
if (!navigator.storage) return if (!navigator.storage) return;
if (!navigator.storage.persist) return if (!navigator.storage.persist) return;
if (!navigator.storage.persisted) return if (!navigator.storage.persisted) return;
if (await navigator.storage.persisted()) { if (await navigator.storage.persisted()) {
return return;
} }
const persistent = await navigator.storage.persist() const persistent = await navigator.storage.persist();
if (!persistent) { if (!persistent) {
toast(t("settings.storage_refused")); console.warn('No storage granted')
} }
} }