updated tarot frame for mobile and desktop usability
This commit is contained in:
+7
-2
@@ -378,9 +378,14 @@
|
||||
}));
|
||||
}
|
||||
|
||||
async function loadGematriaWordsByValue(value) {
|
||||
async function loadGematriaWordsByValue(value, options = {}) {
|
||||
const ciphers = Array.isArray(options?.ciphers)
|
||||
? options.ciphers.map((cipherId) => String(cipherId || "").trim()).filter(Boolean).join(",")
|
||||
: String(options?.ciphers || "").trim();
|
||||
|
||||
return fetchJson(buildApiUrl("/api/v1/gematria/words", {
|
||||
value
|
||||
value,
|
||||
ciphers
|
||||
}));
|
||||
}
|
||||
|
||||
|
||||
+140
-11
@@ -907,6 +907,30 @@
|
||||
flex-wrap: wrap;
|
||||
}
|
||||
|
||||
.tarot-frame-selection-chip {
|
||||
padding: 10px 14px;
|
||||
border: 1px solid rgba(56, 189, 248, 0.55);
|
||||
border-radius: 999px;
|
||||
background: linear-gradient(180deg, rgba(8, 47, 73, 0.96), rgba(12, 74, 110, 0.98));
|
||||
color: #e0f2fe;
|
||||
cursor: pointer;
|
||||
font-size: 13px;
|
||||
font-weight: 800;
|
||||
letter-spacing: 0.02em;
|
||||
box-shadow: 0 10px 24px rgba(2, 132, 199, 0.18);
|
||||
}
|
||||
|
||||
.tarot-frame-selection-chip:hover,
|
||||
.tarot-frame-selection-chip:focus-visible {
|
||||
border-color: rgba(125, 211, 252, 0.92);
|
||||
background: linear-gradient(180deg, rgba(12, 74, 110, 0.98), rgba(14, 116, 144, 1));
|
||||
color: #f0f9ff;
|
||||
}
|
||||
|
||||
.tarot-frame-selection-chip[hidden] {
|
||||
display: none !important;
|
||||
}
|
||||
|
||||
.tarot-frame-layout-panel {
|
||||
position: absolute;
|
||||
top: calc(100% + 10px);
|
||||
@@ -1681,7 +1705,8 @@
|
||||
gap: 12px;
|
||||
}
|
||||
|
||||
.tarot-frame-card-insert-menu {
|
||||
.tarot-frame-card-insert-menu,
|
||||
.tarot-frame-card-action-menu {
|
||||
position: fixed;
|
||||
z-index: 41;
|
||||
width: min(240px, calc(100vw - 24px));
|
||||
@@ -1696,11 +1721,13 @@
|
||||
box-shadow: 0 24px 70px rgba(0, 0, 0, 0.42);
|
||||
}
|
||||
|
||||
.tarot-frame-card-insert-menu[hidden] {
|
||||
.tarot-frame-card-insert-menu[hidden],
|
||||
.tarot-frame-card-action-menu[hidden] {
|
||||
display: none !important;
|
||||
}
|
||||
|
||||
.tarot-frame-card-insert-menu-item {
|
||||
.tarot-frame-card-insert-menu-item,
|
||||
.tarot-frame-card-action-menu-item {
|
||||
padding: 11px 12px;
|
||||
border: 1px solid rgba(99, 102, 241, 0.22);
|
||||
border-radius: 12px;
|
||||
@@ -1713,7 +1740,9 @@
|
||||
}
|
||||
|
||||
.tarot-frame-card-insert-menu-item:hover,
|
||||
.tarot-frame-card-insert-menu-item:focus-visible {
|
||||
.tarot-frame-card-insert-menu-item:focus-visible,
|
||||
.tarot-frame-card-action-menu-item:hover,
|
||||
.tarot-frame-card-action-menu-item:focus-visible {
|
||||
border-color: rgba(165, 180, 252, 0.9);
|
||||
background: rgba(49, 46, 129, 0.34);
|
||||
color: #f8fafc;
|
||||
@@ -2052,6 +2081,11 @@
|
||||
border-radius: 8px;
|
||||
}
|
||||
|
||||
.tarot-frame-slot.is-selected {
|
||||
box-shadow: 0 0 0 2px #38bdf8, 0 0 0 6px rgba(56, 189, 248, 0.2);
|
||||
border-radius: 8px;
|
||||
}
|
||||
|
||||
.tarot-frame-slot.is-drag-source {
|
||||
opacity: 0.42;
|
||||
}
|
||||
@@ -2072,6 +2106,8 @@
|
||||
}
|
||||
|
||||
.tarot-frame-card {
|
||||
--frame-card-rotation: 0deg;
|
||||
--frame-card-hover-lift: 0px;
|
||||
position: absolute;
|
||||
inset: 0;
|
||||
padding: 0;
|
||||
@@ -2086,6 +2122,12 @@
|
||||
user-select: none;
|
||||
touch-action: none;
|
||||
-webkit-touch-callout: none;
|
||||
transform: translateY(var(--frame-card-hover-lift)) rotate(var(--frame-card-rotation));
|
||||
transform-origin: center center;
|
||||
}
|
||||
|
||||
.tarot-frame-card.is-flipped {
|
||||
--frame-card-rotation: 180deg;
|
||||
}
|
||||
|
||||
.tarot-frame-card.is-empty {
|
||||
@@ -2096,13 +2138,18 @@
|
||||
}
|
||||
|
||||
.tarot-frame-card:hover {
|
||||
transform: translateY(-2px);
|
||||
--frame-card-hover-lift: -2px;
|
||||
filter: drop-shadow(0 10px 18px rgba(15, 23, 42, 0.38));
|
||||
}
|
||||
|
||||
.tarot-frame-card.is-selected {
|
||||
filter: drop-shadow(0 12px 20px rgba(14, 165, 233, 0.34));
|
||||
}
|
||||
|
||||
.tarot-frame-card.is-empty:hover {
|
||||
border-color: transparent;
|
||||
box-shadow: none;
|
||||
--frame-card-hover-lift: 0px;
|
||||
transform: none;
|
||||
}
|
||||
|
||||
@@ -2112,6 +2159,7 @@
|
||||
}
|
||||
|
||||
.tarot-frame-card:hover {
|
||||
--frame-card-hover-lift: 0px;
|
||||
transform: none;
|
||||
filter: none;
|
||||
}
|
||||
@@ -2288,6 +2336,28 @@
|
||||
transform: translate(-50%, -50%);
|
||||
}
|
||||
|
||||
.tarot-frame-drag-ghost.is-flipped {
|
||||
transform: translate(-50%, -50%) rotate(180deg);
|
||||
}
|
||||
|
||||
.tarot-frame-drag-ghost-count {
|
||||
position: absolute;
|
||||
top: 8px;
|
||||
right: 8px;
|
||||
min-width: 26px;
|
||||
height: 26px;
|
||||
padding: 0 8px;
|
||||
border-radius: 999px;
|
||||
display: grid;
|
||||
place-items: center;
|
||||
background: rgba(56, 189, 248, 0.94);
|
||||
color: #082f49;
|
||||
font-size: 12px;
|
||||
font-weight: 800;
|
||||
line-height: 1;
|
||||
box-shadow: 0 8px 20px rgba(2, 132, 199, 0.34);
|
||||
}
|
||||
|
||||
.tarot-frame-drag-ghost img {
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
@@ -2410,6 +2480,13 @@
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
.tarot-frame-selection-chip {
|
||||
order: -1;
|
||||
width: 100%;
|
||||
justify-content: center;
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
.tarot-frame-settings-panel {
|
||||
left: 0;
|
||||
right: auto;
|
||||
@@ -2430,8 +2507,8 @@
|
||||
}
|
||||
|
||||
.tarot-frame-card-badge {
|
||||
font-size: 7px;
|
||||
padding: 3px 4px;
|
||||
font-size: 11px;
|
||||
padding: 4px 5px;
|
||||
}
|
||||
|
||||
.tarot-frame-card-text-face {
|
||||
@@ -4227,6 +4304,56 @@
|
||||
font-size: 13px;
|
||||
}
|
||||
|
||||
.alpha-gematria-cipher[hidden] {
|
||||
display: none;
|
||||
}
|
||||
|
||||
.alpha-gematria-reverse-ciphers {
|
||||
display: flex;
|
||||
flex-wrap: wrap;
|
||||
gap: 8px;
|
||||
}
|
||||
|
||||
.alpha-gematria-reverse-ciphers[hidden] {
|
||||
display: none;
|
||||
}
|
||||
|
||||
.alpha-gematria-reverse-cipher-option {
|
||||
display: inline-flex;
|
||||
align-items: center;
|
||||
gap: 6px;
|
||||
padding: 6px 10px;
|
||||
border: 1px solid #3f3f46;
|
||||
border-radius: 999px;
|
||||
background: #101018;
|
||||
color: #d4d4d8;
|
||||
cursor: pointer;
|
||||
-webkit-user-select: none;
|
||||
user-select: none;
|
||||
}
|
||||
|
||||
.alpha-gematria-reverse-cipher-option:has(input:checked) {
|
||||
border-color: #6366f1;
|
||||
background: #1c1b35;
|
||||
color: #eef2ff;
|
||||
}
|
||||
|
||||
.alpha-gematria-reverse-cipher-option input {
|
||||
margin: 0;
|
||||
accent-color: #818cf8;
|
||||
}
|
||||
|
||||
.alpha-gematria-reverse-cipher-name {
|
||||
font-size: 12px;
|
||||
line-height: 1.2;
|
||||
}
|
||||
|
||||
.alpha-gematria-reverse-cipher-hint {
|
||||
color: #a1a1aa;
|
||||
font-size: 11px;
|
||||
line-height: 1.4;
|
||||
}
|
||||
|
||||
.alpha-gematria-input {
|
||||
min-height: 54px;
|
||||
resize: vertical;
|
||||
@@ -4330,15 +4457,17 @@
|
||||
}
|
||||
|
||||
@media (max-width: 900px) {
|
||||
.alpha-gematria-controls.is-input-priority-mode,
|
||||
.alpha-gematria-controls:has(.alpha-gematria-cipher:disabled) {
|
||||
.alpha-gematria-controls.is-input-priority-mode {
|
||||
grid-template-columns: minmax(0, 1fr);
|
||||
}
|
||||
|
||||
.alpha-gematria-controls.is-input-priority-mode .alpha-gematria-field-cipher,
|
||||
.alpha-gematria-controls:has(.alpha-gematria-cipher:disabled) .alpha-gematria-field-cipher {
|
||||
.alpha-gematria-controls.is-input-priority-mode .alpha-gematria-field-cipher {
|
||||
display: none;
|
||||
}
|
||||
|
||||
.alpha-gematria-controls.is-reverse-cipher-mode {
|
||||
grid-template-columns: minmax(0, 1fr);
|
||||
}
|
||||
}
|
||||
|
||||
.alpha-tabs {
|
||||
|
||||
+144
-13
@@ -12,7 +12,9 @@
|
||||
modeEls: [],
|
||||
matchesEl: null,
|
||||
inputLabelEl: null,
|
||||
cipherLabelEl: null
|
||||
cipherLabelEl: null,
|
||||
reverseCiphersEl: null,
|
||||
reverseCipherHintEl: null
|
||||
})
|
||||
};
|
||||
|
||||
@@ -23,6 +25,7 @@
|
||||
activeCipherId: "",
|
||||
forwardInputText: "",
|
||||
reverseInputText: "",
|
||||
reverseSelectedCipherIds: null,
|
||||
anagramInputText: "",
|
||||
dictionaryInputText: "",
|
||||
activeMode: "forward",
|
||||
@@ -52,7 +55,9 @@
|
||||
modeEls: [],
|
||||
matchesEl: null,
|
||||
inputLabelEl: null,
|
||||
cipherLabelEl: null
|
||||
cipherLabelEl: null,
|
||||
reverseCiphersEl: null,
|
||||
reverseCipherHintEl: null
|
||||
};
|
||||
}
|
||||
|
||||
@@ -273,6 +278,80 @@
|
||||
return ciphers.find((cipher) => cipher.id === selectedId) || ciphers[0];
|
||||
}
|
||||
|
||||
function getGematriaCiphers() {
|
||||
const db = state.db || getFallbackGematriaDb();
|
||||
return Array.isArray(db.ciphers) ? db.ciphers : [];
|
||||
}
|
||||
|
||||
function normalizeSelectedReverseCipherIds(rawCipherIds) {
|
||||
const ciphers = getGematriaCiphers();
|
||||
const requestedIds = Array.isArray(rawCipherIds)
|
||||
? rawCipherIds.map((cipherId) => String(cipherId || "").trim()).filter(Boolean)
|
||||
: [];
|
||||
const requestedIdSet = new Set(requestedIds);
|
||||
|
||||
return ciphers
|
||||
.map((cipher) => cipher.id)
|
||||
.filter((cipherId) => requestedIdSet.has(cipherId));
|
||||
}
|
||||
|
||||
function getDefaultReverseCipherIds() {
|
||||
const activeCipher = getActiveGematriaCipher();
|
||||
if (activeCipher?.id) {
|
||||
return [activeCipher.id];
|
||||
}
|
||||
|
||||
const firstCipher = getGematriaCiphers()[0];
|
||||
return firstCipher?.id ? [firstCipher.id] : [];
|
||||
}
|
||||
|
||||
function getSelectedReverseCipherIds() {
|
||||
if (state.reverseSelectedCipherIds === null) {
|
||||
return getDefaultReverseCipherIds();
|
||||
}
|
||||
|
||||
return normalizeSelectedReverseCipherIds(state.reverseSelectedCipherIds);
|
||||
}
|
||||
|
||||
function setSelectedReverseCipherIds(rawCipherIds) {
|
||||
state.reverseSelectedCipherIds = normalizeSelectedReverseCipherIds(rawCipherIds);
|
||||
}
|
||||
|
||||
function renderReverseCipherOptions() {
|
||||
const { reverseCiphersEl } = getElements();
|
||||
if (!reverseCiphersEl) {
|
||||
return;
|
||||
}
|
||||
|
||||
const ciphers = getGematriaCiphers();
|
||||
const selectedCipherIds = new Set(getSelectedReverseCipherIds());
|
||||
const fragment = document.createDocumentFragment();
|
||||
|
||||
ciphers.forEach((cipher) => {
|
||||
const optionEl = document.createElement("label");
|
||||
optionEl.className = "alpha-gematria-reverse-cipher-option";
|
||||
|
||||
const checkboxEl = document.createElement("input");
|
||||
checkboxEl.type = "checkbox";
|
||||
checkboxEl.value = cipher.id;
|
||||
checkboxEl.checked = selectedCipherIds.has(cipher.id);
|
||||
checkboxEl.setAttribute("aria-label", cipher.name);
|
||||
optionEl.appendChild(checkboxEl);
|
||||
|
||||
const textEl = document.createElement("span");
|
||||
textEl.className = "alpha-gematria-reverse-cipher-name";
|
||||
textEl.textContent = cipher.name;
|
||||
if (cipher.description) {
|
||||
textEl.title = cipher.description;
|
||||
}
|
||||
optionEl.appendChild(textEl);
|
||||
|
||||
fragment.appendChild(optionEl);
|
||||
});
|
||||
|
||||
reverseCiphersEl.replaceChildren(fragment);
|
||||
}
|
||||
|
||||
function renderGematriaCipherOptions() {
|
||||
const { cipherEl } = getElements();
|
||||
if (!cipherEl) {
|
||||
@@ -296,6 +375,14 @@
|
||||
const activeCipher = getActiveGematriaCipher();
|
||||
state.activeCipherId = activeCipher?.id || "";
|
||||
cipherEl.value = state.activeCipherId;
|
||||
|
||||
if (state.reverseSelectedCipherIds === null) {
|
||||
state.reverseSelectedCipherIds = getDefaultReverseCipherIds();
|
||||
} else {
|
||||
state.reverseSelectedCipherIds = normalizeSelectedReverseCipherIds(state.reverseSelectedCipherIds);
|
||||
}
|
||||
|
||||
renderReverseCipherOptions();
|
||||
}
|
||||
|
||||
function setMatchesMessage(matchesEl, message) {
|
||||
@@ -332,12 +419,14 @@
|
||||
modeEls,
|
||||
matchesEl,
|
||||
inputLabelEl,
|
||||
cipherLabelEl
|
||||
cipherLabelEl,
|
||||
reverseCiphersEl,
|
||||
reverseCipherHintEl
|
||||
} = getElements();
|
||||
|
||||
const reverseMode = isReverseMode();
|
||||
const anagramMode = isAnagramMode();
|
||||
const dictionaryMode = isDictionaryMode();
|
||||
const dictionaryMode = isDictionaryMode();
|
||||
const radioEls = getModeElements(modeEls);
|
||||
|
||||
radioEls.forEach((element) => {
|
||||
@@ -351,16 +440,32 @@
|
||||
}
|
||||
|
||||
if (cipherLabelEl) {
|
||||
cipherLabelEl.textContent = (reverseMode || anagramMode || dictionaryMode) ? "Cipher (not used in this mode)" : "Cipher";
|
||||
cipherLabelEl.textContent = reverseMode
|
||||
? "Ciphers"
|
||||
: ((anagramMode || dictionaryMode) ? "Cipher (not used in this mode)" : "Cipher");
|
||||
}
|
||||
|
||||
if (cipherEl) {
|
||||
const disableCipher = reverseMode || anagramMode || dictionaryMode;
|
||||
const hideCipherField = anagramMode || dictionaryMode;
|
||||
cipherEl.disabled = disableCipher;
|
||||
cipherEl.hidden = reverseMode;
|
||||
const cipherFieldEl = cipherEl.closest(".alpha-gematria-field");
|
||||
const controlsEl = cipherEl.closest(".alpha-gematria-controls");
|
||||
cipherFieldEl?.classList.toggle("is-disabled", disableCipher);
|
||||
controlsEl?.classList.toggle("is-input-priority-mode", disableCipher);
|
||||
cipherFieldEl?.classList.toggle("is-disabled", hideCipherField);
|
||||
controlsEl?.classList.toggle("is-input-priority-mode", hideCipherField);
|
||||
controlsEl?.classList.toggle("is-reverse-cipher-mode", reverseMode);
|
||||
}
|
||||
|
||||
if (reverseCiphersEl) {
|
||||
if (reverseMode) {
|
||||
renderReverseCipherOptions();
|
||||
}
|
||||
reverseCiphersEl.hidden = !reverseMode;
|
||||
}
|
||||
|
||||
if (reverseCipherHintEl) {
|
||||
reverseCipherHintEl.hidden = !reverseMode;
|
||||
}
|
||||
|
||||
if (inputEl) {
|
||||
@@ -400,12 +505,15 @@
|
||||
}
|
||||
|
||||
async function loadReverseLookup(value) {
|
||||
const cacheKey = String(value);
|
||||
const selectedCipherIds = getSelectedReverseCipherIds();
|
||||
const cacheKey = `${String(value)}::${selectedCipherIds.join(",")}`;
|
||||
if (state.reverseLookupCache.has(cacheKey)) {
|
||||
return state.reverseLookupCache.get(cacheKey);
|
||||
}
|
||||
|
||||
const payload = await window.TarotDataService?.loadGematriaWordsByValue?.(value);
|
||||
const payload = await window.TarotDataService?.loadGematriaWordsByValue?.(value, {
|
||||
ciphers: selectedCipherIds
|
||||
});
|
||||
state.reverseLookupCache.set(cacheKey, payload);
|
||||
return payload;
|
||||
}
|
||||
@@ -493,7 +601,7 @@
|
||||
.map((cipher) => `${String(cipher?.name || cipher?.id || "Unknown")} ${formatCount(cipher?.count)}`)
|
||||
.join(" · ");
|
||||
|
||||
breakdownEl.textContent = `Found ${formatCount(displayCount)} matches across ${formatCount(displayCipherCount)} ciphers.${topCipherSummary ? ` Top ciphers: ${topCipherSummary}.` : ""}${displayCount > visibleMatches.length ? ` Showing first ${formatCount(visibleMatches.length)}.` : ""}`;
|
||||
breakdownEl.textContent = `Found ${formatCount(displayCount)} matches across ${formatCount(displayCipherCount)} selected ciphers.${topCipherSummary ? ` Top ciphers: ${topCipherSummary}.` : ""}${displayCount > visibleMatches.length ? ` Showing first ${formatCount(visibleMatches.length)}.` : ""}`;
|
||||
|
||||
const fragment = document.createDocumentFragment();
|
||||
visibleMatches.forEach((match) => {
|
||||
@@ -546,11 +654,20 @@
|
||||
}
|
||||
|
||||
const rawValue = state.reverseInputText;
|
||||
const selectedCipherIds = getSelectedReverseCipherIds();
|
||||
if (!String(rawValue || "").trim()) {
|
||||
resultEl.textContent = "Value: --";
|
||||
breakdownEl.textContent = "Enter a whole number to find words across all available ciphers.";
|
||||
breakdownEl.textContent = "Enter a whole number and choose one or more ciphers to narrow reverse matches.";
|
||||
matchesEl.hidden = false;
|
||||
setMatchesMessage(matchesEl, "Reverse lookup searches the API-backed gematria word index.");
|
||||
setMatchesMessage(matchesEl, "Reverse lookup searches the API-backed gematria word index using the selected ciphers only.");
|
||||
return;
|
||||
}
|
||||
|
||||
if (!selectedCipherIds.length) {
|
||||
resultEl.textContent = "Value: --";
|
||||
breakdownEl.textContent = "Choose at least one cipher before running reverse lookup.";
|
||||
matchesEl.hidden = false;
|
||||
setMatchesMessage(matchesEl, "Select one or more ciphers to limit reverse gematria matches.");
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -865,7 +982,7 @@
|
||||
}
|
||||
|
||||
function bindGematriaListeners() {
|
||||
const { cipherEl, inputEl, modeEls } = getElements();
|
||||
const { cipherEl, inputEl, modeEls, reverseCiphersEl } = getElements();
|
||||
if (state.listenersBound || !cipherEl || !inputEl) {
|
||||
return;
|
||||
}
|
||||
@@ -900,6 +1017,20 @@
|
||||
});
|
||||
});
|
||||
|
||||
reverseCiphersEl?.addEventListener("change", (event) => {
|
||||
const target = event.target;
|
||||
if (!(target instanceof HTMLInputElement) || target.type !== "checkbox") {
|
||||
return;
|
||||
}
|
||||
|
||||
const nextSelectedCipherIds = Array.from(reverseCiphersEl.querySelectorAll("input[type='checkbox']:checked"))
|
||||
.map((element) => String(element.value || "").trim())
|
||||
.filter(Boolean);
|
||||
setSelectedReverseCipherIds(nextSelectedCipherIds);
|
||||
renderReverseCipherOptions();
|
||||
renderGematriaResult();
|
||||
});
|
||||
|
||||
state.listenersBound = true;
|
||||
}
|
||||
|
||||
|
||||
+6
-1
@@ -53,6 +53,7 @@
|
||||
let searchInputEl, searchClearEl, typeFilterEl;
|
||||
let gematriaCipherEl, gematriaInputEl, gematriaResultEl, gematriaBreakdownEl;
|
||||
let gematriaModeEls, gematriaMatchesEl, gematriaInputLabelEl, gematriaCipherLabelEl;
|
||||
let gematriaReverseCiphersEl, gematriaReverseCipherHintEl;
|
||||
|
||||
function getElements() {
|
||||
listEl = document.getElementById("alpha-letter-list");
|
||||
@@ -77,6 +78,8 @@
|
||||
gematriaMatchesEl = document.getElementById("alpha-gematria-matches");
|
||||
gematriaInputLabelEl = document.getElementById("alpha-gematria-input-label");
|
||||
gematriaCipherLabelEl = document.getElementById("alpha-gematria-cipher-label");
|
||||
gematriaReverseCiphersEl = document.getElementById("alpha-gematria-reverse-ciphers");
|
||||
gematriaReverseCipherHintEl = document.getElementById("alpha-gematria-reverse-cipher-hint");
|
||||
}
|
||||
|
||||
function getGematriaElements() {
|
||||
@@ -89,7 +92,9 @@
|
||||
modeEls: gematriaModeEls,
|
||||
matchesEl: gematriaMatchesEl,
|
||||
inputLabelEl: gematriaInputLabelEl,
|
||||
cipherLabelEl: gematriaCipherLabelEl
|
||||
cipherLabelEl: gematriaCipherLabelEl,
|
||||
reverseCiphersEl: gematriaReverseCiphersEl,
|
||||
reverseCipherHintEl: gematriaReverseCipherHintEl
|
||||
};
|
||||
}
|
||||
|
||||
|
||||
+911
-69
File diff suppressed because it is too large
Load Diff
Reference in New Issue
Block a user