mirror of
				https://github.com/mickael-kerjean/filestash.git
				synced 2025-11-01 02:43:35 +08:00 
			
		
		
		
	feature (speed): improve loading speed
This commit is contained in:
		| @ -1,4 +1,4 @@ | ||||
| const CACHENAME = "assets"; | ||||
| let VERSION = null; | ||||
|  | ||||
| /* | ||||
|  * This Service Worker is an optional optimisation to load the app faster. | ||||
| @ -41,7 +41,7 @@ self.addEventListener("fetch", async(event) => { | ||||
|     if (!event.request.url.startsWith(location.origin + "/assets/")) return; | ||||
|  | ||||
|     event.respondWith((async() => { | ||||
|         const cache = await caches.open(CACHENAME); | ||||
|         const cache = await caches.open(VERSION); | ||||
|         const cachedResponse = await cache.match(event.request); | ||||
|         if (cachedResponse) return cachedResponse; | ||||
|         return fetch(event.request); | ||||
| @ -51,19 +51,42 @@ self.addEventListener("fetch", async(event) => { | ||||
| self.addEventListener("message", (event) => { | ||||
|     if (event.data.type === "preload") handlePreloadMessage( | ||||
|         event.data.payload, | ||||
|         event.data.clear, | ||||
|         event.data.version, | ||||
|         () => event.source.postMessage({ type: "preload", status: "ok" }), | ||||
|         (err) => event.source.postMessage({ type: "preload", status: "error", msg: err.message }), | ||||
|     ); | ||||
| }); | ||||
|  | ||||
| async function handlePreloadMessage(chunks, resolve, reject, id) { | ||||
| async function handlePreloadMessage(chunks, clear, version, resolve, reject) { | ||||
|     VERSION = version; | ||||
|     const cleanup = []; | ||||
|     try { | ||||
|         await caches.delete(CACHENAME); | ||||
|         const cache = await caches.open(CACHENAME); | ||||
|         await Promise.all(chunks.map((urls) => { | ||||
|             return preload({ urls, cache, cleanup }); | ||||
|         })); | ||||
|         let execHTTP = true; | ||||
|         await caches.keys().then(async(names) => { | ||||
|             for (let i=0; i<names.length; i++) { | ||||
|                 if (names[i] === VERSION && !clear) { | ||||
|                     execHTTP = false; | ||||
|                     return; | ||||
|                 } | ||||
|                 await caches.delete(names[i]); | ||||
|             } | ||||
|         }); | ||||
|         if (execHTTP) { | ||||
|             const cache = await caches.open(VERSION); | ||||
|             chunks = await Promise.all(chunks.map(async(urls) => { | ||||
|                 const missing = []; | ||||
|                 await Promise.all(urls.map(async(url) => { | ||||
|                     if (!await cache.match(location.origin + url)) missing.push(url); | ||||
|                 })); | ||||
|                 return missing; | ||||
|             })); | ||||
|             if (chunks.filter((urls) => urls.length > 0).length > 0) { | ||||
|                 await Promise.all(chunks.map((urls) => { | ||||
|                     return preload({ urls, cache, cleanup }); | ||||
|                 })); | ||||
|             } | ||||
|         } | ||||
|         resolve(); | ||||
|     } catch (err) { | ||||
|         console.log("ERR", err); | ||||
| @ -88,7 +111,7 @@ async function preload({ urls, cache, cleanup }) { | ||||
|         await cache.put( | ||||
|             location.origin + url, | ||||
|             new Response( | ||||
|                 decoder(new Blob([Uint8Array.from(atob(event.data), (c) => c.charCodeAt(0))]).stream()), | ||||
|                 decoder(new Blob([base128Decode(event.data)]).stream()), | ||||
|                 { headers: { "Content-Type": mime } }, | ||||
|             ), | ||||
|         ); | ||||
| @ -117,3 +140,22 @@ async function preload({ urls, cache, cleanup }) { | ||||
|         }; | ||||
|     }); | ||||
| } | ||||
|  | ||||
| function base128Decode(s) { // encoder is in server/ctrl/static.go -> encodeB128 | ||||
|     const out = new Uint8Array(Math.floor((s.length * 7) / 8) + 1); | ||||
|     let acc = 0; | ||||
|     let bits = 0; | ||||
|     let oi = 0; | ||||
|     for (let i = 0; i < s.length; i++) { | ||||
|         const ch = s.charCodeAt(i); | ||||
|         const digit = ch & 0x7F; // undo 0x80 masking for NUL/LF/CR | ||||
|         acc = (acc << 7) | digit; | ||||
|         bits += 7; | ||||
|         while (bits >= 8) { | ||||
|             bits -= 8; | ||||
|             out[oi++] = (acc >> bits) & 0xFF; | ||||
|             acc &= (1 << bits) - 1; | ||||
|         } | ||||
|     } | ||||
|     return out.subarray(0, oi); | ||||
| } | ||||
|  | ||||
| @ -57,7 +57,12 @@ | ||||
|                              resolve(); | ||||
|                          }); | ||||
|                  }); | ||||
|                  register.active.postMessage({ "type": "preload", "payload": URLS }); | ||||
|                  register.active.postMessage({ | ||||
|                      "type": "preload", | ||||
|                      "payload": URLS, | ||||
|                      "version": "{{ .version }}".substring(0, 7) + "::{{ .hash }}", | ||||
|                      "clear": {{ .clear }}, | ||||
|                  }); | ||||
|                  await new Promise((resolve, reject) => navigator.serviceWorker.addEventListener("message", (event) => { | ||||
|                      if (event.data && event.data.type === "preload") { | ||||
|                          if (event.data.status !== "ok") console.log(`turboload failure data=${JSON.stringify(event.data)}`); | ||||
|  | ||||
| @ -29,7 +29,7 @@ func PluginExportHandler(ctx *App, res http.ResponseWriter, req *http.Request) { | ||||
| 			} | ||||
| 		} | ||||
| 	} | ||||
| 	SendSuccessResult(res, plgExports) | ||||
| 	SendSuccessResultWithEtagAndGzip(res, req, plgExports) | ||||
| } | ||||
|  | ||||
| func PluginStaticHandler(ctx *App, res http.ResponseWriter, req *http.Request) { | ||||
|  | ||||
| @ -2,8 +2,8 @@ package ctrl | ||||
|  | ||||
| import ( | ||||
| 	"bytes" | ||||
| 	"compress/gzip" | ||||
| 	_ "embed" | ||||
| 	"encoding/base64" | ||||
| 	"encoding/json" | ||||
| 	"fmt" | ||||
| 	"io" | ||||
| @ -205,32 +205,42 @@ func ServeFile(chroot string) func(*App, http.ResponseWriter, *http.Request) { | ||||
| } | ||||
|  | ||||
| func ServeIndex(indexPath string) func(*App, http.ResponseWriter, *http.Request) { | ||||
| 	// STEP1: pull the data from the embed | ||||
| 	file, err := WWWPublic.Open(indexPath) | ||||
| 	if err != nil { | ||||
| 		return func(ctx *App, res http.ResponseWriter, req *http.Request) { | ||||
| 			http.NotFound(res, req) | ||||
| 		} | ||||
| 	} | ||||
| 	defer file.Close() | ||||
|  | ||||
| 	// STEP2: compile the template | ||||
| 	b, err := io.ReadAll(file) | ||||
| 	if err != nil { | ||||
| 		return func(ctx *App, res http.ResponseWriter, req *http.Request) { | ||||
| 			SendErrorResult(res, err) | ||||
| 		} | ||||
| 	} | ||||
| 	tmpl := template.Must(template.New(indexPath).Parse(string(b))) | ||||
| 	tmpl = template.Must(tmpl.Parse(string(TmplLoader))) | ||||
|  | ||||
| 	return func(ctx *App, res http.ResponseWriter, req *http.Request) { | ||||
| 		head := res.Header() | ||||
|  | ||||
| 		// STEP1: pull the data from the embed | ||||
| 		file, err := WWWPublic.Open(indexPath) | ||||
| 		if err != nil { | ||||
| 			http.NotFound(res, req) | ||||
| 			return | ||||
| 		} | ||||
| 		defer file.Close() | ||||
|  | ||||
| 		// STEP2: compile the template | ||||
| 		b, err := io.ReadAll(file) | ||||
| 		if err != nil { | ||||
| 			SendErrorResult(res, err) | ||||
| 			return | ||||
| 		var out io.Writer = res | ||||
| 		if strings.Contains(req.Header.Get("Accept-Encoding"), "gzip") { | ||||
| 			head.Set("Content-Encoding", "gzip") | ||||
| 			gz := gzip.NewWriter(res) | ||||
| 			defer gz.Close() | ||||
| 			out = gz | ||||
| 		} | ||||
| 		head.Set("Content-Type", "text/html") | ||||
| 		res.WriteHeader(http.StatusOK) | ||||
| 		tmpl := template.Must(template.New(indexPath).Parse(string(b))) | ||||
| 		tmpl = template.Must(tmpl.Parse(string(TmplLoader))) | ||||
| 		tmpl.Execute(res, map[string]any{ | ||||
| 		tmpl.Execute(out, map[string]any{ | ||||
| 			"base":    WithBase("/"), | ||||
| 			"version": BUILD_REF, | ||||
| 			"license": LICENSE, | ||||
| 			"preload": preload(), | ||||
| 			"clear":   req.Header.Get("Cache-Control") == "no-cache", | ||||
| 			"hash":    signature(), | ||||
| 		}) | ||||
| 	} | ||||
| } | ||||
| @ -265,7 +275,7 @@ func ServeBundle(ctx *App, res http.ResponseWriter, req *http.Request) { | ||||
| 		fmt.Fprintf(res, "id: %s\n", urls[i]) | ||||
| 		fmt.Fprintf(res, "data: ") | ||||
| 		b, _ := io.ReadAll(file) | ||||
| 		res.Write([]byte(base64.StdEncoding.EncodeToString(b))) | ||||
| 		res.Write([]byte(encodeB128(b))) | ||||
| 		fmt.Fprintf(res, "\n\n") | ||||
| 		res.(http.Flusher).Flush() | ||||
| 		file.Close() | ||||
| @ -274,6 +284,34 @@ func ServeBundle(ctx *App, res http.ResponseWriter, req *http.Request) { | ||||
| 	res.(http.Flusher).Flush() | ||||
| } | ||||
|  | ||||
| func encodeB128(src []byte) string { // decoder is in public/assets/sw.js | ||||
| 	if len(src) == 0 { | ||||
| 		return "" | ||||
| 	} | ||||
| 	out := make([]rune, 0, len(src)+len(src)/7) // N + N/7 runes (+tail) | ||||
| 	var bits uint32 | ||||
| 	var n int // bits held in 'bits' | ||||
| 	emit := func(d byte) { | ||||
| 		if d == 0x00 || d == 0x0A || d == 0x0D { // NUL, LF, CR | ||||
| 			out = append(out, rune(0x80|d)) // 2-byte UTF-8, still decodable as d&0x7F | ||||
| 			return | ||||
| 		} | ||||
| 		out = append(out, rune(d)) // ASCII, 1-byte UTF-8 | ||||
| 	} | ||||
| 	for _, b := range src { | ||||
| 		bits = (bits << 8) | uint32(b) | ||||
| 		n += 8 | ||||
| 		for n >= 7 { | ||||
| 			n -= 7 | ||||
| 			emit(byte((bits >> n) & 0x7F)) | ||||
| 		} | ||||
| 	} | ||||
| 	if n > 0 { // tail | ||||
| 		emit(byte((bits << (7 - n)) & 0x7F)) | ||||
| 	} | ||||
| 	return string(out) | ||||
| } | ||||
|  | ||||
| func applyPatch(filePath string) (file *bytes.Buffer) { | ||||
| 	var ( | ||||
| 		outputBuffer bytes.Buffer | ||||
| @ -329,10 +367,7 @@ func preload() string { | ||||
| 			"/assets/" + BUILD_REF + "/lib/vendor/rxjs/rxjs.min.js", | ||||
| 			"/assets/" + BUILD_REF + "/lib/vendor/rxjs/rxjs-ajax.min.js", | ||||
| 			"/assets/" + BUILD_REF + "/lib/vendor/rxjs/rxjs-shared.min.js", | ||||
| 		}, | ||||
| 		{ | ||||
| 			"/assets/" + BUILD_REF + "/boot/ctrl_boot_frontoffice.js", | ||||
| 			"/assets/" + BUILD_REF + "/locales/index.js", | ||||
|  | ||||
| 			"/assets/" + BUILD_REF + "/css/designsystem.css", | ||||
| 			"/assets/" + BUILD_REF + "/css/designsystem_input.css", | ||||
| 			"/assets/" + BUILD_REF + "/css/designsystem_textarea.css", | ||||
| @ -348,13 +383,50 @@ func preload() string { | ||||
| 			"/assets/" + BUILD_REF + "/css/designsystem_skeleton.css", | ||||
| 			"/assets/" + BUILD_REF + "/css/designsystem_utils.css", | ||||
| 			"/assets/" + BUILD_REF + "/css/designsystem_alert.css", | ||||
|  | ||||
| 			"/assets/" + BUILD_REF + "/pages/filespage/modal.css", | ||||
| 			"/assets/" + BUILD_REF + "/pages/filespage/ctrl_submenu.css", | ||||
| 			"/assets/" + BUILD_REF + "/pages/filespage/modal_share.css", | ||||
| 			"/assets/" + BUILD_REF + "/pages/filespage/ctrl_filesystem.css", | ||||
| 			"/assets/" + BUILD_REF + "/pages/ctrl_filespage.css", | ||||
| 			"/assets/" + BUILD_REF + "/pages/connectpage/ctrl_form.css", | ||||
| 			"/assets/" + BUILD_REF + "/pages/viewerpage/component_menubar.css", | ||||
| 			"/assets/" + BUILD_REF + "/pages/filespage/ctrl_upload.css", | ||||
| 			"/assets/" + BUILD_REF + "/components/decorator_shell_filemanager.css", | ||||
| 		}, | ||||
| 		{ | ||||
| 			"/assets/" + BUILD_REF + "/boot/ctrl_boot_frontoffice.js", | ||||
| 			"/assets/" + BUILD_REF + "/boot/router_frontoffice.js", | ||||
| 			"/assets/" + BUILD_REF + "/boot/common.js", | ||||
| 			"/assets/" + BUILD_REF + "/components/loader.js", | ||||
| 			"/assets/" + BUILD_REF + "/components/modal.js", | ||||
| 			"/assets/" + BUILD_REF + "/components/modal.css", | ||||
| 			"/assets/" + BUILD_REF + "/components/notification.js", | ||||
| 			"/assets/" + BUILD_REF + "/components/notification.css", | ||||
| 			"/assets/" + BUILD_REF + "/boot/router_frontoffice.js", | ||||
| 			"/assets/" + BUILD_REF + "/components/sidebar.js", | ||||
| 			"/assets/" + BUILD_REF + "/components/sidebar.css", | ||||
| 			"/assets/" + BUILD_REF + "/components/dropdown.js", | ||||
| 			"/assets/" + BUILD_REF + "/components/decorator_shell_filemanager.js", | ||||
| 			"/assets/" + BUILD_REF + "/helpers/loader.js", | ||||
| 			"/assets/" + BUILD_REF + "/helpers/log.js", | ||||
| 			"/assets/" + BUILD_REF + "/helpers/sdk.js", | ||||
| 			"/assets/" + BUILD_REF + "/locales/index.js", | ||||
| 			"/assets/" + BUILD_REF + "/lib/store.js", | ||||
| 			"/assets/" + BUILD_REF + "/lib/form.js", | ||||
| 			"/assets/" + BUILD_REF + "/lib/path.js", | ||||
| 			"/assets/" + BUILD_REF + "/lib/random.js", | ||||
| 			"/assets/" + BUILD_REF + "/model/config.js", | ||||
| 			"/assets/" + BUILD_REF + "/model/chromecast.js", | ||||
| 			"/assets/" + BUILD_REF + "/model/session.js", | ||||
| 			"/assets/" + BUILD_REF + "/pages/filespage/model_acl.js", | ||||
| 			"/assets/" + BUILD_REF + "/pages/filespage/cache.js", | ||||
| 			"/assets/" + BUILD_REF + "/pages/filespage/thing.css", | ||||
| 			"/assets/" + BUILD_REF + "/pages/viewerpage/component_menubar.js", | ||||
| 		}, | ||||
| 		{ | ||||
| 			"/assets/" + BUILD_REF + "/components/form.js", | ||||
| 			"/assets/" + BUILD_REF + "/components/icon.js", | ||||
| 			"/assets/" + BUILD_REF + "/lib/settings.js", | ||||
| 			"/assets/" + BUILD_REF + "/lib/skeleton/index.js", | ||||
| 			"/assets/" + BUILD_REF + "/lib/rx.js", | ||||
| 			"/assets/" + BUILD_REF + "/lib/ajax.js", | ||||
| @ -364,80 +436,63 @@ func preload() string { | ||||
| 			"/assets/" + BUILD_REF + "/lib/skeleton/router.js", | ||||
| 			"/assets/" + BUILD_REF + "/lib/skeleton/lifecycle.js", | ||||
| 			"/assets/" + BUILD_REF + "/lib/error.js", | ||||
| 			"/assets/" + BUILD_REF + "/model/config.js", | ||||
| 			"/assets/" + BUILD_REF + "/model/plugin.js", | ||||
| 			"/assets/" + BUILD_REF + "/model/chromecast.js", | ||||
| 			"/assets/" + BUILD_REF + "/model/session.js", | ||||
| 			"/assets/" + BUILD_REF + "/helpers/log.js", | ||||
| 			"/assets/" + BUILD_REF + "/boot/common.js", | ||||
| 			"/assets/" + BUILD_REF + "/helpers/sdk.js", | ||||
|  | ||||
| 			"/assets/" + BUILD_REF + "/components/breadcrumb.js", | ||||
| 			"/assets/" + BUILD_REF + "/components/breadcrumb.css", | ||||
| 			"/assets/" + BUILD_REF + "/components/form.js", | ||||
| 			"/assets/" + BUILD_REF + "/components/sidebar.js", | ||||
| 			"/assets/" + BUILD_REF + "/components/sidebar.css", | ||||
| 			"/assets/" + BUILD_REF + "/components/dropdown.js", | ||||
| 			"/assets/" + BUILD_REF + "/components/icon.js", | ||||
| 			"/assets/" + BUILD_REF + "/lib/store.js", | ||||
| 			"/assets/" + BUILD_REF + "/lib/random.js", | ||||
| 			"/assets/" + BUILD_REF + "/lib/form.js", | ||||
| 			"/assets/" + BUILD_REF + "/lib/path.js", | ||||
|  | ||||
| 			"/assets/" + BUILD_REF + "/components/decorator_shell_filemanager.js", | ||||
| 			"/assets/" + BUILD_REF + "/components/decorator_shell_filemanager.css", | ||||
| 			"/assets/" + BUILD_REF + "/pages/ctrl_error.js", | ||||
| 		}, | ||||
| 		{ | ||||
| 			"/assets/" + BUILD_REF + "/pages/ctrl_connectpage.js", | ||||
| 			"/assets/" + BUILD_REF + "/pages/ctrl_connectpage.css", | ||||
| 			"/assets/" + BUILD_REF + "/pages/ctrl_error.js", | ||||
| 			"/assets/" + BUILD_REF + "/pages/ctrl_filespage.js", | ||||
| 			"/assets/" + BUILD_REF + "/pages/ctrl_viewerpage.js", | ||||
| 			"/assets/" + BUILD_REF + "/pages/ctrl_viewerpage.css", | ||||
| 			"/assets/" + BUILD_REF + "/pages/ctrl_logout.js", | ||||
| 			"/assets/" + BUILD_REF + "/pages/connectpage/ctrl_form.js", | ||||
| 			"/assets/" + BUILD_REF + "/pages/connectpage/ctrl_forkme.js", | ||||
| 			"/assets/" + BUILD_REF + "/pages/connectpage/ctrl_poweredby.js", | ||||
| 			"/assets/" + BUILD_REF + "/lib/path.js", | ||||
| 			"/assets/" + BUILD_REF + "/lib/form.js", | ||||
| 			"/assets/" + BUILD_REF + "/lib/settings.js", | ||||
| 			"/assets/" + BUILD_REF + "/components/form.js", | ||||
| 			"/assets/" + BUILD_REF + "/model/session.js", | ||||
| 			"/assets/" + BUILD_REF + "/pages/ctrl_error.js", | ||||
| 			"/assets/" + BUILD_REF + "/pages/connectpage/model_backend.js", | ||||
| 			"/assets/" + BUILD_REF + "/pages/connectpage/model_config.js", | ||||
| 			"/assets/" + BUILD_REF + "/pages/connectpage/ctrl_form_state.js", | ||||
| 			"/assets/" + BUILD_REF + "/lib/random.js", | ||||
| 			"/assets/" + BUILD_REF + "/components/icon.js", | ||||
|  | ||||
| 			"/assets/" + BUILD_REF + "/pages/ctrl_connectpage.css", | ||||
| 			"/assets/" + BUILD_REF + "/pages/connectpage/ctrl_form.css", | ||||
| 			"/assets/" + BUILD_REF + "/pages/filespage/ctrl_filesystem.js", | ||||
| 		}, | ||||
| 		{ | ||||
| 			"/assets/" + BUILD_REF + "/pages/ctrl_filespage.js", | ||||
| 			"/assets/" + BUILD_REF + "/pages/ctrl_filespage.css", | ||||
| 			"/assets/" + BUILD_REF + "/pages/filespage/ctrl_filesystem.js", | ||||
| 			"/assets/" + BUILD_REF + "/pages/filespage/ctrl_submenu.js", | ||||
| 			"/assets/" + BUILD_REF + "/pages/filespage/ctrl_newitem.js", | ||||
| 			"/assets/" + BUILD_REF + "/components/breadcrumb.js", | ||||
| 			"/assets/" + BUILD_REF + "/components/breadcrumb.css", | ||||
| 			"/assets/" + BUILD_REF + "/components/skeleton.js", | ||||
| 			"/assets/" + BUILD_REF + "/pages/filespage/ctrl_upload.js", | ||||
| 			"/assets/" + BUILD_REF + "/pages/filespage/cache.js", | ||||
| 			"/assets/" + BUILD_REF + "/pages/filespage/state_config.js", | ||||
| 			"/assets/" + BUILD_REF + "/pages/filespage/thing.js", | ||||
| 			"/assets/" + BUILD_REF + "/pages/filespage/state_newthing.js", | ||||
| 			"/assets/" + BUILD_REF + "/pages/filespage/helper.js", | ||||
| 			"/assets/" + BUILD_REF + "/pages/filespage/model_files.js", | ||||
| 			"/assets/" + BUILD_REF + "/pages/filespage/model_virtual_layer.js", | ||||
| 			"/assets/" + BUILD_REF + "/pages/filespage/modal_share.js", | ||||
| 			"/assets/" + BUILD_REF + "/pages/filespage/modal_tag.js", | ||||
| 			"/assets/" + BUILD_REF + "/pages/filespage/modal_tag.css", | ||||
| 			"/assets/" + BUILD_REF + "/pages/filespage/modal_rename.js", | ||||
| 			"/assets/" + BUILD_REF + "/pages/filespage/modal_delete.js", | ||||
| 			"/assets/" + BUILD_REF + "/pages/filespage/state_selection.js", | ||||
| 			"/assets/" + BUILD_REF + "/pages/filespage/model_acl.js", | ||||
|  | ||||
| 			"/assets/" + BUILD_REF + "/pages/filespage/ctrl_filesystem.css", | ||||
| 			"/assets/" + BUILD_REF + "/pages/filespage/thing.css", | ||||
| 			"/assets/" + BUILD_REF + "/pages/filespage/modal.css", | ||||
| 			"/assets/" + BUILD_REF + "/pages/filespage/ctrl_submenu.css", | ||||
| 			"/assets/" + BUILD_REF + "/pages/filespage/modal_share.css", | ||||
| 			"/assets/" + BUILD_REF + "/pages/filespage/modal_tag.css", | ||||
| 			"/assets/" + BUILD_REF + "/pages/filespage/state_newthing.js", | ||||
| 			"/assets/" + BUILD_REF + "/pages/filespage/ctrl_newitem.js", | ||||
| 			"/assets/" + BUILD_REF + "/pages/filespage/ctrl_newitem.css", | ||||
| 			"/assets/" + BUILD_REF + "/pages/filespage/ctrl_upload.css", | ||||
| 			"/assets/" + BUILD_REF + "/pages/viewerpage/mimetype.js", | ||||
| 			"/assets/" + BUILD_REF + "/pages/viewerpage/model_files.js", | ||||
| 			"/assets/" + BUILD_REF + "/pages/viewerpage/common.js", | ||||
| 		}, | ||||
| 		{ | ||||
| 			"/assets/" + BUILD_REF + "/pages/filespage/ctrl_submenu.js", | ||||
| 			"/assets/" + BUILD_REF + "/pages/filespage/thing.js", | ||||
| 			"/assets/" + BUILD_REF + "/pages/filespage/modal_share.js", | ||||
| 			"/assets/" + BUILD_REF + "/pages/viewerpage/application_downloader.js", | ||||
| 			"/assets/" + BUILD_REF + "/model/plugin.js", | ||||
| 		}, | ||||
| 	}) | ||||
| 	return string(out) | ||||
| } | ||||
|  | ||||
| func signature() string { | ||||
| 	text := BUILD_REF | ||||
| 	patches := Hooks.Get.StaticPatch() | ||||
| 	for i := 0; i < len(patches); i++ { | ||||
| 		text += string(patches[i]) | ||||
| 	} | ||||
| 	entries, _ := os.ReadDir(GetAbsolutePath(PLUGIN_PATH)) | ||||
| 	for _, e := range entries { | ||||
| 		stat, _ := e.Info() | ||||
| 		text += fmt.Sprintf("[%s][%d][%s]", stat.Name(), stat.Size(), stat.ModTime().String()) | ||||
| 	} | ||||
| 	return strings.ToLower(QuickHash(text, 3)) | ||||
| } | ||||
|  | ||||
		Reference in New Issue
	
	Block a user
	 MickaelK
					MickaelK