From 8bb6d09e6ebcc57d95841483b83bfeb5b5f0900c Mon Sep 17 00:00:00 2001 From: Dmitry Popov Date: Wed, 9 Oct 2024 17:41:02 +0400 Subject: [PATCH] fix(Signatures): Signatures update fixes fixes #25 --- assets/css/app.css | 6 + .../SystemSignaturesContent.tsx | 237 +++++++++++------- .../SystemSignatures/helpers/getActualSigs.ts | 5 +- .../SystemSignatures/helpers/getState.ts | 4 +- assets/lib/phoenix/index.js | 223 ++++++++++++++++ .../components/layouts/root.html.heex | 14 ++ .../controllers/blog_html/index.html.heex | 15 +- .../live/access_lists/access_lists_live.ex | 9 +- lib/wanderer_app_web/router.ex | 3 +- 9 files changed, 411 insertions(+), 105 deletions(-) diff --git a/assets/css/app.css b/assets/css/app.css index 0f4976ff..5274c984 100644 --- a/assets/css/app.css +++ b/assets/css/app.css @@ -28,6 +28,12 @@ body { font-weight: 500; } +#bg-canvas { + position: absolute; + width: 100vw; + height: 100vh; +} + .ccp-font { font-family: 'Shentox', 'Rogan', sans-serif !important; } diff --git a/assets/js/hooks/Mapper/components/mapInterface/widgets/SystemSignatures/SystemSignaturesContent/SystemSignaturesContent.tsx b/assets/js/hooks/Mapper/components/mapInterface/widgets/SystemSignatures/SystemSignaturesContent/SystemSignaturesContent.tsx index 5748ba74..042169e3 100644 --- a/assets/js/hooks/Mapper/components/mapInterface/widgets/SystemSignatures/SystemSignaturesContent/SystemSignaturesContent.tsx +++ b/assets/js/hooks/Mapper/components/mapInterface/widgets/SystemSignatures/SystemSignaturesContent/SystemSignaturesContent.tsx @@ -48,6 +48,8 @@ export const SystemSignaturesContent = ({ systemId, settings }: SystemSignatures const [signatures, setSignatures, signaturesRef] = useRefState([]); const [selectedSignatures, setSelectedSignatures] = useState([]); const [nameColumnWidth, setNameColumnWidth] = useState('auto'); + const [parsedSignatures, setParsedSignatures] = useState([]); + const [askUser, setAskUser] = useState(false); const [hoveredSig, setHoveredSig] = useState(null); @@ -90,8 +92,8 @@ export const SystemSignaturesContent = ({ systemId, settings }: SystemSignatures }, [outCommand, systemId]); const handleUpdateSignatures = useCallback( - async (newSignatures: SystemSignature[]) => { - const { added, updated, removed } = getActualSigs(signaturesRef.current, newSignatures); + async (newSignatures: SystemSignature[], updateOnly: boolean) => { + const { added, updated, removed } = getActualSigs(signaturesRef.current, newSignatures, updateOnly); const { signatures: updatedSignatures } = await outCommand({ type: OutCommand.updateSignatures, @@ -114,13 +116,26 @@ export const SystemSignaturesContent = ({ systemId, settings }: SystemSignatures return; } const selectedSignaturesEveIds = selectedSignatures.map(x => x.eve_id); - await handleUpdateSignatures(signatures.filter(x => !selectedSignaturesEveIds.includes(x.eve_id))); + await handleUpdateSignatures( + signatures.filter(x => !selectedSignaturesEveIds.includes(x.eve_id)), + false, + ); }, [handleUpdateSignatures, signatures, selectedSignatures]); const handleSelectAll = useCallback(() => { setSelectedSignatures(signatures); }, [signatures]); + const handleReplaceAll = useCallback(() => { + handleUpdateSignatures(parsedSignatures, false); + setAskUser(false); + }, [parsedSignatures, handleUpdateSignatures]); + + const handleUpdateOnly = useCallback(() => { + handleUpdateSignatures(parsedSignatures, true); + setAskUser(false); + }, [parsedSignatures, handleUpdateSignatures]); + useHotkey(true, ['a'], handleSelectAll); useHotkey(false, ['Backspace', 'Delete'], handleDeleteSelected); @@ -135,7 +150,12 @@ export const SystemSignaturesContent = ({ systemId, settings }: SystemSignatures settings.map(x => x.key), ); - handleUpdateSignatures(signatures); + if (!signaturesRef.current || !signaturesRef.current.length) { + handleUpdateSignatures(signatures, false); + } else { + setParsedSignatures(signatures); + setAskUser(true); + } }, [clipboardContent]); useEffect(() => { @@ -184,98 +204,125 @@ export const SystemSignaturesContent = ({ systemId, settings }: SystemSignatures // }; return ( -
- {filteredSignatures.length === 0 ? ( -
- No signatures + <> + {askUser && ( +
+
+
+
+ + +
+
+
- ) : ( - <> - setSelectedSignatures(e.value)} - dataKey="eve_id" - tableClassName="w-full select-none" - resizableColumns={false} - rowHover - selectAll - sortField={sortSettings.sortField} - sortOrder={sortSettings.sortOrder} - onSort={event => setSortSettings(() => ({ sortField: event.sortField, sortOrder: event.sortOrder }))} - onRowMouseEnter={compact || medium ? handleEnterRow : undefined} - onRowMouseLeave={compact || medium ? handleLeaveRow : undefined} - rowClassName={row => { - if (selectedSignatures.some(x => x.eve_id === row.eve_id)) { - return clsx(classes.TableRowCompact, 'bg-amber-500/50 hover:bg-amber-500/70 transition duration-200'); - } - - const dateClass = getRowColorByTimeLeft(row.updated_at ? new Date(row.updated_at) : undefined); - if (!dateClass) { - return clsx(classes.TableRowCompact, 'hover:bg-purple-400/20 transition duration-200'); - } - - return clsx(classes.TableRowCompact, dateClass); - }} - > - - - - - - - - {/**/} - - )} - : null} - /> -
+ {!askUser && ( +
+ {filteredSignatures.length === 0 ? ( +
+ No signatures +
+ ) : ( + <> + setSelectedSignatures(e.value)} + dataKey="eve_id" + tableClassName="w-full select-none" + resizableColumns={false} + rowHover + selectAll + sortField={sortSettings.sortField} + sortOrder={sortSettings.sortOrder} + onSort={event => setSortSettings(() => ({ sortField: event.sortField, sortOrder: event.sortOrder }))} + onRowMouseEnter={compact || medium ? handleEnterRow : undefined} + onRowMouseLeave={compact || medium ? handleLeaveRow : undefined} + rowClassName={row => { + if (selectedSignatures.some(x => x.eve_id === row.eve_id)) { + return clsx( + classes.TableRowCompact, + 'bg-amber-500/50 hover:bg-amber-500/70 transition duration-200', + ); + } + + const dateClass = getRowColorByTimeLeft(row.updated_at ? new Date(row.updated_at) : undefined); + if (!dateClass) { + return clsx(classes.TableRowCompact, 'hover:bg-purple-400/20 transition duration-200'); + } + + return clsx(classes.TableRowCompact, dateClass); + }} + > + + + + + + + + {/**/} + + + )} + : null} + /> +
+ )} + ); }; diff --git a/assets/js/hooks/Mapper/components/mapInterface/widgets/SystemSignatures/helpers/getActualSigs.ts b/assets/js/hooks/Mapper/components/mapInterface/widgets/SystemSignatures/helpers/getActualSigs.ts index 4798a6be..b19dbf4c 100644 --- a/assets/js/hooks/Mapper/components/mapInterface/widgets/SystemSignatures/helpers/getActualSigs.ts +++ b/assets/js/hooks/Mapper/components/mapInterface/widgets/SystemSignatures/helpers/getActualSigs.ts @@ -5,6 +5,7 @@ import { getState } from './getState.ts'; export const getActualSigs = ( oldSignatures: SystemSignature[], newSignatures: SystemSignature[], + updateOnly: boolean, ): { added: SystemSignature[]; updated: SystemSignature[]; removed: SystemSignature[] } => { const updated: SystemSignature[] = []; const removed: SystemSignature[] = []; @@ -20,7 +21,9 @@ export const getActualSigs = ( updated.push({ ...oldSig, group: newSig.group, name: newSig.name }); } } else { - removed.push(oldSig); + if (!updateOnly) { + removed.push(oldSig); + } } }); diff --git a/assets/js/hooks/Mapper/components/mapInterface/widgets/SystemSignatures/helpers/getState.ts b/assets/js/hooks/Mapper/components/mapInterface/widgets/SystemSignatures/helpers/getState.ts index 88f19979..b3df81a5 100644 --- a/assets/js/hooks/Mapper/components/mapInterface/widgets/SystemSignatures/helpers/getState.ts +++ b/assets/js/hooks/Mapper/components/mapInterface/widgets/SystemSignatures/helpers/getState.ts @@ -7,9 +7,9 @@ export const getState = (_: string[], newSig: SystemSignature) => { let state = -1; if (!newSig.group || newSig.group === '') { state = 0; - } else if (!!newSig.group && newSig.group !== '' && newSig.name === '') { + } else if (!newSig.name || newSig.name === '') { state = 1; - } else if (!!newSig.group && newSig.group !== '' && newSig.name !== '') { + } else if (newSig.name !== '') { state = 2; } return state; diff --git a/assets/lib/phoenix/index.js b/assets/lib/phoenix/index.js index 9a54b82e..4c6981f7 100644 --- a/assets/lib/phoenix/index.js +++ b/assets/lib/phoenix/index.js @@ -3,7 +3,230 @@ import 'phoenix_html'; import './live_reload.css'; +const animateBg = function (bgCanvas) { + const { TweenMax, _ } = window; + /** + * Utility function for returning a random integer in a given range + * @param {Int} max + * @param {Int} min + */ + const randomInRange = (max, min) => Math.floor(Math.random() * (max - min + 1)) + min; + const BASE_SIZE = 1; + const VELOCITY_INC = 1.01; + const VELOCITY_INIT_INC = 0.525; + const JUMP_VELOCITY_INC = 0.55; + const JUMP_SIZE_INC = 1.15; + const SIZE_INC = 1.01; + const RAD = Math.PI / 180; + const WARP_COLORS = [ + [197, 239, 247], + [25, 181, 254], + [77, 5, 232], + [165, 55, 253], + [255, 255, 255], + ]; + /** + * Class for storing the particle metadata + * position, size, length, speed etc. + */ + class Star { + STATE = { + alpha: Math.random(), + angle: randomInRange(0, 360) * RAD, + }; + reset = () => { + const angle = randomInRange(0, 360) * (Math.PI / 180); + const vX = Math.cos(angle); + const vY = Math.sin(angle); + const travelled = + Math.random() > 0.5 + ? Math.random() * Math.max(window.innerWidth, window.innerHeight) + Math.random() * (window.innerWidth * 0.24) + : Math.random() * (window.innerWidth * 0.25); + this.STATE = { + ...this.STATE, + iX: undefined, + iY: undefined, + active: travelled ? true : false, + x: Math.floor(vX * travelled) + window.innerWidth / 2, + vX, + y: Math.floor(vY * travelled) + window.innerHeight / 2, + vY, + size: BASE_SIZE, + }; + }; + constructor() { + this.reset(); + } + } + + const generateStarPool = size => new Array(size).fill().map(() => new Star()); + + // Class for the actual app + // Not too much happens in here + // Initiate the drawing process and listen for user interactions 👍 + class JumpToHyperspace { + STATE = { + stars: generateStarPool(300), + bgAlpha: 0, + sizeInc: SIZE_INC, + velocity: VELOCITY_INC, + }; + canvas = null; + context = null; + constructor(canvas) { + this.canvas = canvas; + this.context = canvas.getContext('2d'); + this.bind(); + this.setup(); + this.render(); + } + render = () => { + const { + STATE: { bgAlpha, velocity, sizeInc, initiating, jumping, stars }, + context, + render, + } = this; + // Clear the canvas + context.clearRect(0, 0, window.innerWidth, window.innerHeight); + if (bgAlpha > 0) { + context.fillStyle = `rgba(31, 58, 157, ${bgAlpha})`; + context.fillRect(0, 0, window.innerWidth, window.innerHeight); + } + // 1. Shall we add a new star + const nonActive = stars.filter(s => !s.STATE.active); + if (!initiating && nonActive.length > 0) { + // Introduce a star + nonActive[0].STATE.active = true; + } + // 2. Update the stars and draw them. + for (const star of stars.filter(s => s.STATE.active)) { + const { active, x, y, iX, iY, iVX, iVY, size, vX, vY } = star.STATE; + // Check if the star needs deactivating + if ( + ((iX || x) < 0 || (iX || x) > window.innerWidth || (iY || y) < 0 || (iY || y) > window.innerHeight) && + active && + !initiating + ) { + star.reset(true); + } else if (active) { + const newIX = initiating ? iX : iX + iVX; + const newIY = initiating ? iY : iY + iVY; + const newX = x + vX; + const newY = y + vY; + // Just need to work out if it overtakes the original line that's all + const caught = + (vX < 0 && newIX < x) || (vX > 0 && newIX > x) || (vY < 0 && newIY < y) || (vY > 0 && newIY > y); + star.STATE = { + ...star.STATE, + iX: caught ? undefined : newIX, + iY: caught ? undefined : newIY, + iVX: caught ? undefined : iVX * VELOCITY_INIT_INC, + iVY: caught ? undefined : iVY * VELOCITY_INIT_INC, + x: newX, + vX: star.STATE.vX * velocity, + y: newY, + vY: star.STATE.vY * velocity, + size: initiating ? size : size * (iX || iY ? SIZE_INC : sizeInc), + }; + let color = `rgba(255, 255, 255, ${star.STATE.alpha})`; + if (jumping) { + const [r, g, b] = WARP_COLORS[randomInRange(0, WARP_COLORS.length)]; + color = `rgba(${r}, ${g}, ${b}, ${star.STATE.alpha})`; + } + context.strokeStyle = color; + context.lineWidth = size; + context.beginPath(); + context.moveTo(star.STATE.iX || x, star.STATE.iY || y); + context.lineTo(star.STATE.x, star.STATE.y); + context.stroke(); + } + } + requestAnimationFrame(render); + }; + initiate = () => { + if (this.STATE.jumping || this.STATE.initiating) return; + this.STATE = { + ...this.STATE, + initiating: true, + initiateTimestamp: new Date().getTime(), + }; + TweenMax.to(this.STATE, 0.25, { velocity: VELOCITY_INIT_INC, bgAlpha: 0.3 }); + // When we initiate, stop the XY origin from moving so that we draw + // longer lines until the jump + for (const star of this.STATE.stars.filter(s => s.STATE.active)) { + star.STATE = { + ...star.STATE, + iX: star.STATE.x, + iY: star.STATE.y, + iVX: star.STATE.vX, + iVY: star.STATE.vY, + }; + } + }; + jump = () => { + this.STATE = { + ...this.STATE, + bgAlpha: 0, + jumping: true, + }; + TweenMax.to(this.STATE, 0.25, { velocity: JUMP_VELOCITY_INC, bgAlpha: 0.75, sizeInc: JUMP_SIZE_INC }); + setTimeout(() => { + this.STATE = { + ...this.STATE, + jumping: false, + }; + TweenMax.to(this.STATE, 0.25, { bgAlpha: 0, velocity: VELOCITY_INC, sizeInc: SIZE_INC }); + }, 5000); + }; + enter = () => { + if (this.STATE.jumping) return; + const { initiateTimestamp } = this.STATE; + this.STATE = { + ...this.STATE, + initiating: false, + initiateTimestamp: undefined, + }; + if (new Date().getTime() - initiateTimestamp > 600) { + this.jump(); + } else { + TweenMax.to(this.STATE, 0.25, { velocity: VELOCITY_INC, bgAlpha: 0 }); + } + }; + bind = () => { + this.canvas.addEventListener('mousedown', this.initiate); + this.canvas.addEventListener('touchstart', this.initiate); + this.canvas.addEventListener('mouseup', this.enter); + this.canvas.addEventListener('touchend', this.enter); + }; + setup = () => { + this.context.lineCap = 'round'; + this.canvas.height = window.innerHeight; + this.canvas.width = window.innerWidth; + }; + reset = () => { + this.STATE = { + ...this.STATE, + stars: generateStarPool(300), + }; + this.setup(); + }; + } + window.myJump = new JumpToHyperspace(bgCanvas); + window.addEventListener( + 'resize', + _.debounce(() => { + window.myJump.reset(); + }, 250), + ); +}; + document.addEventListener('DOMContentLoaded', function () { + // animage background + const canvas = document.getElementById('bg-canvas'); + if (canvas) { + animateBg(canvas); + } + // Select all buttons with the 'share-link' class const buttons = document.querySelectorAll('button.copy-link'); diff --git a/lib/wanderer_app_web/components/layouts/root.html.heex b/lib/wanderer_app_web/components/layouts/root.html.heex index aa81da8f..e1893ee8 100644 --- a/lib/wanderer_app_web/components/layouts/root.html.heex +++ b/lib/wanderer_app_web/components/layouts/root.html.heex @@ -43,6 +43,20 @@ > + + + + diff --git a/lib/wanderer_app_web/controllers/blog_html/index.html.heex b/lib/wanderer_app_web/controllers/blog_html/index.html.heex index d6910e35..80b44e30 100644 --- a/lib/wanderer_app_web/controllers/blog_html/index.html.heex +++ b/lib/wanderer_app_web/controllers/blog_html/index.html.heex @@ -1,4 +1,5 @@
+
@@ -11,9 +12,17 @@
- <.link navigate={~p"/auth/eve?invite=#{@invite_token}"}> - - +
+
+
+ <.link navigate={~p"/auth/eve?invite=#{@invite_token}"} class="opacity-100"> + + +
+
diff --git a/lib/wanderer_app_web/live/access_lists/access_lists_live.ex b/lib/wanderer_app_web/live/access_lists/access_lists_live.ex index 289f60c0..8798588d 100755 --- a/lib/wanderer_app_web/live/access_lists/access_lists_live.ex +++ b/lib/wanderer_app_web/live/access_lists/access_lists_live.ex @@ -319,11 +319,14 @@ defmodule WandererAppWeb.AccessListsLive do @impl true def handle_info({:search, text}, socket) do - first_character_id = - socket.assigns.user_character_ids + + active_character_id = + socket.assigns.current_user.characters + |> Enum.filter(fn character -> not is_nil(character.refresh_token) end) + |> Enum.map(& &1.id) |> Enum.at(0) - {:ok, options} = search(first_character_id, text) + {:ok, options} = search(active_character_id, text) send_update(LiveSelect.Component, options: options, id: socket.assigns.member_search_id) {:noreply, socket |> assign(member_search_options: options)} diff --git a/lib/wanderer_app_web/router.ex b/lib/wanderer_app_web/router.ex index 5f0270ab..8a051e2a 100644 --- a/lib/wanderer_app_web/router.ex +++ b/lib/wanderer_app_web/router.ex @@ -58,7 +58,8 @@ defmodule WandererAppWeb.Router do ~w('unsafe-inline'), ~w(https://unpkg.com), ~w(https://w.appzi.io), - ~w(https://www.googletagmanager.com) + ~w(https://www.googletagmanager.com), + ~w(https://cdnjs.cloudflare.com) ], style_src: @style_src, img_src: @img_src,