added initial files
@@ -0,0 +1,59 @@
|
||||
const { Client } = require('discord-rpc');
|
||||
const log = require('electron-log');
|
||||
|
||||
let client;
|
||||
let activity;
|
||||
|
||||
const initialAppStartup = Math.floor(Date.now() / 1000);
|
||||
|
||||
const defaultValue = {
|
||||
details: 'Idle',
|
||||
startTimestamp: initialAppStartup,
|
||||
largeImageKey: 'default_big',
|
||||
largeImageText: 'GDLauncher - A Custom Minecraft Launcher',
|
||||
instance: false
|
||||
};
|
||||
|
||||
exports.initRPC = () => {
|
||||
client = new Client({ transport: 'ipc' });
|
||||
|
||||
activity = defaultValue;
|
||||
|
||||
client.on('ready', () => {
|
||||
log.log('Discord RPC Connected');
|
||||
client.setActivity(activity);
|
||||
});
|
||||
|
||||
client.login({ clientId: '555898932467597312' }).catch(error => {
|
||||
if (error.message.includes('ENOENT')) {
|
||||
log.error('Unable to initialize Discord RPC, no client detected.');
|
||||
} else {
|
||||
log.error('Unable to initialize Discord RPC:', error);
|
||||
}
|
||||
});
|
||||
};
|
||||
|
||||
exports.update = details => {
|
||||
if (!client) return;
|
||||
activity = {
|
||||
...activity,
|
||||
startTimestamp: Math.floor(Date.now() / 1000),
|
||||
details: `Playing ${details}`
|
||||
};
|
||||
client.setActivity(activity);
|
||||
};
|
||||
|
||||
exports.reset = () => {
|
||||
if (!client) return;
|
||||
activity = defaultValue;
|
||||
activity.startTimestamp = initialAppStartup;
|
||||
client.setActivity(activity);
|
||||
};
|
||||
|
||||
exports.shutdownRPC = () => {
|
||||
if (!client) return;
|
||||
client.clearActivity();
|
||||
client.destroy();
|
||||
client = null;
|
||||
activity = null;
|
||||
};
|
||||
|
After Width: | Height: | Size: 7.0 KiB |
|
After Width: | Height: | Size: 26 KiB |
@@ -0,0 +1,226 @@
|
||||
<!DOCTYPE html>
|
||||
<html lang="en">
|
||||
<head>
|
||||
<meta charset="utf-8" />
|
||||
<link rel="icon" href="%PUBLIC_URL%/icon.ico" />
|
||||
<meta
|
||||
name="description"
|
||||
content="GDLauncher -- A custom Minecraft launcher"
|
||||
/>
|
||||
<style>
|
||||
.loader,
|
||||
.loader:after {
|
||||
border-radius: 50%;
|
||||
width: 10em;
|
||||
height: 10em;
|
||||
}
|
||||
.loader {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
margin: 60px auto;
|
||||
position: relative;
|
||||
text-indent: -9999em;
|
||||
}
|
||||
|
||||
.loader svg {
|
||||
z-index: 2;
|
||||
width: 700px;
|
||||
animation: spin 1.1s infinite ease-in-out;
|
||||
transform: scale(4);
|
||||
}
|
||||
|
||||
@keyframes spin {
|
||||
0% {
|
||||
transform: rotate(0);
|
||||
}
|
||||
20% {
|
||||
transform: rotate(-3.2deg);
|
||||
}
|
||||
80% {
|
||||
transform: rotate(360deg);
|
||||
}
|
||||
90% {
|
||||
transform: rotate(370deg);
|
||||
}
|
||||
100% {
|
||||
transform: rotate(360deg);
|
||||
}
|
||||
}
|
||||
/* @keyframes spin { 100% { transform:rotate(360deg); } } */
|
||||
</style>
|
||||
<link rel="manifest" href="%PUBLIC_URL%/manifest.json" />
|
||||
<script>
|
||||
(function () {
|
||||
if (process.env.NODE_ENV !== 'development') {
|
||||
window.gaInitialized = true;
|
||||
window.ga =
|
||||
window.ga ||
|
||||
function () {
|
||||
(ga.q = ga.q || []).push(arguments);
|
||||
};
|
||||
ga.l = +new Date();
|
||||
ga('create', 'UA-147631204-1', 'none');
|
||||
ga('set', 'transport', 'xhr');
|
||||
ga('set', 'appName', 'GDLauncher');
|
||||
ga('set', 'checkProtocolTask', null);
|
||||
ga('set', 'checkStorageTask', null);
|
||||
ga('set', 'storage', 'none');
|
||||
ga('set', 'storeGac', null);
|
||||
ga('set', 'anonymizeIp', true);
|
||||
ga('set', 'ds', 'app');
|
||||
}
|
||||
})();
|
||||
</script>
|
||||
|
||||
<script>
|
||||
!(function () {
|
||||
'use strict';
|
||||
var i = {};
|
||||
var a = window.location,
|
||||
r = window.document,
|
||||
o = r.currentScript,
|
||||
l =
|
||||
o.getAttribute('data-api') || 'https://plausible.io' + '/api/event';
|
||||
function s(e) {
|
||||
console.warn('Ignoring Event: ' + e);
|
||||
}
|
||||
function e(e, t) {
|
||||
if (
|
||||
/^localhost$|^127(\.[0-9]+){0,2}\.[0-9]+$|^\[::1?\]$/.test(
|
||||
a.hostname
|
||||
)
|
||||
)
|
||||
return s('localhost');
|
||||
if (
|
||||
!(
|
||||
window._phantom ||
|
||||
window.__nightmare ||
|
||||
window.navigator.webdriver ||
|
||||
window.Cypress
|
||||
)
|
||||
) {
|
||||
try {
|
||||
if ('true' === window.localStorage.plausible_ignore)
|
||||
return s('localStorage flag');
|
||||
} catch (e) {}
|
||||
(i.n = e),
|
||||
(i.d = 'app.gdevs.io'),
|
||||
(i.r = 'https://app.gdevs.io'),
|
||||
(i.w = window.innerWidth),
|
||||
t && t.meta && (i.m = JSON.stringify(t.meta)),
|
||||
t && t.props && (i.p = t.props),
|
||||
(i.h = 1);
|
||||
var n = new XMLHttpRequest();
|
||||
n.open('POST', l, !0),
|
||||
n.setRequestHeader('Content-Type', 'text/plain'),
|
||||
n.send(JSON.stringify(i)),
|
||||
(n.onreadystatechange = function () {
|
||||
4 === n.readyState && t && t.callback && t.callback();
|
||||
});
|
||||
}
|
||||
}
|
||||
var t = (window.plausible && window.plausible.q) || [];
|
||||
window.plausible = e;
|
||||
for (var i, n = 0; n < t.length; n++) e.apply(this, t[n]);
|
||||
function w() {
|
||||
(i.u = 'https://app.gdevs.io' + a.hash.slice(1)),
|
||||
e('pageview', { props: { version: '1.1.29' } });
|
||||
}
|
||||
window.addEventListener('hashchange', w),
|
||||
'prerender' === r.visibilityState
|
||||
? r.addEventListener('visibilitychange', function () {
|
||||
i || 'visible' !== r.visibilityState || w();
|
||||
})
|
||||
: w();
|
||||
})();
|
||||
</script>
|
||||
|
||||
<script async src="https://www.google-analytics.com/analytics.js"></script>
|
||||
<!--
|
||||
Notice the use of %PUBLIC_URL% in the tags above.
|
||||
It will be replaced with the URL of the `public` folder during the build.
|
||||
Only files inside the `public` folder can be referenced from the HTML.
|
||||
|
||||
Unlike "/favicon.ico" or "favicon.ico", "%PUBLIC_URL%/favicon.ico" will
|
||||
work correctly both with client-side routing and a non-root public URL.
|
||||
Learn how to configure a non-root public URL by running `npm run build`.
|
||||
-->
|
||||
<title>GDLauncher</title>
|
||||
</head>
|
||||
<body>
|
||||
<noscript>You need to enable JavaScript to run this app.</noscript>
|
||||
<div id="root">
|
||||
<div
|
||||
style="
|
||||
width: 100%;
|
||||
height: 95vh;
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
"
|
||||
>
|
||||
<div class="loader">
|
||||
<svg
|
||||
version="1.1"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
xmlns:xlink="http://www.w3.org/1999/xlink"
|
||||
x="0px"
|
||||
y="0px"
|
||||
viewBox="0 0 1080 1080"
|
||||
style="enable-background: new 0 0 1080 1080"
|
||||
xml:space="preserve"
|
||||
>
|
||||
<style type="text/css">
|
||||
.st0 {
|
||||
fill: #365076;
|
||||
}
|
||||
.st1 {
|
||||
fill: #ffffff;
|
||||
}
|
||||
</style>
|
||||
<g>
|
||||
<polygon
|
||||
class="st0"
|
||||
points="996,276.7 540,13.5 84,276.7 84,803.3 540,1066.5 996,803.3 "
|
||||
/>
|
||||
<g>
|
||||
<path
|
||||
class="st1"
|
||||
d="M540,797.5L540,797.5c77.7,0,140.7-63,140.7-140.7v-23.9c0-2,1.2-3.9,3.1-4.6
|
||||
c21.8-8.8,150.6-66.2,133.6-193.2c-18.3-136.9-188.3-115.4-274-33.6c-1.9,1.8-4.9,1.8-6.9,0c-85.7-81.8-255.7-103.2-274,33.6
|
||||
c-17,127,111.8,184.4,133.6,193.2c1.9,0.8,3.1,2.6,3.1,4.6v23.9C399.3,734.6,462.3,797.5,540,797.5L540,797.5L540,797.5z"
|
||||
/>
|
||||
<g>
|
||||
<path
|
||||
class="st0"
|
||||
d="M479.8,526.4c0.4,4.8-5.5,7.5-8.7,3.8c-10.3-12-30-29.1-62.9-38.2c-54-15,3.3-46.9,25.4-36.5
|
||||
C453.6,465,475.6,478.1,479.8,526.4z"
|
||||
/>
|
||||
<path
|
||||
class="st0"
|
||||
d="M600.2,526.4c-0.4,4.8,5.5,7.5,8.7,3.8c10.3-12,30-29.1,62.9-38.2c54-15-3.3-46.9-25.4-36.5
|
||||
C626.4,465,604.4,478.1,600.2,526.4z"
|
||||
/>
|
||||
</g>
|
||||
<g>
|
||||
<path
|
||||
class="st0"
|
||||
d="M571.8,598.1c7.4,16.4,19.2,49,8.9,72.1c-1.4,3.2-5.8,3.8-8.2,1.1c-8.4-9.5-23.6-33.4-10-72.7
|
||||
C564,594.3,570,594,571.8,598.1z"
|
||||
/>
|
||||
<path
|
||||
class="st0"
|
||||
d="M508.2,598.1c-7.4,16.4-19.2,49-8.9,72.1c1.4,3.2,5.8,3.8,8.2,1.1c8.4-9.5,23.6-33.4,10-72.7
|
||||
C516,594.3,510,594,508.2,598.1z"
|
||||
/>
|
||||
</g>
|
||||
</g>
|
||||
</g>
|
||||
</svg>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</body>
|
||||
</html>
|
||||
@@ -0,0 +1,61 @@
|
||||
# For my application GUID (fix GUID to match what your application uses)
|
||||
!macro customInit
|
||||
# Workaround for installer handing when the app directory is removed manually
|
||||
${ifNot} ${FileExists} "$INSTDIR"
|
||||
DeleteRegKey HKCU "Software\Microsoft\Windows\CurrentVersion\Uninstall\${APP_GUID}"
|
||||
${EndIf}
|
||||
|
||||
DeleteRegKey HKCU "Software\Microsoft\Windows\CurrentVersion\Uninstall\{${APP_GUID}}"
|
||||
|
||||
ReadRegStr $0 HKCU "Software\Microsoft\Windows\CurrentVersion\Uninstall\${APP_GUID}" "QuietUninstallString"
|
||||
StrCmp $0 "" proceed 0
|
||||
DeleteRegKey HKCU "Software\Microsoft\Windows\CurrentVersion\Uninstall\${APP_GUID}"
|
||||
proceed:
|
||||
!macroend
|
||||
|
||||
!macro customUnInstall
|
||||
push $4
|
||||
push $0
|
||||
|
||||
SetShellVarContext current
|
||||
ClearErrors
|
||||
${ifNot} ${isUpdated}
|
||||
|
||||
MessageBox MB_YESNO "Also delete all your user data? (instances, preferences...)" IDNO Skipped IDYES Accepted
|
||||
|
||||
Accepted:
|
||||
FileOpen $4 "$APPDATA\gdlauncher_next\override.data" r
|
||||
FileRead $4 $0
|
||||
RMDir /r "$0\instances"
|
||||
RMDir /r "$0\java"
|
||||
RMDir /r "$0\datastore"
|
||||
RMDir /r "$0\blob_storage"
|
||||
RMDir /r "$0\Local Storage"
|
||||
RMDir /r "$0\Cache"
|
||||
RMDir /r "$0\Code Cache"
|
||||
RMDir /r "$0\Dictionaries"
|
||||
RMDir /r "$0\GPUCache"
|
||||
RMDir /r "$0\Session Storage"
|
||||
RMDir /r "$0\shared_proto_db"
|
||||
RMDir /r "$0\temp"
|
||||
Delete "$0\Cookies"
|
||||
Delete "$0\.updaterId"
|
||||
Delete "$0\7za.exe"
|
||||
Delete "$0\Cookies-journal"
|
||||
Delete "$0\Network Persistent State"
|
||||
Delete "$0\Preferences"
|
||||
Delete "$0\TransportSecurity"
|
||||
Delete "$0\Config"
|
||||
Delete "$0\rChannel"
|
||||
|
||||
FileClose $4
|
||||
|
||||
RMDir /r "$APPDATA\gdlauncher_next"
|
||||
Goto done
|
||||
Skipped:
|
||||
Goto done
|
||||
done:
|
||||
${endIf}
|
||||
pop $4
|
||||
pop $0
|
||||
!macroend
|
||||
|
After Width: | Height: | Size: 34 KiB |
|
After Width: | Height: | Size: 201 KiB |
|
After Width: | Height: | Size: 23 KiB |
|
After Width: | Height: | Size: 2.8 KiB |
|
After Width: | Height: | Size: 5.1 KiB |
|
After Width: | Height: | Size: 896 B |
|
After Width: | Height: | Size: 1.3 KiB |
|
After Width: | Height: | Size: 11 KiB |
|
After Width: | Height: | Size: 1.6 KiB |
|
After Width: | Height: | Size: 2.2 KiB |
|
After Width: | Height: | Size: 669 B |
@@ -0,0 +1,123 @@
|
||||
/* eslint-disable global-require */
|
||||
const { promises: fs } = require('fs');
|
||||
const path = require('path');
|
||||
// const os = require('os');
|
||||
|
||||
const NSFW = require('./native/nsfw.node');
|
||||
|
||||
function NSFWFilePoller(watchPath, eventCallback, debounceMS) {
|
||||
const { CREATED, DELETED, MODIFIED } = nsfw.actions;
|
||||
const directory = path.dirname(watchPath);
|
||||
const file = path.basename(watchPath);
|
||||
|
||||
let fileStatus;
|
||||
let filePollerInterval;
|
||||
|
||||
const getStatus = async () => {
|
||||
try {
|
||||
const status = await fs.stat(watchPath);
|
||||
if (fileStatus === null) {
|
||||
fileStatus = status;
|
||||
eventCallback([{ action: CREATED, directory, file }]);
|
||||
} else if (
|
||||
status.mtime - fileStatus.mtime !== 0 ||
|
||||
status.ctime - fileStatus.ctime !== 0
|
||||
) {
|
||||
fileStatus = status;
|
||||
eventCallback([{ action: MODIFIED, directory, file }]);
|
||||
}
|
||||
} catch (e) {
|
||||
if (fileStatus !== null) {
|
||||
fileStatus = null;
|
||||
eventCallback([{ action: DELETED, directory, file }]);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
this.start = async () => {
|
||||
try {
|
||||
fileStatus = await fs.stat(watchPath);
|
||||
} catch (e) {
|
||||
fileStatus = null;
|
||||
}
|
||||
|
||||
filePollerInterval = setInterval(getStatus, debounceMS);
|
||||
};
|
||||
|
||||
this.stop = async () => {
|
||||
clearInterval(filePollerInterval);
|
||||
};
|
||||
|
||||
this.pause = () => this.stop();
|
||||
this.resume = () => this.start();
|
||||
}
|
||||
|
||||
const buildNSFW = async (
|
||||
watchPath,
|
||||
eventCallback,
|
||||
{ debounceMS = 500, errorCallback: _errorCallback } = {}
|
||||
) => {
|
||||
if (Number.isInteger(debounceMS)) {
|
||||
if (debounceMS < 1) {
|
||||
throw new Error('Minimum debounce is 1ms.');
|
||||
}
|
||||
} else {
|
||||
throw new Error('debounceMS must be an integer.');
|
||||
}
|
||||
|
||||
const errorCallback =
|
||||
_errorCallback ||
|
||||
(nsfwError => {
|
||||
throw nsfwError;
|
||||
});
|
||||
|
||||
if (!path.isAbsolute(watchPath)) {
|
||||
throw new Error('Path to watch must be an absolute path.');
|
||||
}
|
||||
|
||||
let stats;
|
||||
try {
|
||||
stats = await fs.stat(watchPath);
|
||||
} catch (e) {
|
||||
throw new Error('Path must be a valid path to a file or a directory.');
|
||||
}
|
||||
|
||||
if (stats.isDirectory()) {
|
||||
return new NSFW(watchPath, eventCallback, { debounceMS, errorCallback });
|
||||
}
|
||||
if (stats.isFile()) {
|
||||
return new NSFWFilePoller(watchPath, eventCallback, debounceMS);
|
||||
}
|
||||
throw new Error('Path must be a valid path to a file or a directory');
|
||||
};
|
||||
|
||||
function nsfw(watchPath, eventCallback, options) {
|
||||
if (!(this instanceof nsfw)) {
|
||||
return buildNSFW(watchPath, eventCallback, options).then(
|
||||
// eslint-disable-next-line
|
||||
implementation => new nsfw(implementation)
|
||||
);
|
||||
}
|
||||
|
||||
const implementation = watchPath;
|
||||
|
||||
this.start = () => implementation.start();
|
||||
this.stop = () => implementation.stop();
|
||||
this.pause = () => implementation.pause();
|
||||
this.resume = () => implementation.resume();
|
||||
}
|
||||
|
||||
nsfw.actions = {
|
||||
CREATED: 0,
|
||||
DELETED: 1,
|
||||
MODIFIED: 2,
|
||||
RENAMED: 3
|
||||
};
|
||||
|
||||
nsfw._native = NSFW;
|
||||
|
||||
if (NSFW.getAllocatedInstanceCount) {
|
||||
nsfw.getAllocatedInstanceCount = NSFW.getAllocatedInstanceCount;
|
||||
}
|
||||
|
||||
module.exports = nsfw;
|
||||