mirror of
https://github.com/exogen/vl2-forge.git
synced 2026-04-27 15:25:28 +00:00
Add action log viewer
This commit is contained in:
parent
e38b3678cb
commit
175534b788
20 changed files with 215 additions and 28 deletions
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
1
docs/_next/static/chunks/94730671-6ced0342e6a25b8f.js
Normal file
1
docs/_next/static/chunks/94730671-6ced0342e6a25b8f.js
Normal file
|
|
@ -0,0 +1 @@
|
|||
"use strict";(self.webpackChunk_N_E=self.webpackChunk_N_E||[]).push([[522],{3051:(t,L,r)=>{r.d(L,{qGf:()=>e});var a=r(1810);function e(t){return(0,a.w_)({tag:"svg",attr:{viewBox:"0 0 24 24",fill:"currentColor"},child:[{tag:"path",attr:{d:"M12 22C6.47715 22 2 17.5228 2 12C2 6.47715 6.47715 2 12 2C17.5228 2 22 6.47715 22 12C22 17.5228 17.5228 22 12 22ZM12 10.5858L9.17157 7.75736L7.75736 9.17157L10.5858 12L7.75736 14.8284L9.17157 16.2426L12 13.4142L14.8284 16.2426L16.2426 14.8284L13.4142 12L16.2426 9.17157L14.8284 7.75736L12 10.5858Z"},child:[]}]})(t)}}}]);
|
||||
File diff suppressed because one or more lines are too long
1
docs/_next/static/chunks/app/page-2dac80ee609f3188.js
Normal file
1
docs/_next/static/chunks/app/page-2dac80ee609f3188.js
Normal file
File diff suppressed because one or more lines are too long
1
docs/_next/static/chunks/f8025e75-eec57ce6fbd95417.js
Normal file
1
docs/_next/static/chunks/f8025e75-eec57ce6fbd95417.js
Normal file
|
|
@ -0,0 +1 @@
|
|||
"use strict";(self.webpackChunk_N_E=self.webpackChunk_N_E||[]).push([[950],{2655:(l,a,t)=>{t.d(a,{m2k:()=>c});var r=t(1810);function c(l){return(0,r.w_)({tag:"svg",attr:{viewBox:"0 0 24 24",fill:"currentColor"},child:[{tag:"path",attr:{d:"M12 1.67c.955 0 1.845 .467 2.39 1.247l.105 .16l8.114 13.548a2.914 2.914 0 0 1 -2.307 4.363l-.195 .008h-16.225a2.914 2.914 0 0 1 -2.582 -4.2l.099 -.185l8.11 -13.538a2.914 2.914 0 0 1 2.491 -1.403zm.01 13.33l-.127 .007a1 1 0 0 0 0 1.986l.117 .007l.127 -.007a1 1 0 0 0 0 -1.986l-.117 -.007zm-.01 -7a1 1 0 0 0 -.993 .883l-.007 .117v4l.007 .117a1 1 0 0 0 1.986 0l.007 -.117v-4l-.007 -.117a1 1 0 0 0 -.993 -.883z"},child:[]}]})(l)}}}]);
|
||||
|
|
@ -1 +1 @@
|
|||
(()=>{"use strict";var e={},t={};function r(o){var n=t[o];if(void 0!==n)return n.exports;var a=t[o]={id:o,loaded:!1,exports:{}},i=!0;try{e[o].call(a.exports,a,a.exports,r),i=!1}finally{i&&delete t[o]}return a.loaded=!0,a.exports}r.m=e,(()=>{var e=[];r.O=(t,o,n,a)=>{if(o){a=a||0;for(var i=e.length;i>0&&e[i-1][2]>a;i--)e[i]=e[i-1];e[i]=[o,n,a];return}for(var l=1/0,i=0;i<e.length;i++){for(var[o,n,a]=e[i],u=!0,d=0;d<o.length;d++)(!1&a||l>=a)&&Object.keys(r.O).every(e=>r.O[e](o[d]))?o.splice(d--,1):(u=!1,a<l&&(l=a));if(u){e.splice(i--,1);var c=n();void 0!==c&&(t=c)}}return t}})(),r.n=e=>{var t=e&&e.__esModule?()=>e.default:()=>e;return r.d(t,{a:t}),t},(()=>{var e,t=Object.getPrototypeOf?e=>Object.getPrototypeOf(e):e=>e.__proto__;r.t=function(o,n){if(1&n&&(o=this(o)),8&n||"object"==typeof o&&o&&(4&n&&o.__esModule||16&n&&"function"==typeof o.then))return o;var a=Object.create(null);r.r(a);var i={};e=e||[null,t({}),t([]),t(t)];for(var l=2&n&&o;"object"==typeof l&&!~e.indexOf(l);l=t(l))Object.getOwnPropertyNames(l).forEach(e=>i[e]=()=>o[e]);return i.default=()=>o,r.d(a,i),a}})(),r.d=(e,t)=>{for(var o in t)r.o(t,o)&&!r.o(e,o)&&Object.defineProperty(e,o,{enumerable:!0,get:t[o]})},r.f={},r.e=e=>Promise.all(Object.keys(r.f).reduce((t,o)=>(r.f[o](e,t),t),[])),r.u=e=>{},r.miniCssF=e=>{},r.g=function(){if("object"==typeof globalThis)return globalThis;try{return this||Function("return this")()}catch(e){if("object"==typeof window)return window}}(),r.o=(e,t)=>Object.prototype.hasOwnProperty.call(e,t),(()=>{var e={},t="_N_E:";r.l=(o,n,a,i)=>{if(e[o]){e[o].push(n);return}if(void 0!==a)for(var l,u,d=document.getElementsByTagName("script"),c=0;c<d.length;c++){var s=d[c];if(s.getAttribute("src")==o||s.getAttribute("data-webpack")==t+a){l=s;break}}l||(u=!0,(l=document.createElement("script")).charset="utf-8",l.timeout=120,r.nc&&l.setAttribute("nonce",r.nc),l.setAttribute("data-webpack",t+a),l.src=r.tu(o)),e[o]=[n];var f=(t,r)=>{l.onerror=l.onload=null,clearTimeout(p);var n=e[o];if(delete e[o],l.parentNode&&l.parentNode.removeChild(l),n&&n.forEach(e=>e(r)),t)return t(r)},p=setTimeout(f.bind(null,void 0,{type:"timeout",target:l}),12e4);l.onerror=f.bind(null,l.onerror),l.onload=f.bind(null,l.onload),u&&document.head.appendChild(l)}})(),r.r=e=>{"undefined"!=typeof Symbol&&Symbol.toStringTag&&Object.defineProperty(e,Symbol.toStringTag,{value:"Module"}),Object.defineProperty(e,"__esModule",{value:!0})},r.nmd=e=>(e.paths=[],e.children||(e.children=[]),e),(()=>{var e;r.tt=()=>(void 0===e&&(e={createScriptURL:e=>e},"undefined"!=typeof trustedTypes&&trustedTypes.createPolicy&&(e=trustedTypes.createPolicy("nextjs#bundler",e))),e)})(),r.tu=e=>r.tt().createScriptURL(e),r.p="/vl2-forge/_next/",(()=>{var e={272:0,465:0,113:0};r.f.j=(t,o)=>{var n=r.o(e,t)?e[t]:void 0;if(0!==n){if(n)o.push(n[2]);else if(/^(113|272|465)$/.test(t))e[t]=0;else{var a=new Promise((r,o)=>n=e[t]=[r,o]);o.push(n[2]=a);var i=r.p+r.u(t),l=Error();r.l(i,o=>{if(r.o(e,t)&&(0!==(n=e[t])&&(e[t]=void 0),n)){var a=o&&("load"===o.type?"missing":o.type),i=o&&o.target&&o.target.src;l.message="Loading chunk "+t+" failed.\n("+a+": "+i+")",l.name="ChunkLoadError",l.type=a,l.request=i,n[1](l)}},"chunk-"+t,t)}}},r.O.j=t=>0===e[t];var t=(t,o)=>{var n,a,[i,l,u]=o,d=0;if(i.some(t=>0!==e[t])){for(n in l)r.o(l,n)&&(r.m[n]=l[n]);if(u)var c=u(r)}for(t&&t(o);d<i.length;d++)a=i[d],r.o(e,a)&&e[a]&&e[a][0](),e[a]=0;return r.O(c)},o=self.webpackChunk_N_E=self.webpackChunk_N_E||[];o.forEach(t.bind(null,0)),o.push=t.bind(null,o.push.bind(o))})()})();
|
||||
(()=>{"use strict";var e={},t={};function r(o){var n=t[o];if(void 0!==n)return n.exports;var a=t[o]={id:o,loaded:!1,exports:{}},i=!0;try{e[o].call(a.exports,a,a.exports,r),i=!1}finally{i&&delete t[o]}return a.loaded=!0,a.exports}r.m=e,(()=>{var e=[];r.O=(t,o,n,a)=>{if(o){a=a||0;for(var i=e.length;i>0&&e[i-1][2]>a;i--)e[i]=e[i-1];e[i]=[o,n,a];return}for(var l=1/0,i=0;i<e.length;i++){for(var[o,n,a]=e[i],u=!0,d=0;d<o.length;d++)(!1&a||l>=a)&&Object.keys(r.O).every(e=>r.O[e](o[d]))?o.splice(d--,1):(u=!1,a<l&&(l=a));if(u){e.splice(i--,1);var c=n();void 0!==c&&(t=c)}}return t}})(),r.n=e=>{var t=e&&e.__esModule?()=>e.default:()=>e;return r.d(t,{a:t}),t},(()=>{var e,t=Object.getPrototypeOf?e=>Object.getPrototypeOf(e):e=>e.__proto__;r.t=function(o,n){if(1&n&&(o=this(o)),8&n||"object"==typeof o&&o&&(4&n&&o.__esModule||16&n&&"function"==typeof o.then))return o;var a=Object.create(null);r.r(a);var i={};e=e||[null,t({}),t([]),t(t)];for(var l=2&n&&o;"object"==typeof l&&!~e.indexOf(l);l=t(l))Object.getOwnPropertyNames(l).forEach(e=>i[e]=()=>o[e]);return i.default=()=>o,r.d(a,i),a}})(),r.d=(e,t)=>{for(var o in t)r.o(t,o)&&!r.o(e,o)&&Object.defineProperty(e,o,{enumerable:!0,get:t[o]})},r.f={},r.e=e=>Promise.all(Object.keys(r.f).reduce((t,o)=>(r.f[o](e,t),t),[])),r.u=e=>{},r.miniCssF=e=>{},r.g=function(){if("object"==typeof globalThis)return globalThis;try{return this||Function("return this")()}catch(e){if("object"==typeof window)return window}}(),r.o=(e,t)=>Object.prototype.hasOwnProperty.call(e,t),(()=>{var e={},t="_N_E:";r.l=(o,n,a,i)=>{if(e[o]){e[o].push(n);return}if(void 0!==a)for(var l,u,d=document.getElementsByTagName("script"),c=0;c<d.length;c++){var s=d[c];if(s.getAttribute("src")==o||s.getAttribute("data-webpack")==t+a){l=s;break}}l||(u=!0,(l=document.createElement("script")).charset="utf-8",l.timeout=120,r.nc&&l.setAttribute("nonce",r.nc),l.setAttribute("data-webpack",t+a),l.src=r.tu(o)),e[o]=[n];var f=(t,r)=>{l.onerror=l.onload=null,clearTimeout(p);var n=e[o];if(delete e[o],l.parentNode&&l.parentNode.removeChild(l),n&&n.forEach(e=>e(r)),t)return t(r)},p=setTimeout(f.bind(null,void 0,{type:"timeout",target:l}),12e4);l.onerror=f.bind(null,l.onerror),l.onload=f.bind(null,l.onload),u&&document.head.appendChild(l)}})(),r.r=e=>{"undefined"!=typeof Symbol&&Symbol.toStringTag&&Object.defineProperty(e,Symbol.toStringTag,{value:"Module"}),Object.defineProperty(e,"__esModule",{value:!0})},r.nmd=e=>(e.paths=[],e.children||(e.children=[]),e),(()=>{var e;r.tt=()=>(void 0===e&&(e={createScriptURL:e=>e},"undefined"!=typeof trustedTypes&&trustedTypes.createPolicy&&(e=trustedTypes.createPolicy("nextjs#bundler",e))),e)})(),r.tu=e=>r.tt().createScriptURL(e),r.p="/vl2-forge/_next/",(()=>{var e={272:0,465:0,995:0};r.f.j=(t,o)=>{var n=r.o(e,t)?e[t]:void 0;if(0!==n){if(n)o.push(n[2]);else if(/^(272|465|995)$/.test(t))e[t]=0;else{var a=new Promise((r,o)=>n=e[t]=[r,o]);o.push(n[2]=a);var i=r.p+r.u(t),l=Error();r.l(i,o=>{if(r.o(e,t)&&(0!==(n=e[t])&&(e[t]=void 0),n)){var a=o&&("load"===o.type?"missing":o.type),i=o&&o.target&&o.target.src;l.message="Loading chunk "+t+" failed.\n("+a+": "+i+")",l.name="ChunkLoadError",l.type=a,l.request=i,n[1](l)}},"chunk-"+t,t)}}},r.O.j=t=>0===e[t];var t=(t,o)=>{var n,a,[i,l,u]=o,d=0;if(i.some(t=>0!==e[t])){for(n in l)r.o(l,n)&&(r.m[n]=l[n]);if(u)var c=u(r)}for(t&&t(o);d<i.length;d++)a=i[d],r.o(e,a)&&e[a]&&e[a][0](),e[a]=0;return r.O(c)},o=self.webpackChunk_N_E=self.webpackChunk_N_E||[];o.forEach(t.bind(null,0)),o.push=t.bind(null,o.push.bind(o))})()})();
|
||||
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
|
|
@ -1,7 +1,7 @@
|
|||
7:"$Sreact.fragment"
|
||||
8:I[9275,[],""]
|
||||
9:I[1343,[],""]
|
||||
a:I[7341,["665","static/chunks/f97e080b-d92374f1605c166e.js","51","static/chunks/795d4814-df14aa386162ffad.js","212","static/chunks/59650de3-3851382c06f0a1a6.js","516","static/chunks/f7333993-0b21ce6d3b378608.js","675","static/chunks/b563f954-1a29a90b42165810.js","240","static/chunks/53c13509-7351503a4af8a85a.js","699","static/chunks/8e1d74a4-900578ac2c71efa7.js","515","static/chunks/515-35a068dc133b7a18.js","931","static/chunks/app/page-198e743de2f7340f.js"],"Forge",1]
|
||||
a:I[4538,["950","static/chunks/f8025e75-eec57ce6fbd95417.js","522","static/chunks/94730671-6ced0342e6a25b8f.js","665","static/chunks/f97e080b-d92374f1605c166e.js","51","static/chunks/795d4814-df14aa386162ffad.js","212","static/chunks/59650de3-3851382c06f0a1a6.js","516","static/chunks/f7333993-0b21ce6d3b378608.js","675","static/chunks/b563f954-1a29a90b42165810.js","240","static/chunks/53c13509-7351503a4af8a85a.js","699","static/chunks/8e1d74a4-900578ac2c71efa7.js","515","static/chunks/515-a62e2db5bca20cf3.js","931","static/chunks/app/page-2dac80ee609f3188.js"],"Forge",1]
|
||||
b:I[3120,[],"OutletBoundary"]
|
||||
d:I[3120,[],"MetadataBoundary"]
|
||||
f:I[3120,[],"ViewportBoundary"]
|
||||
|
|
@ -11,8 +11,8 @@ f:I[3120,[],"ViewportBoundary"]
|
|||
3:HL["/vl2-forge/_next/static/media/a521fcc400cf9065-s.p.ttf","font",{"crossOrigin":"","type":"font/ttf"}]
|
||||
4:HL["/vl2-forge/_next/static/media/e9ed9197b1d41e00-s.p.woff2","font",{"crossOrigin":"","type":"font/woff2"}]
|
||||
5:HL["/vl2-forge/_next/static/css/bdff6c7d2b4adc3b.css","style"]
|
||||
6:HL["/vl2-forge/_next/static/css/d8287fbacbbad8f6.css","style"]
|
||||
0:{"P":null,"b":"9Pi0et4BW69YTW10MWfB6","p":"/vl2-forge","c":["",""],"i":false,"f":[[["",{"children":["__PAGE__",{}]},"$undefined","$undefined",true],["",["$","$7","c",{"children":[[["$","link","0",{"rel":"stylesheet","href":"/vl2-forge/_next/static/css/bdff6c7d2b4adc3b.css","precedence":"next","crossOrigin":"$undefined","nonce":"$undefined"}]],["$","html",null,{"lang":"en","className":"__variable_6dd175 __variable_60c549 __variable_b97ccf","children":["$","body",null,{"children":["$","$L8",null,{"parallelRouterKey":"children","segmentPath":["children"],"error":"$undefined","errorStyles":"$undefined","errorScripts":"$undefined","template":["$","$L9",null,{}],"templateStyles":"$undefined","templateScripts":"$undefined","notFound":[["$","title",null,{"children":"404: This page could not be found."}],["$","div",null,{"style":{"fontFamily":"system-ui,\"Segoe UI\",Roboto,Helvetica,Arial,sans-serif,\"Apple Color Emoji\",\"Segoe UI Emoji\"","height":"100vh","textAlign":"center","display":"flex","flexDirection":"column","alignItems":"center","justifyContent":"center"},"children":["$","div",null,{"children":[["$","style",null,{"dangerouslySetInnerHTML":{"__html":"body{color:#000;background:#fff;margin:0}.next-error-h1{border-right:1px solid rgba(0,0,0,.3)}@media (prefers-color-scheme:dark){body{color:#fff;background:#000}.next-error-h1{border-right:1px solid rgba(255,255,255,.3)}}"}}],["$","h1",null,{"className":"next-error-h1","style":{"display":"inline-block","margin":"0 20px 0 0","padding":"0 23px 0 0","fontSize":24,"fontWeight":500,"verticalAlign":"top","lineHeight":"49px"},"children":"404"}],["$","div",null,{"style":{"display":"inline-block"},"children":["$","h2",null,{"style":{"fontSize":14,"fontWeight":400,"lineHeight":"49px","margin":0},"children":"This page could not be found."}]}]]}]}]],"notFoundStyles":[]}]}]}]]}],{"children":["__PAGE__",["$","$7","c",{"children":[["$","$La",null,{}],[["$","link","0",{"rel":"stylesheet","href":"/vl2-forge/_next/static/css/d8287fbacbbad8f6.css","precedence":"next","crossOrigin":"$undefined","nonce":"$undefined"}]],["$","$Lb",null,{"children":"$Lc"}]]}],{},null]},null],["$","$7","h",{"children":[null,["$","$7","Bbs2r012w6VYSLPXygGDr",{"children":[["$","$Ld",null,{"children":"$Le"}],["$","$Lf",null,{"children":"$L10"}],["$","meta",null,{"name":"next-size-adjust"}]]}]]}]]],"m":"$undefined","G":"$11","s":false,"S":true}
|
||||
6:HL["/vl2-forge/_next/static/css/8f45e42583e71b0d.css","style"]
|
||||
0:{"P":null,"b":"doB4mbbCjK_svkG4sfPx3","p":"/vl2-forge","c":["",""],"i":false,"f":[[["",{"children":["__PAGE__",{}]},"$undefined","$undefined",true],["",["$","$7","c",{"children":[[["$","link","0",{"rel":"stylesheet","href":"/vl2-forge/_next/static/css/bdff6c7d2b4adc3b.css","precedence":"next","crossOrigin":"$undefined","nonce":"$undefined"}]],["$","html",null,{"lang":"en","className":"__variable_6dd175 __variable_60c549 __variable_b97ccf","children":["$","body",null,{"children":["$","$L8",null,{"parallelRouterKey":"children","segmentPath":["children"],"error":"$undefined","errorStyles":"$undefined","errorScripts":"$undefined","template":["$","$L9",null,{}],"templateStyles":"$undefined","templateScripts":"$undefined","notFound":[["$","title",null,{"children":"404: This page could not be found."}],["$","div",null,{"style":{"fontFamily":"system-ui,\"Segoe UI\",Roboto,Helvetica,Arial,sans-serif,\"Apple Color Emoji\",\"Segoe UI Emoji\"","height":"100vh","textAlign":"center","display":"flex","flexDirection":"column","alignItems":"center","justifyContent":"center"},"children":["$","div",null,{"children":[["$","style",null,{"dangerouslySetInnerHTML":{"__html":"body{color:#000;background:#fff;margin:0}.next-error-h1{border-right:1px solid rgba(0,0,0,.3)}@media (prefers-color-scheme:dark){body{color:#fff;background:#000}.next-error-h1{border-right:1px solid rgba(255,255,255,.3)}}"}}],["$","h1",null,{"className":"next-error-h1","style":{"display":"inline-block","margin":"0 20px 0 0","padding":"0 23px 0 0","fontSize":24,"fontWeight":500,"verticalAlign":"top","lineHeight":"49px"},"children":"404"}],["$","div",null,{"style":{"display":"inline-block"},"children":["$","h2",null,{"style":{"fontSize":14,"fontWeight":400,"lineHeight":"49px","margin":0},"children":"This page could not be found."}]}]]}]}]],"notFoundStyles":[]}]}]}]]}],{"children":["__PAGE__",["$","$7","c",{"children":[["$","$La",null,{}],[["$","link","0",{"rel":"stylesheet","href":"/vl2-forge/_next/static/css/8f45e42583e71b0d.css","precedence":"next","crossOrigin":"$undefined","nonce":"$undefined"}]],["$","$Lb",null,{"children":"$Lc"}]]}],{},null]},null],["$","$7","h",{"children":[null,["$","$7","zy8WzxHRJrJcftPOY8oU_",{"children":[["$","$Ld",null,{"children":"$Le"}],["$","$Lf",null,{"children":"$L10"}],["$","meta",null,{"name":"next-size-adjust"}]]}]]}]]],"m":"$undefined","G":"$11","s":false,"S":true}
|
||||
10:[["$","meta","0",{"name":"viewport","content":"width=device-width, initial-scale=1"}]]
|
||||
e:[["$","meta","0",{"charSet":"utf-8"}],["$","title","1",{"children":"VL2 Forge"}],["$","meta","2",{"name":"description","content":"Create .vl2 files for Tribes 2"}]]
|
||||
c:null
|
||||
|
|
|
|||
|
|
@ -1,5 +1,11 @@
|
|||
"use client";
|
||||
import { useCallback, useMemo, useState, useTransition } from "react";
|
||||
import {
|
||||
useCallback,
|
||||
useEffect,
|
||||
useMemo,
|
||||
useState,
|
||||
useTransition,
|
||||
} from "react";
|
||||
import { useDropzone } from "react-dropzone";
|
||||
import orderBy from "lodash.orderby";
|
||||
import { FaGithub } from "react-icons/fa";
|
||||
|
|
@ -8,39 +14,67 @@ import { FileItem } from "./FileItem";
|
|||
import { DownloadForm } from "./DownloadForm";
|
||||
import { handleInputFile } from "./utils";
|
||||
import styles from "./Forge.module.css";
|
||||
import { Messages } from "./Messages";
|
||||
|
||||
const defaultFileData = {
|
||||
files: new Map(),
|
||||
actionLog: [],
|
||||
};
|
||||
|
||||
export function Forge() {
|
||||
const [isPending, startTransition] = useTransition();
|
||||
const [loadingCount, setLoadingCount] = useState(0);
|
||||
const [actionLog, setActionLog] = useState(() => []);
|
||||
const [files, setFiles] = useState(() => new Map());
|
||||
const [fileData, setFileData] = useState(defaultFileData);
|
||||
|
||||
const { files, actionLog } = fileData;
|
||||
|
||||
const onDrop = useCallback(async (acceptedFiles) => {
|
||||
setLoadingCount((count) => count + 1);
|
||||
const actionLog = [];
|
||||
const finalMap = new Map();
|
||||
const orderedAcceptedFiles = orderBy(
|
||||
Array.from(acceptedFiles),
|
||||
[(file) => (file.name ?? "").toLowerCase()],
|
||||
["asc"]
|
||||
);
|
||||
const allFiles: Array<Map<string, any>> = await Promise.all(
|
||||
acceptedFiles.map((file) => handleInputFile(file))
|
||||
orderedAcceptedFiles.map((file) => handleInputFile(file))
|
||||
);
|
||||
allFiles.forEach((map) => {
|
||||
map.forEach((file, path) => {
|
||||
if (finalMap.has(path)) {
|
||||
actionLog.push({
|
||||
type: "overwrite",
|
||||
type: "BATCH_OVERWRITE",
|
||||
path,
|
||||
oldSource: finalMap.get(path).source,
|
||||
newSource: file.source,
|
||||
});
|
||||
}
|
||||
finalMap.set(path, file);
|
||||
});
|
||||
});
|
||||
startTransition(() => {
|
||||
setFiles((prevMap) => {
|
||||
return new Map([
|
||||
...Array.from(prevMap.entries()),
|
||||
...Array.from(finalMap.entries()),
|
||||
]);
|
||||
setFileData((prevData) => {
|
||||
const { files: prevFiles, actionLog: prevActionLog } = prevData;
|
||||
const newActionLog = [...prevActionLog, ...actionLog];
|
||||
const newFiles = new Map(prevFiles);
|
||||
finalMap.forEach((file, path) => {
|
||||
if (newFiles.has(path)) {
|
||||
newActionLog.push({
|
||||
type: "NEW_OVERWRITE",
|
||||
path,
|
||||
oldSource: newFiles.get(path).source,
|
||||
newSource: file.source,
|
||||
});
|
||||
}
|
||||
newFiles.set(path, file);
|
||||
});
|
||||
setActionLog((prevLog) => [...prevLog, ...actionLog]);
|
||||
return {
|
||||
files: newFiles,
|
||||
actionLog:
|
||||
newActionLog.length === prevActionLog.length
|
||||
? prevActionLog
|
||||
: newActionLog,
|
||||
};
|
||||
});
|
||||
setLoadingCount((count) => count - 1);
|
||||
}, []);
|
||||
|
|
@ -73,21 +107,27 @@ export function Forge() {
|
|||
);
|
||||
|
||||
const handleDelete = useCallback((path) => {
|
||||
setFiles((files) => {
|
||||
const newFiles = new Map(files);
|
||||
setFileData((prevFileData) => {
|
||||
const newFiles = new Map(prevFileData.files);
|
||||
newFiles.delete(path);
|
||||
return newFiles;
|
||||
return {
|
||||
files: newFiles,
|
||||
actionLog: prevFileData.actionLog,
|
||||
};
|
||||
});
|
||||
}, []);
|
||||
|
||||
const handleRename = useCallback((oldPath, newPath) => {
|
||||
setFiles((files) => {
|
||||
const file = files.get(oldPath);
|
||||
setFileData((prevFileData) => {
|
||||
const file = prevFileData.files.get(oldPath);
|
||||
const newFile = { ...file, path: newPath };
|
||||
const newFiles = new Map(files);
|
||||
const newFiles = new Map(prevFileData.files);
|
||||
newFiles.delete(oldPath);
|
||||
newFiles.set(newPath, newFile);
|
||||
return newFiles;
|
||||
return {
|
||||
files: newFiles,
|
||||
actionLog: prevFileData.actionLog,
|
||||
};
|
||||
});
|
||||
}, []);
|
||||
|
||||
|
|
@ -144,6 +184,7 @@ export function Forge() {
|
|||
<FaGithub aria-label="GitHub" />
|
||||
</a>
|
||||
<DownloadForm fileList={fileList} />
|
||||
<Messages actionLog={actionLog} />
|
||||
</footer>
|
||||
</section>
|
||||
);
|
||||
|
|
|
|||
69
src/Messages.module.css
Normal file
69
src/Messages.module.css
Normal file
|
|
@ -0,0 +1,69 @@
|
|||
.MessagesButton,
|
||||
.CloseButton {
|
||||
background: transparent;
|
||||
border: 0;
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
display: grid;
|
||||
place-content: center;
|
||||
width: 40px;
|
||||
height: 40px;
|
||||
font-size: 32px;
|
||||
color: rgba(255, 255, 255, 0.3);
|
||||
transition: color 200ms;
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
.MessagesButton.NewMessages {
|
||||
color: rgba(255, 162, 43, 1);
|
||||
}
|
||||
|
||||
.MessagesButton svg {
|
||||
pointer-events: none;
|
||||
}
|
||||
|
||||
.CloseButton {
|
||||
position: absolute;
|
||||
top: 12px;
|
||||
right: 12px;
|
||||
}
|
||||
|
||||
.CloseButton:hover {
|
||||
color: rgba(255, 255, 255, 1);
|
||||
}
|
||||
|
||||
.ActionLog {
|
||||
position: fixed;
|
||||
top: 0;
|
||||
left: 0;
|
||||
right: 0;
|
||||
bottom: 0;
|
||||
font-size: 12px;
|
||||
background: rgba(0, 0, 0, 0.9);
|
||||
color: rgba(255, 162, 43, 1);
|
||||
padding: 32px;
|
||||
overflow: auto;
|
||||
z-index: 2;
|
||||
}
|
||||
|
||||
.ActionLog del {
|
||||
font-style: normal;
|
||||
text-decoration: none;
|
||||
border-bottom: 2px solid red;
|
||||
}
|
||||
|
||||
.ActionLog ins {
|
||||
font-style: normal;
|
||||
text-decoration: none;
|
||||
border-bottom: 2px solid green;
|
||||
}
|
||||
|
||||
.Path {
|
||||
color: rgb(255, 237, 212);
|
||||
}
|
||||
|
||||
@media (max-width: 767px) {
|
||||
.MessagesButton {
|
||||
display: none;
|
||||
}
|
||||
}
|
||||
72
src/Messages.tsx
Normal file
72
src/Messages.tsx
Normal file
|
|
@ -0,0 +1,72 @@
|
|||
import { useEffect, useState } from "react";
|
||||
import { TbAlertTriangleFilled } from "react-icons/tb";
|
||||
import { RiCloseCircleFill } from "react-icons/ri";
|
||||
import styles from "./Messages.module.css";
|
||||
|
||||
export function Messages({ actionLog }) {
|
||||
const [isOpen, setIsOpen] = useState(false);
|
||||
const [hasNewMessages, setHasNewMessages] = useState(false);
|
||||
|
||||
useEffect(() => {
|
||||
if (!isOpen) {
|
||||
setHasNewMessages(false);
|
||||
}
|
||||
}, [isOpen]);
|
||||
|
||||
useEffect(() => {
|
||||
if (actionLog.length > 0) {
|
||||
setHasNewMessages(true);
|
||||
}
|
||||
}, [actionLog]);
|
||||
|
||||
return (
|
||||
<>
|
||||
<button
|
||||
type="button"
|
||||
className={`${styles.MessagesButton} ${
|
||||
hasNewMessages ? styles.NewMessages : ""
|
||||
}`}
|
||||
onClick={() => {
|
||||
setIsOpen((isOpen) => !isOpen);
|
||||
}}
|
||||
>
|
||||
<TbAlertTriangleFilled />
|
||||
</button>
|
||||
<div className={styles.ActionLog} hidden={!isOpen}>
|
||||
<button
|
||||
className={styles.CloseButton}
|
||||
type="button"
|
||||
onClick={() => {
|
||||
setIsOpen(false);
|
||||
}}
|
||||
>
|
||||
<RiCloseCircleFill />
|
||||
</button>
|
||||
{actionLog.map((message, i) => {
|
||||
switch (message.type) {
|
||||
case "BATCH_OVERWRITE":
|
||||
return (
|
||||
<p key={i}>
|
||||
File at <span className={styles.Path}>{message.path}</span>{" "}
|
||||
from <del>{message.oldSource}</del> was replaced with the one
|
||||
from <ins>{message.newSource}</ins> because of the priority in
|
||||
which it was handled.
|
||||
</p>
|
||||
);
|
||||
case "NEW_OVERWRITE":
|
||||
return (
|
||||
<p key={i}>
|
||||
File at <span className={styles.Path}>{message.path}</span>{" "}
|
||||
from <del>{message.oldSource}</del> was replaced with the one
|
||||
from <ins>{message.newSource}</ins> because it is a newer
|
||||
upload.
|
||||
</p>
|
||||
);
|
||||
default:
|
||||
return null;
|
||||
}
|
||||
})}
|
||||
</div>
|
||||
</>
|
||||
);
|
||||
}
|
||||
|
|
@ -7,6 +7,7 @@ export type FileType = {
|
|||
};
|
||||
|
||||
export type FileEntry = {
|
||||
source: string | null;
|
||||
path: string;
|
||||
buffer: ArrayBuffer;
|
||||
blobUri: string | null;
|
||||
|
|
@ -145,6 +146,7 @@ export async function handleZipFile(file) {
|
|||
path = detectBestPath(path);
|
||||
const buffer = await fileObj.async("arraybuffer");
|
||||
const fileEntry = {
|
||||
source: file.name || null,
|
||||
path,
|
||||
buffer,
|
||||
blobUri: null,
|
||||
|
|
@ -192,6 +194,7 @@ export async function handleOtherFile(file) {
|
|||
reader.readAsArrayBuffer(file);
|
||||
});
|
||||
const fileEntry = {
|
||||
source: "direct upload",
|
||||
path,
|
||||
buffer,
|
||||
blobUri: null,
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue