Feat(Fortune): Preview result url (#62)

* Feat(Fortune): Support preview result depends on url params

* Feat(Fortune): Specify commit hash in preview result to ensure event consistency

* Feat(Fortune): Add copy preview url button

* Feat(Fortune): Support theme color for copy preview button

* Impr(Fortune): Make UI looks better

* Docs(CONTRIBUTING): Add missing theme field
This commit was merged in pull request #62.
This commit is contained in:
tobiichi3227
2025-03-09 15:52:26 +08:00
committed by GitHub
parent 1471b5950d
commit e1e17bd2bc
7 changed files with 188 additions and 111 deletions

View File

@@ -31,13 +31,17 @@ jobs:
steps: steps:
- name: Checkout - name: Checkout
uses: actions/checkout@v4 uses: actions/checkout@v4
- name: Setup Pages
uses: actions/configure-pages@v5 - name: Write Commit Hash
- name: Upload artifact run: |
uses: actions/upload-pages-artifact@v3 cat << EOF | tee fortune_generator/json/commit_hash.json > /dev/null
{"commit_hash": "$(git rev-parse HEAD)"}
EOF
- name: Deploy
uses: peaceiris/actions-gh-pages@v4
if: github.ref == 'refs/heads/main'
with: with:
# Upload entire repository github_token: ${{ secrets.GITHUB_TOKEN }}
path: '.' publish_dir: ./
- name: Deploy to GitHub Pages publish_branch: gh-pages
id: deployment
uses: actions/deploy-pages@v4

View File

@@ -128,6 +128,7 @@ structure:
"button-hover-color": "#hexcode", "button-hover-color": "#hexcode",
"toggle-theme-button-color": "#hexcode", "toggle-theme-button-color": "#hexcode",
"copy-result-button-color": "#hexcode", "copy-result-button-color": "#hexcode",
"copy-preview-result-url-button-color": "#hexcode",
"date-color": "#hexcode", "date-color": "#hexcode",
"special-event-color": "#hexcode" "special-event-color": "#hexcode"
} }

View File

@@ -3,6 +3,7 @@
--button-hover-color: #459aef; --button-hover-color: #459aef;
--toggle-theme-button-color: #000000; --toggle-theme-button-color: #000000;
--copy-result-button-color: #000000; --copy-result-button-color: #000000;
--copy-preview-result-url-button-color: #000000;
--bg-color: #ffffff; --bg-color: #ffffff;
--good-fortune-color: #e74c3c; --good-fortune-color: #e74c3c;
--bad-fortune-color: #000000bf; --bad-fortune-color: #000000bf;
@@ -99,10 +100,16 @@ button:hover {
#copy-result-button { #copy-result-button {
margin-top: 20px; margin-top: 20px;
font-size: 1.5rem; font-size: 2.2rem;
color: var(--copy-result-button-color); color: var(--copy-result-button-color);
} }
#copy-preview-result-url-button {
margin-top: 20px;
font-size: 2.2rem;
color: var(--copy-preview-result-url-button-color);
}
#themeModal { #themeModal {
.modal-content { .modal-content {
background-color: var(--bg-color) !important; background-color: var(--bg-color) !important;

View File

@@ -121,7 +121,12 @@
點擊打卡 點擊打卡
</button> </button>
<i <i
class="col-2 offset-2 fas fa-clone d-none" class="offset-md-1 col-md-1 col-2 fas fa-link d-none"
id="copy-preview-result-url-button"
onclick="copyPreviewResultUrlToClipboard()"
></i>
<i
class="col-2 fas fa-clone d-none"
id="copy-result-button" id="copy-result-button"
onclick="copyResultImageToClipboard()" onclick="copyResultImageToClipboard()"
></i> ></i>

View File

@@ -24,16 +24,25 @@ fetch("https://api.ipify.org?format=json").then((response) => {
let goodFortunes = []; let goodFortunes = [];
let badFortunes = []; let badFortunes = [];
let special_events = []; let special_events = [];
let fortune_generated = false; let commit_hash = "";
// using async and await to prevent fetching the data too late... // using async and await to prevent fetching the data too late...
async function fetch_data() { async function fetch_data(commit_hash) {
await fetch("./json/fortune.json") let prefix = "";
if (commit_hash) {
prefix = `https://raw.githubusercontent.com/LifeAdventurer/generators/${commit_hash}/fortune_generator/`;
}
await fetch(`${prefix}./json/fortune.json`)
.then((response) => response.json()) .then((response) => response.json())
.then((data) => { .then((data) => {
goodFortunes = data.goodFortunes; goodFortunes = data.goodFortunes;
badFortunes = data.badFortunes; badFortunes = data.badFortunes;
}); });
await fetch('./json/commit_hash.json')
.then((response) => response.json())
.then((data) => {
commit_hash = data.commit_hash;
});
async function fetch_events(path) { async function fetch_events(path) {
await fetch(path) await fetch(path)
@@ -43,9 +52,9 @@ async function fetch_data() {
}); });
} }
await fetch_events("./json/custom_special.json"); await fetch_events(`${prefix}./json/custom_special.json`);
await fetch_events("./json/static_special.json"); await fetch_events(`${prefix}./json/static_special.json`);
await fetch_events("./json/cyclical_special.json"); await fetch_events(`${prefix}./json/cyclical_special.json`);
} }
const textColorClass = [ const textColorClass = [
@@ -267,13 +276,35 @@ const J_r_2_desc = $("#r-2-desc");
const J_ip_to_fortune = $("#ip-to-fortune"); const J_ip_to_fortune = $("#ip-to-fortune");
let special = false; let special = false;
let special_events_index = 0; let special_events_index = -1;
let l1 = -1, l2 = -1, r1 = -1, r2 = -1;
let status_index = -1;
let seed1 = -1, seed2 = -1;
let fortune_generated = false;
let preview_result = false;
let current_day_special_events = []; let current_day_special_events = [];
// init page // init page
async function init_page() { async function init_page() {
let urlParams = new URLSearchParams(window.location.search);
let commit_hash = null;
if (urlParams.has('fi') && urlParams.has('si') && urlParams.has('ei'), urlParams.has('ch')) { // fortune_index, status_index, event_index, commit_hash
status_index = parseInt(urlParams.get('si'));
special_events_index = parseInt(urlParams.get('ei'));
[l1, l2, r1, r2] = urlParams.get('fi').split(':').map(num => parseInt(num));
commit_hash = urlParams.get('ch');
if (isNaN(status_index) || isNaN(special_events_index) || isNaN(l1) || isNaN(l2) || isNaN(r1) || isNaN(r2)) {
special_events_index = -1;
l1 = -1, l2 = -1, r1 = -1, r2 = -1;
status_index = -1;
commit_hash = null;
} else {
preview_result = true;
if (special_events_index != -1) special = true;
}
}
// fetch data from `fortune.json` // fetch data from `fortune.json`
await fetch_data(); await fetch_data(commit_hash);
// hide the elements of show fortune page // hide the elements of show fortune page
$("#result-page").hide(); $("#result-page").hide();
@@ -295,6 +326,8 @@ async function init_page() {
$("#date").html(showDate); $("#date").html(showDate);
$("#weekday").html(showDay); $("#weekday").html(showDay);
if (preview_result) Appear();
if (!preview_result) {
const showSpecialEventCount = 2; const showSpecialEventCount = 2;
let eventIndexList = Array(showSpecialEventCount).fill(-1); let eventIndexList = Array(showSpecialEventCount).fill(-1);
let eventDiffDaysIndexList = Array(showSpecialEventCount).fill( let eventDiffDaysIndexList = Array(showSpecialEventCount).fill(
@@ -360,6 +393,7 @@ async function init_page() {
} }
} }
} }
}
// event bar // event bar
const good_span = (event) => const good_span = (event) =>
@@ -383,11 +417,7 @@ function Appear() {
const badLen = badFortunes.length; const badLen = badFortunes.length;
const statusLen = fortuneStatus.length; const statusLen = fortuneStatus.length;
let status_index = -1; if (!fortune_generated && !preview_result) {
let seed1 = -1;
let seed2 = -1;
if (!fortune_generated) {
// transform ip to four numbers // transform ip to four numbers
const num = ip.split(".").map((num) => parseInt(num)); const num = ip.split(".").map((num) => parseInt(num));
@@ -430,7 +460,7 @@ function Appear() {
localStorage.setItem("last_status_index", status_index.toString()); localStorage.setItem("last_status_index", status_index.toString());
localStorage.setItem("last_seed1", seed1.toString()); localStorage.setItem("last_seed1", seed1.toString());
localStorage.setItem("last_seed2", seed2.toString()); localStorage.setItem("last_seed2", seed2.toString());
} else { } else if (!preview_result) {
status_index = parseInt(localStorage.getItem("last_status_index")); status_index = parseInt(localStorage.getItem("last_status_index"));
seed1 = parseInt(localStorage.getItem("last_seed1")); seed1 = parseInt(localStorage.getItem("last_seed1"));
seed2 = parseInt(localStorage.getItem("last_seed2")); seed2 = parseInt(localStorage.getItem("last_seed2"));
@@ -453,15 +483,16 @@ function Appear() {
} }
// make sure the events won't collide // make sure the events won't collide
if (!preview_result) {
const set = new Set(); const set = new Set();
const l1 = (seed1 % goodLen + goodLen) % goodLen; l1 = (seed1 % goodLen + goodLen) % goodLen;
set.add(goodFortunes[l1].event); set.add(goodFortunes[l1].event);
let l2 = (((seed1 << 1) + date) % goodLen + goodLen) % goodLen; l2 = (((seed1 << 1) + date) % goodLen + goodLen) % goodLen;
while (set.has(goodFortunes[l2].event)) { while (set.has(goodFortunes[l2].event)) {
l2 = (l2 + 1) % goodLen; l2 = (l2 + 1) % goodLen;
} }
set.add(goodFortunes[l2].event); set.add(goodFortunes[l2].event);
let r1 = r1 =
(((seed1 >> 2) + ((month * 42 + year) << 3 + 3) + 19) % badLen + badLen) % (((seed1 >> 2) + ((month * 42 + year) << 3 + 3) + 19) % badLen + badLen) %
badLen; badLen;
if ( if (
@@ -475,7 +506,7 @@ function Appear() {
r1 = (r1 + 7) % badLen; r1 = (r1 + 7) % badLen;
} }
set.add(badFortunes[r1].event); set.add(badFortunes[r1].event);
let r2 = (((((seed1 << 3 + 7) + (year >> 5) * (date << 2 + 3)) * r2 = (((((seed1 << 3 + 7) + (year >> 5) * (date << 2 + 3)) *
seed2) >> 4 + seed2 % 42) % badLen + badLen) % badLen; seed2) >> 4 + seed2 % 42) % badLen + badLen) % badLen;
if ( if (
r2 == 0 && r2 == 0 &&
@@ -489,6 +520,7 @@ function Appear() {
while (set.has(badFortunes[r2].event)) { while (set.has(badFortunes[r2].event)) {
r2 = (r2 + 17) % badLen; r2 = (r2 + 17) % badLen;
} }
}
// organize the stuffs below this line... // organize the stuffs below this line...
const l1_desc_list = goodFortunes[l1].description; const l1_desc_list = goodFortunes[l1].description;
@@ -569,6 +601,14 @@ function Appear() {
} }
} }
$("#copy-result-button").removeClass("d-none"); $("#copy-result-button").removeClass("d-none");
$("#copy-preview-result-url-button").removeClass("d-none");
}
function copyPreviewResultUrlToClipboard() {
let baseUrl = location.href.split("?")[0];
let url = `${baseUrl}?si=${status_index}&ei=${special_events_index}&fi=${[l1,l2,r1,r2].join(":")}&ch=${commit_hash.substr(0, 7)}`;
navigator.clipboard.writeText(url);
showCopiedNotice();
} }
function getLuck() { function getLuck() {

View File

@@ -13,6 +13,7 @@
"button-hover-color": "#459aef", "button-hover-color": "#459aef",
"toggle-theme-button-color": "#000000", "toggle-theme-button-color": "#000000",
"copy-result-button-color": "#000000", "copy-result-button-color": "#000000",
"copy-preview-result-url-button-color": "#000000",
"date-color": "#096e1bc9", "date-color": "#096e1bc9",
"special-event-color": "#3e4fbb" "special-event-color": "#3e4fbb"
} }
@@ -30,6 +31,7 @@
"button-hover-color": "#9ac6f1", "button-hover-color": "#9ac6f1",
"toggle-theme-button-color": "#ffffff", "toggle-theme-button-color": "#ffffff",
"copy-result-button-color": "#ffffff", "copy-result-button-color": "#ffffff",
"copy-preview-result-url-button-color": "#ffffff",
"date-color": "#0ed64aed", "date-color": "#0ed64aed",
"special-event-color": "#6477f3" "special-event-color": "#6477f3"
} }
@@ -47,6 +49,7 @@
"button-hover-color": "#a6e3a1", "button-hover-color": "#a6e3a1",
"toggle-theme-button-color": "#f9e2af", "toggle-theme-button-color": "#f9e2af",
"copy-result-button-color": "#f38ba8", "copy-result-button-color": "#f38ba8",
"copy-preview-result-url-button-color": "#f38ba8",
"date-color": "#f5c2e7", "date-color": "#f5c2e7",
"special-event-color": "#fab387" "special-event-color": "#fab387"
} }
@@ -64,6 +67,7 @@
"button-hover-color": "#5a5b7f", "button-hover-color": "#5a5b7f",
"toggle-theme-button-color": "#7dcfff", "toggle-theme-button-color": "#7dcfff",
"copy-result-button-color": "#ff5c8d", "copy-result-button-color": "#ff5c8d",
"copy-preview-result-url-button-color": "#ff5c8d",
"date-color": "#ffbb93", "date-color": "#ffbb93",
"special-event-color": "#f7768e" "special-event-color": "#f7768e"
} }
@@ -81,6 +85,7 @@
"button-hover-color": "#ffb347", "button-hover-color": "#ffb347",
"toggle-theme-button-color": "#ff6f61", "toggle-theme-button-color": "#ff6f61",
"copy-result-button-color": "#6d597a", "copy-result-button-color": "#6d597a",
"copy-preview-result-url-button-color": "#6d597a",
"date-color": "#ff9f80", "date-color": "#ff9f80",
"special-event-color": "#ffb6b9" "special-event-color": "#ffb6b9"
} }
@@ -98,6 +103,7 @@
"button-hover-color": "#ff8500", "button-hover-color": "#ff8500",
"toggle-theme-button-color": "#34ace0", "toggle-theme-button-color": "#34ace0",
"copy-result-button-color": "#ffcc29", "copy-result-button-color": "#ffcc29",
"copy-preview-result-url-button-color": "#ffcc29",
"date-color": "#ffd32a", "date-color": "#ffd32a",
"special-event-color": "#f7b731" "special-event-color": "#f7b731"
} }
@@ -115,6 +121,7 @@
"button-hover-color": "#b9896e", "button-hover-color": "#b9896e",
"toggle-theme-button-color": "#a74c3c", "toggle-theme-button-color": "#a74c3c",
"copy-result-button-color": "#7a6e61", "copy-result-button-color": "#7a6e61",
"copy-preview-result-url-button-color": "#7a6e61",
"date-color": "#e6b89c", "date-color": "#e6b89c",
"special-event-color": "#e8a87c" "special-event-color": "#e8a87c"
} }
@@ -132,6 +139,7 @@
"button-hover-color": "#a29bfe", "button-hover-color": "#a29bfe",
"toggle-theme-button-color": "#00b894", "toggle-theme-button-color": "#00b894",
"copy-result-button-color": "#0984e3", "copy-result-button-color": "#0984e3",
"copy-preview-result-url-button-color": "#0984e3",
"date-color": "#74b9ff", "date-color": "#74b9ff",
"special-event-color": "#fdcb6e" "special-event-color": "#fdcb6e"
} }
@@ -149,6 +157,7 @@
"button-hover-color": "#535c88", "button-hover-color": "#535c88",
"toggle-theme-button-color": "#7ed6df", "toggle-theme-button-color": "#7ed6df",
"copy-result-button-color": "#ffeaa7", "copy-result-button-color": "#ffeaa7",
"copy-preview-result-url-button-color": "#ffeaa7",
"date-color": "#dcdde1", "date-color": "#dcdde1",
"special-event-color": "#ff9ff3" "special-event-color": "#ff9ff3"
} }
@@ -166,6 +175,7 @@
"button-hover-color": "#646b8a", "button-hover-color": "#646b8a",
"toggle-theme-button-color": "#7289da", "toggle-theme-button-color": "#7289da",
"copy-result-button-color": "#b56576", "copy-result-button-color": "#b56576",
"copy-preview-result-url-button-color": "#b56576",
"date-color": "#d4d4dc", "date-color": "#d4d4dc",
"special-event-color": "#ffb86c" "special-event-color": "#ffb86c"
} }
@@ -183,6 +193,7 @@
"button-hover-color": "#52577a", "button-hover-color": "#52577a",
"toggle-theme-button-color": "#00eaff", "toggle-theme-button-color": "#00eaff",
"copy-result-button-color": "#ff5555", "copy-result-button-color": "#ff5555",
"copy-preview-result-url-button-color": "#ff5555",
"date-color": "#9aedfe", "date-color": "#9aedfe",
"special-event-color": "#ffa07a" "special-event-color": "#ffa07a"
} }
@@ -200,6 +211,7 @@
"button-hover-color": "#6a9a76", "button-hover-color": "#6a9a76",
"toggle-theme-button-color": "#a1e887", "toggle-theme-button-color": "#a1e887",
"copy-result-button-color": "#d94e3b", "copy-result-button-color": "#d94e3b",
"copy-preview-result-url-button-color": "#d94e3b",
"date-color": "#e4f9e0", "date-color": "#e4f9e0",
"special-event-color": "#9fd9b7" "special-event-color": "#9fd9b7"
} }
@@ -217,6 +229,7 @@
"button-hover-color": "#b98b6f", "button-hover-color": "#b98b6f",
"toggle-theme-button-color": "#8b5e3c", "toggle-theme-button-color": "#8b5e3c",
"copy-result-button-color": "#d4a373", "copy-result-button-color": "#d4a373",
"copy-preview-result-url-button-color": "#d4a373",
"date-color": "#7f6a5d", "date-color": "#7f6a5d",
"special-event-color": "#c7ab93" "special-event-color": "#c7ab93"
} }
@@ -234,6 +247,7 @@
"button-hover-color": "#2980b9", "button-hover-color": "#2980b9",
"toggle-theme-button-color": "#4e8c47", "toggle-theme-button-color": "#4e8c47",
"copy-result-button-color": "#d9534f", "copy-result-button-color": "#d9534f",
"copy-preview-result-url-button-color": "#d9534f",
"date-color": "#bdc3c7", "date-color": "#bdc3c7",
"special-event-color": "#f39c12" "special-event-color": "#f39c12"
} }
@@ -251,6 +265,7 @@
"button-hover-color": "#ff6347", "button-hover-color": "#ff6347",
"toggle-theme-button-color": "#00bfae", "toggle-theme-button-color": "#00bfae",
"copy-result-button-color": "#ff6347", "copy-result-button-color": "#ff6347",
"copy-preview-result-url-button-color": "#ff6347",
"date-color": "#2e8b57", "date-color": "#2e8b57",
"special-event-color": "#ff8c00" "special-event-color": "#ff8c00"
} }
@@ -268,6 +283,7 @@
"button-hover-color": "#fc4f48", "button-hover-color": "#fc4f48",
"toggle-theme-button-color": "#e1b1e3", "toggle-theme-button-color": "#e1b1e3",
"copy-result-button-color": "#c93f36", "copy-result-button-color": "#c93f36",
"copy-preview-result-url-button-color": "#c93f36",
"date-color": "#cf63a1", "date-color": "#cf63a1",
"special-event-color": "#f6c6d4" "special-event-color": "#f6c6d4"
} }
@@ -285,6 +301,7 @@
"button-hover-color": "#b0b098", "button-hover-color": "#b0b098",
"toggle-theme-button-color": "#8c9f6f", "toggle-theme-button-color": "#8c9f6f",
"copy-result-button-color": "#e18e8b", "copy-result-button-color": "#e18e8b",
"copy-preview-result-url-button-color": "#e18e8b",
"date-color": "#4f5049", "date-color": "#4f5049",
"special-event-color": "#b7c7b5" "special-event-color": "#b7c7b5"
} }
@@ -302,6 +319,7 @@
"button-hover-color": "#5072b3", "button-hover-color": "#5072b3",
"toggle-theme-button-color": "#00d084", "toggle-theme-button-color": "#00d084",
"copy-result-button-color": "#455a64", "copy-result-button-color": "#455a64",
"copy-preview-result-url-button-color": "#455a64",
"date-color": "#cfd8dc", "date-color": "#cfd8dc",
"special-event-color": "#a1d6ff" "special-event-color": "#a1d6ff"
} }
@@ -319,6 +337,7 @@
"button-hover-color": "#005f87", "button-hover-color": "#005f87",
"toggle-theme-button-color": "#00f5d4", "toggle-theme-button-color": "#00f5d4",
"copy-result-button-color": "#293462", "copy-result-button-color": "#293462",
"copy-preview-result-url-button-color": "#293462",
"date-color": "#72efdd", "date-color": "#72efdd",
"special-event-color": "#72ddf7" "special-event-color": "#72ddf7"
} }

View File

@@ -117,6 +117,7 @@ def check_theme(theme, idx: int):
("button-hover-color", str), ("button-hover-color", str),
("toggle-theme-button-color", str), ("toggle-theme-button-color", str),
("copy-result-button-color", str), ("copy-result-button-color", str),
("copy-preview-result-url-button-color", str),
("date-color", str), ("date-color", str),
("special-event-color", str), ("special-event-color", str),
] ]