Skip to content

Commit

Permalink
Finish update checker
Browse files Browse the repository at this point in the history
  • Loading branch information
GarboMuffin committed Aug 19, 2023
1 parent 704164e commit a1b8f8f
Show file tree
Hide file tree
Showing 7 changed files with 224 additions and 47 deletions.
2 changes: 1 addition & 1 deletion src-main/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ if (!app.requestSingleInstanceLock()) {
const openExternal = require('./open-external');
const BaseWindow = require('./windows/base');
const EditorWindow = require('./windows/editor');
const checkForUpdates = require('./update-checker');
const {checkForUpdates} = require('./update-checker');
require('./protocols');
require('./context-menu');
require('./shortcuts');
Expand Down
14 changes: 14 additions & 0 deletions src-main/settings.js
Original file line number Diff line number Diff line change
Expand Up @@ -70,6 +70,20 @@ class Settings {
this.data.updateChecker = updateChecker;
}

get ignoredUpdate () {
return this.data.ignoredUpdate || null;
}
set ignoredUpdate (ignoredUpdate) {
this.data.ignoredUpdate = ignoredUpdate;
}

get ignoredUpdateUntil () {
return this.data.ignoredUpdateUntil || 0;
}
set ignoredUpdateUntil (ignoredUpdateUntil) {
this.data.ignoredUpdateUntil = ignoredUpdateUntil;
}

get camera () {
return this.data.camera || null;
}
Expand Down
40 changes: 31 additions & 9 deletions src-main/update-checker.js
Original file line number Diff line number Diff line change
Expand Up @@ -24,11 +24,6 @@ const fetchVersionJSON = () => new Promise((resolve, reject) => {
});

response.on('end', () => {
data = JSON.stringify({
latest: '1.99.0-fake-version',
yanked: '1.8.1'
});

try {
resolve(JSON.parse(data));
} catch (e) {
Expand All @@ -53,14 +48,41 @@ const checkForUpdates = async () => {
const latestVersion = json.latest;
const yanked = json.yanked;

// Security updates can not be ignored.
if (semverSatisfies(currentVersion, yanked)) {
UpdateWindow.updateAvailable(latestVersion, true);
UpdateWindow.updateAvailable(currentVersion, latestVersion, true);
return;
}

if (settings.updateChecker === 'security') {
// Nothing further to check
return;
}

const now = Date.now();
const ignoredUpdate = settings.ignoredUpdate;
const ignoredUpdateUntil = settings.ignoredUpdateUntil * 1000;
if (ignoredUpdate === latestVersion && now < ignoredUpdateUntil) {
// This update was ignored
return;
}

if (settings.updateChecker === 'stable' && semverLt(currentVersion, latestVersion)) {
UpdateWindow.updateAvailable(latestVersion, false);
if (semverLt(currentVersion, latestVersion)) {
UpdateWindow.updateAvailable(currentVersion, latestVersion, false);
}
};

module.exports = checkForUpdates;
/**
* @param {string} version
* @param {Date} until
*/
const ignoreUpdate = async (version, until) => {
settings.ignoredUpdate = version;
settings.ignoredUpdateUntil = Math.floor(until.getTime() / 1000);
await settings.save();
};

module.exports = {
checkForUpdates,
ignoreUpdate
};
74 changes: 61 additions & 13 deletions src-main/windows/update.js
Original file line number Diff line number Diff line change
@@ -1,33 +1,81 @@
const BaseWindow = require('./base');
const {translate} = require('../l10n');
const {APP_NAME} = require('../brand');
const openExternal = require('../open-external');

class UpdateWindow extends BaseWindow {
constructor (latestVersion, isSecurity) {
constructor (currentVersion, latestVersion, security) {
super();

this.window.setTitle(translate('update.title'));
this.window.setTitle(`${translate('update.title')} - ${APP_NAME}`);

const params = new URLSearchParams();
params.set('version', latestVersion);
params.set('security', isSecurity);
const ipc = this.window.webContents.ipc;

this.window.on('ready-to-show', () => {
ipc.on('get-info', (event) => {
event.returnValue = {
currentVersion,
latestVersion,
security
};
});

ipc.handle('download', () => {
this.window.destroy();

const params = new URLSearchParams();
params.set('from', currentVersion);
params.set('to', latestVersion);
openExternal(`https://desktop.turbowarp.org/update_available?${params}`);
});

const ignore = (permanently) => {
const SECOND = 1000;
const MINUTE = SECOND * 60;
const HOUR = MINUTE * 60;

let until;
if (security) {
// Security updates can't be ignored.
until = new Date(0);
} else if (permanently) {
// 3000 ought to be enough years into the future...
until = new Date(3000, 0, 0);
} else {
until = new Date();
until.setTime(until.getTime() + (HOUR * 6));
}

// Imported late due to circular dependency
const {ignoreUpdate} = require('../update-checker');
ignoreUpdate(latestVersion, until);
};

ipc.handle('ignore', (event, permanently) => {
this.window.destroy();
ignore(permanently);
});

this.window.on('close', () => {
ignore(false);
});

this.window.webContents.on('did-finish-load', () => {
this.show();
})
});

this.window.loadURL(`tw-update://./update.html?${params.toString()}`);
this.window.loadURL('tw-update://./update.html');
}

getDimensions () {
return [500, 500];
return [600, 500];
}

enableWebview () {
return true;
getPreload () {
return 'update';
}

static updateAvailable (latestVersion, isSecurity) {
new UpdateWindow(latestVersion, isSecurity);
static updateAvailable (currentVersion, latestVersion, isSecurity) {
new UpdateWindow(currentVersion, latestVersion, isSecurity);
}
}

Expand Down
7 changes: 7 additions & 0 deletions src-preload/update.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
const {contextBridge, ipcRenderer} = require('electron');

contextBridge.exposeInMainWorld('UpdatePreload', {
getInfo: () => ipcRenderer.sendSync('get-info'),
download: () => ipcRenderer.invoke('download'),
ignore: (permanently) => ipcRenderer.invoke('ignore', permanently)
});
4 changes: 2 additions & 2 deletions src-renderer/desktop-settings/index.html
Original file line number Diff line number Diff line change
Expand Up @@ -49,16 +49,16 @@ <h1>Desktop Settings</h1>
<label>
<div class="label">Update checker</div>
<select class="update-checker" autocomplete="off">
<!-- <option value="beta">Notify me about beta updates</option> -->
<option value="stable">Notify me about stable updates</option>
<option value="security">Notify me about security updates</option>
<!-- <option value="never">Never notify me about updates</option> -->
<option value="never">Never notify me about updates</option>
</select>
<script>
const updateChecker = document.querySelector('.update-checker');
updateChecker.addEventListener('change', (e) => {
DesktopSettingsPreload.setUpdateChecker(e.target.value);
});
updateChecker.value = settings.updateChecker;
</script>
</label>

Expand Down
130 changes: 108 additions & 22 deletions src-renderer/update/update.html
Original file line number Diff line number Diff line change
Expand Up @@ -13,22 +13,33 @@
main {
padding: 20px;
box-sizing: border-box;
width: 100%;
min-height: 100vh;
width: 100vw;
height: 100vh;
border: 20px solid hsla(0, 100%, 65%, 1);
display: flex;
flex-direction: column;
gap: 0.5rem;
}

h1, p {
h1, h2, p {
margin: 0;
}
ul {
margin: 0.5rem 0;
}

.update-log {
width: 100%;
flex-grow: 1;
border: 0;
overflow: auto;
}
.loading, .error, .empty {
width: 100%;
height: 100%;
display: flex;
align-items: center;
justify-content: center;
}
button {
cursor: pointer;
Expand All @@ -39,54 +50,129 @@
border: 1px solid hsla(0, 0%, 0%, 0.15);
font-weight: bold;
}
.download-update {
.download-button {
color: black;
background-color: #24cd11;
}
.ignore-button {

}
label {
cursor: pointer;
}

.if-security {
display: none;
}
.security .if-security {
display: initial;
}
.security .if-normal {
display: none;
}
</style>
</head>
<body>
<main>
<h1>An update is available!</h1>
<script>
const info = UpdatePreload.getInfo();
if (info.security) {
document.body.classList.add('security');
}
</script>

<h1 class="if-normal">An update is available</h1>
<h1 class="if-security">A security update is available</h1>

<p>TurboWarp Desktop <span class="latest-version"></span> is now available. Read the changelog below:</p>
<p class="if-normal">TurboWarp Desktop v1.2.3 is now available.</p>
<p class="if-security">TurboWarp Desktop v1.2.3 is now available. This release contains security fixes. Updating is highly recommended.</p>

<div class="update-log"></div>
<div class="update-log">
<p class="loading">Loading...</p>
</div>

<button class="download-update">Download Update</button>
<button class="ignore-update">Ignore</button>
<button class="download-button">Download Update</button>
<button class="ignore-button">Remind me later</button>

<label>
<label class="permanently-ignore-outer if-normal">
<input type="checkbox" class="permanently-ignore">
Ignore this update
Permanently ignore this update
</label>

<script>
const params = new URLSearchParams(location.search);
const downloadButton = document.querySelector('.download-button');
const ignoreButton = document.querySelector('.ignore-button');
const permanentCheckbox = document.querySelector('.permanently-ignore');
downloadButton.addEventListener('click', () => {
UpdatePreload.download();
});
ignoreButton.addEventListener('click', () => {
UpdatePreload.ignore(permanentCheckbox.checked);
});

const latestVersion = document.querySelector('.latest-version');
latestVersion.textContent = `v${params.get('version')}`;
const compareVersions = (a, b) => {
const partsA = a.split('-')[0].split('.');
const partsB = b.split('-')[0].split('.');
const expectedLength = 3;
for (var i = 0; i < expectedLength; i++) {
const itemA = +partsA[i];
const itemB = +partsB[i];
if (itemA > itemB) {
return 1;
} else if (itemA < itemB) {
return 2;
}
}
return 0;
};

if (params.get('security') === 'true') {
document.body.classList.add('security');
}
const removeChildren = (el) => {
while (el.firstChild) {
el.removeChild(el.firstChild);
}
};

const changelog = document.querySelector('.changelog');
fetch(`https://desktop.turbowarp.org/in-app-changelog.json?version=${latestVersion}`)
const changelog = document.querySelector('.update-log');
fetch(`https://desktop.turbowarp.org/changelog.json?version=${info.latestVersion}`)
.then((res) => {
if (!res.ok) {
throw new Error(`HTTP error ${res.ok}`);
throw new Error(`HTTP error ${res.status}`);
}
return res.json();
})
.then((data) => {
console.log(data);
.then((releases) => {
removeChildren(changelog);

const releaseNotes = releases.filter(({version}) => compareVersions(info.currentVersion, version) === 2);
if (releaseNotes.length) {
for (const {version, date, notes} of releaseNotes) {
const titleElement = document.createElement('h2');
titleElement.textContent = `v${version} (${date})`;
changelog.appendChild(titleElement);

const ul = document.createElement('ul');
for (const note of notes) {
const li = document.createElement('li');
li.textContent = note;
ul.appendChild(li);
}
changelog.appendChild(ul);
}
} else {
const p = document.createElement('p');
p.className = 'empty';
p.textContent = 'Changelog not available yet.';
changelog.appendChild(p);
}
})
.catch((error) => {
console.error(error);

removeChildren(changelog);
const p = document.createElement('p');
p.className = 'error';
p.textContent = `Error loading changelog: ${error}`;
changelog.appendChild(p);
});
</script>
</main>
Expand Down

0 comments on commit a1b8f8f

Please sign in to comment.