diff --git a/src-ui/css/ui.css b/src-ui/css/ui.css index 97c4ac8f0..d433b5cd7 100644 --- a/src-ui/css/ui.css +++ b/src-ui/css/ui.css @@ -614,6 +614,19 @@ form#fileform2 { content: "+"; } +div#saveicon { + float: right; + position: relative; + height: 100%; + display: flex; + align-items: center; + margin-right: 2px; + margin-top: 1px; +} +.hide { + visibility: hidden; +} + div#timertext { display: inline-block; padding: 2pt 0; diff --git a/src-ui/js/list.js b/src-ui/js/list.js index ea26a397d..b179a28c5 100644 --- a/src-ui/js/list.js +++ b/src-ui/js/list.js @@ -103,7 +103,7 @@ localStorage.getItem("pzprv3_config:ui") || "{}" ); setting.listsort = typename; - localStorage.setItem("pzprv3_config:ui", JSON.stringify(setting)); + pzpr.util.store("pzprv3_config:ui", JSON.stringify(setting)); self.apply_sort(); }, diff --git a/src-ui/js/ui/Boot.js b/src-ui/js/ui/Boot.js index a0526f397..0749231e5 100644 --- a/src-ui/js/ui/Boot.js +++ b/src-ui/js/ui/Boot.js @@ -13,18 +13,42 @@ // ★boot() window.onload直後の処理 //--------------------------------------------------------------------------- pzpr.on("load", function boot() { - if (importData()) { - startPuzzle(); + var pzl; + var storedGame = null; + + if (pzpr.env.localStorageAvailable) { + // If localStorage is available and autosave is enabled: + // Get URL search hash and check localStorage to see if a board state is saved + + // ui.menuconfig is not yet populated, so need to manually check + var json_menu = localStorage.getItem("pzprv3_config:ui"); + if (json_menu && JSON.parse(json_menu)["autosave"]) { + var key = "pzpr_" + getPuzzleString(); + storedGame = localStorage.getItem(key); + } + } + + if (storedGame) { + var valObject = JSON.parse(storedGame); + pzl = importData(valObject.pzl); } else { + pzl = importData(); + } + if (!pzl) { setTimeout(boot, 0); } + startPuzzle(); }); - function importData() { + function importData(string) { if (!onload_pzl) { /* 1) 盤面複製・index.htmlからのファイル入力/Database入力か */ /* 2) URL(?以降)をチェック */ - onload_pzl = importURL(); + if (!string) { + onload_pzl = importURL(); + } else { + onload_pzl = importFromString(string); + } /* 指定されたパズルがない場合はさようなら~ */ if (!onload_pzl || !onload_pzl.pid) { @@ -90,26 +114,75 @@ //--------------------------------------------------------------------------- function importURL() { /* index.htmlからURLが入力されていない場合は現在のURLの?以降をとってくる */ + var puzString = getPuzzleString(); + return importFromString(puzString); + } + //Splitting functionality from above for flexibility. + + //Return the string associated with the puzzle + function getPuzzleString() { var search = location.search; if (!search) { return null; } - - /* 一旦先頭の?記号を取り除く */ if (search.charAt(0) === "?") { - search = search.substr(1); + search = search.slice(1); } while (search.match(/^(\w+)\=(\w+)\&(.*)/)) { onload_option[RegExp.$1] = RegExp.$2; search = RegExp.$3; } + return search; + } + //Import from a puzzle string. This can come from the URL or from localStorage + function importFromString(string) { + if (!string) { + return null; + } - onload_pzv = search; - var pzl = pzpr.parser.parseURL(search); + onload_pzv = string; + var pzl = pzpr.parser.parseURL(string); var startmode = pzl.mode || (!pzl.body ? "editor" : "player"); onload_option.type = onload_option.type || startmode; return pzl; } + + //--------------------------------------------------------------------------- + // Functionality to support browser caching + //--------------------------------------------------------------------------- + + //Save board state. Creates an entry in localStorage whose key is a 'pzpr_' identifier plus the current board state puzzle string. + //Board state puzzle string is the same thing you get from duplicating the board state + //Auto-exits if the correct setting is not set, so safe to call from anywhere without checking + function saveBoardState() { + if (!ui.menuconfig.get("autosave")) { + return; + } + var key = "pzpr_" + getPuzzleString(); + var url = ui.puzzle.getURL( + pzpr.parser.URL_PZPRFILE, + ui.puzzle.playeronly ? "player" : "editor" + ); + //Strip url to the last option. This is the "puzzle string" we want + url = url.substring(url.indexOf("?") + 1); //Skip to the search parameters part of the url + while (url.match(/^(\w+)\=(\w+)\&(.*)/)) { + url = RegExp.$3; + } + //Add a time signifier so that we can sort and delete oldest if setting fails + var valObject = { + t: Date.now(), + pzl: url + // bufferToForceStorageLimitErrors: "0".repeat(1700000) //Include for testing to force out-of-storage errors + }; + pzpr.util.store(key, JSON.stringify(valObject)); + } + + //Events that trigger a board state save + document.addEventListener("visibilitychange", function() { + if (document.visibilityState === "hidden") { + saveBoardState(); + } + }); })(); diff --git a/src-ui/js/ui/MenuConfig.js b/src-ui/js/ui/MenuConfig.js index 44040e279..863d7b77e 100644 --- a/src-ui/js/ui/MenuConfig.js +++ b/src-ui/js/ui/MenuConfig.js @@ -50,6 +50,11 @@ volatile: true }); /* マウスの左右ボタンを反転する設定 */ + //Autosave feature. Not on by default, but persists once enabled + this.add("autosave", false, { + volatile: false + }); + this.add("language", pzpr.lang, { option: ["en", "ja"] }); /* 言語設定 */ /* puzzle.configを一括で扱うため登録 */ @@ -264,11 +269,11 @@ } try { - localStorage.setItem( + pzpr.util.store( "pzprv3_config:puzzle", JSON.stringify(ui.puzzle.saveConfig()) ); - localStorage.setItem("pzprv3_config:ui", JSON.stringify(this.getAll())); + pzpr.util.store("pzprv3_config:ui", JSON.stringify(this.getAll())); } catch (ex) { console.warn(ex); } @@ -336,6 +341,15 @@ // config.configevent() 設定変更時の動作を記述する (modeはlistener.onModeChangeで変更) //--------------------------------------------------------------------------- configevent: function(idname, newval) { + //Need to set save icon visibility here to make sure it goes off before the early exit + if (idname === "autosave") { + var saveIcon = document.getElementById("saveicon"); + if (!!newval) { + saveIcon.classList.remove("hide"); + } else { + saveIcon.classList.add("hide"); + } + } if (!ui.menuarea.menuitem) { return; } diff --git a/src-ui/p.html b/src-ui/p.html index 63ca8a2d1..dfd0e94b9 100644 --- a/src-ui/p.html +++ b/src-ui/p.html @@ -93,6 +93,7 @@

読み込み中です...

  • __lattice.menu__
  • __singlenum.menu__
  • __discolor__
  • +
  • __autosave__
  • __autocheck__ ->
  • __autocheck.off__
  • __autocheck.guarded__
  • @@ -111,6 +112,7 @@

    読み込み中です...

  • +
    💾