mirror of
https://github.com/heyman/heynote.git
synced 2024-11-21 15:33:14 +01:00
Add auto update support
This commit is contained in:
parent
2c3eacbba0
commit
7ce91016d6
@ -1,3 +1,12 @@
|
||||
export const WINDOW_CLOSE_EVENT = "window-close"
|
||||
export const OPEN_SETTINGS_EVENT = "open-settings"
|
||||
export const SETTINGS_CHANGE_EVENT = "settings-change"
|
||||
|
||||
export const UPDATE_AVAILABLE_EVENT = "update-available"
|
||||
export const UPDATE_NOT_AVAILABLE_EVENT = "update-not-available"
|
||||
export const UPDATE_DOWNLOADED = "update-downloaded"
|
||||
export const UPDATE_ERROR = "update-error"
|
||||
export const UPDATE_DOWNLOAD_PROGRESS = "update-download-progress"
|
||||
|
||||
export const UPDATE_START_DOWNLOAD = "auto-update:startDownload"
|
||||
export const UPDATE_INSTALL_AND_RESTART = "auto-update:installAndRestart"
|
||||
|
70
electron/main/auto-update.ts
Normal file
70
electron/main/auto-update.ts
Normal file
@ -0,0 +1,70 @@
|
||||
import { autoUpdater } from "electron-updater"
|
||||
import { app, dialog, ipcMain } from "electron"
|
||||
|
||||
import {
|
||||
UPDATE_AVAILABLE_EVENT,
|
||||
UPDATE_NOT_AVAILABLE_EVENT,
|
||||
UPDATE_DOWNLOADED,
|
||||
UPDATE_DOWNLOAD_PROGRESS,
|
||||
UPDATE_ERROR,
|
||||
UPDATE_START_DOWNLOAD,
|
||||
UPDATE_INSTALL_AND_RESTART,
|
||||
} from '../constants'
|
||||
|
||||
|
||||
// will reference the main window
|
||||
let window
|
||||
|
||||
// configure logging
|
||||
const log = require('electron-log');
|
||||
|
||||
autoUpdater.logger = log
|
||||
autoUpdater.logger.transports.file.level = "info"
|
||||
|
||||
autoUpdater.autoDownload = false
|
||||
|
||||
autoUpdater.on('error', (error) => {
|
||||
window?.webContents.send(UPDATE_ERROR, error == null ? "unknown" : (error.stack || error).toString())
|
||||
//dialog.showErrorBox('Error: ', error == null ? "unknown" : (error.stack || error).toString())
|
||||
})
|
||||
|
||||
autoUpdater.on('update-available', (info) => {
|
||||
window?.webContents.send(UPDATE_AVAILABLE_EVENT, {
|
||||
version: info.version,
|
||||
releaseDate: info.releaseDate,
|
||||
currentVersion: app.getVersion(),
|
||||
})
|
||||
})
|
||||
|
||||
autoUpdater.on('update-not-available', () => {
|
||||
window?.webContents.send(UPDATE_NOT_AVAILABLE_EVENT)
|
||||
})
|
||||
|
||||
autoUpdater.on('update-downloaded', () => {
|
||||
window?.webContents.send(UPDATE_DOWNLOADED)
|
||||
})
|
||||
|
||||
autoUpdater.on('download-progress', (info) => {
|
||||
window?.webContents.send(UPDATE_DOWNLOAD_PROGRESS, {
|
||||
percent: info.percent,
|
||||
total: info.total,
|
||||
transferred: info.transferred,
|
||||
bytesPerSecond: info.bytesPerSecond,
|
||||
})
|
||||
})
|
||||
|
||||
// handle messages from Vue components
|
||||
ipcMain.handle(UPDATE_START_DOWNLOAD, () => {
|
||||
autoUpdater.downloadUpdate()
|
||||
})
|
||||
|
||||
ipcMain.handle(UPDATE_INSTALL_AND_RESTART, () => {
|
||||
setImmediate(() => autoUpdater.quitAndInstall())
|
||||
})
|
||||
|
||||
export function checkForUpdates(win) {
|
||||
window = win
|
||||
|
||||
// check for updates
|
||||
autoUpdater.checkForUpdates()
|
||||
}
|
@ -2,12 +2,15 @@ import { app, BrowserWindow, shell, ipcMain, Menu, nativeTheme, globalShortcut }
|
||||
import { release } from 'node:os'
|
||||
import { join } from 'node:path'
|
||||
import * as jetpack from "fs-jetpack";
|
||||
|
||||
import menu from './menu'
|
||||
import { initialContent, initialDevContent } from '../initial-content'
|
||||
import { WINDOW_CLOSE_EVENT, SETTINGS_CHANGE_EVENT } from '../constants';
|
||||
import CONFIG from "../config"
|
||||
import { onBeforeInputEvent } from "../keymap"
|
||||
import { isMac } from '../detect-platform';
|
||||
import { checkForUpdates } from './auto-update';
|
||||
|
||||
|
||||
// The built directory structure
|
||||
//
|
||||
@ -134,7 +137,9 @@ async function createWindow() {
|
||||
})
|
||||
}
|
||||
|
||||
app.whenReady().then(createWindow)
|
||||
app.whenReady().then(createWindow).then(async () => {
|
||||
checkForUpdates(win)
|
||||
})
|
||||
|
||||
app.on('window-all-closed', () => {
|
||||
win = null
|
||||
|
@ -2,7 +2,18 @@ const { contextBridge } = require('electron')
|
||||
import darkMode from "./theme-mode"
|
||||
import { isMac, isWindows, isLinux } from "../detect-platform"
|
||||
import { ipcRenderer } from "electron"
|
||||
import { WINDOW_CLOSE_EVENT, OPEN_SETTINGS_EVENT, SETTINGS_CHANGE_EVENT } from "../constants"
|
||||
import {
|
||||
WINDOW_CLOSE_EVENT,
|
||||
OPEN_SETTINGS_EVENT,
|
||||
SETTINGS_CHANGE_EVENT,
|
||||
UPDATE_AVAILABLE_EVENT,
|
||||
UPDATE_ERROR,
|
||||
UPDATE_DOWNLOAD_PROGRESS,
|
||||
UPDATE_NOT_AVAILABLE_EVENT,
|
||||
UPDATE_START_DOWNLOAD,
|
||||
UPDATE_INSTALL_AND_RESTART,
|
||||
UPDATE_DOWNLOADED,
|
||||
} from "../constants"
|
||||
import CONFIG from "../config"
|
||||
|
||||
//contextBridge.exposeInMainWorld("platform", )
|
||||
@ -51,6 +62,23 @@ contextBridge.exposeInMainWorld("heynote", {
|
||||
onSettingsChange(callback) {
|
||||
ipcRenderer.on(SETTINGS_CHANGE_EVENT, (event, settings) => callback(settings))
|
||||
},
|
||||
|
||||
autoUpdate: {
|
||||
callbacks(callbacks) {
|
||||
ipcRenderer.on(UPDATE_AVAILABLE_EVENT, (event, info) => callbacks?.updateAvailable(info))
|
||||
ipcRenderer.on(UPDATE_NOT_AVAILABLE_EVENT, (event) => callbacks?.updateNotAvailable())
|
||||
ipcRenderer.on(UPDATE_DOWNLOADED, (event) => callbacks?.updateDownloaded())
|
||||
ipcRenderer.on(UPDATE_ERROR, (event, error) => callbacks?.updateError(error))
|
||||
ipcRenderer.on(UPDATE_DOWNLOAD_PROGRESS, (event, progress) => callbacks?.updateDownloadProgress(progress))
|
||||
},
|
||||
|
||||
startDownload() {
|
||||
ipcRenderer.invoke(UPDATE_START_DOWNLOAD)
|
||||
},
|
||||
installAndRestart() {
|
||||
ipcRenderer.invoke(UPDATE_INSTALL_AND_RESTART)
|
||||
},
|
||||
},
|
||||
})
|
||||
|
||||
|
||||
|
120
package-lock.json
generated
120
package-lock.json
generated
@ -7,6 +7,9 @@
|
||||
"": {
|
||||
"name": "Heynote",
|
||||
"version": "1.0.0",
|
||||
"dependencies": {
|
||||
"electron-log": "^4.4.8"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@codemirror/commands": "^6.1.2",
|
||||
"@codemirror/lang-cpp": "^6.0.2",
|
||||
@ -34,6 +37,7 @@
|
||||
"electron-builder": "^23.6.0",
|
||||
"electron-builder-notarize": "^1.5.1",
|
||||
"electron-store": "^8.1.0",
|
||||
"electron-updater": "^5.3.0",
|
||||
"fs-jetpack": "^5.1.0",
|
||||
"prettier": "^2.8.4",
|
||||
"sass": "^1.57.1",
|
||||
@ -1321,6 +1325,12 @@
|
||||
"@types/node": "*"
|
||||
}
|
||||
},
|
||||
"node_modules/@types/semver": {
|
||||
"version": "7.3.13",
|
||||
"resolved": "https://registry.npmjs.org/@types/semver/-/semver-7.3.13.tgz",
|
||||
"integrity": "sha512-21cFJr9z3g5dW8B0CVI9g2O9beqaThGQ6ZFBqHfwhzLDKUxaqTIy3vnfah/UPkfOiF2pLq+tGz+W8RyCskuslw==",
|
||||
"dev": true
|
||||
},
|
||||
"node_modules/@types/verror": {
|
||||
"version": "1.10.6",
|
||||
"resolved": "https://registry.npmjs.org/@types/verror/-/verror-1.10.6.tgz",
|
||||
@ -2831,6 +2841,11 @@
|
||||
"node": ">= 10.0.0"
|
||||
}
|
||||
},
|
||||
"node_modules/electron-log": {
|
||||
"version": "4.4.8",
|
||||
"resolved": "https://registry.npmjs.org/electron-log/-/electron-log-4.4.8.tgz",
|
||||
"integrity": "sha512-QQ4GvrXO+HkgqqEOYbi+DHL7hj5JM+nHi/j+qrN9zeeXVKy8ZABgbu4CnG+BBqDZ2+tbeq9tUC4DZfIWFU5AZA=="
|
||||
},
|
||||
"node_modules/electron-notarize": {
|
||||
"version": "1.2.2",
|
||||
"resolved": "https://registry.npmjs.org/electron-notarize/-/electron-notarize-1.2.2.tgz",
|
||||
@ -3005,6 +3020,73 @@
|
||||
"url": "https://github.com/sponsors/sindresorhus"
|
||||
}
|
||||
},
|
||||
"node_modules/electron-updater": {
|
||||
"version": "5.3.0",
|
||||
"resolved": "https://registry.npmjs.org/electron-updater/-/electron-updater-5.3.0.tgz",
|
||||
"integrity": "sha512-iKEr7yQBcvnQUPnSDYGSWC9t0eF2YbZWeYYYZzYxdl+HiRejXFENjYMnYjoOm2zxyD6Cr2JTHZhp9pqxiXuCOw==",
|
||||
"dev": true,
|
||||
"dependencies": {
|
||||
"@types/semver": "^7.3.6",
|
||||
"builder-util-runtime": "9.1.1",
|
||||
"fs-extra": "^10.0.0",
|
||||
"js-yaml": "^4.1.0",
|
||||
"lazy-val": "^1.0.5",
|
||||
"lodash.escaperegexp": "^4.1.2",
|
||||
"lodash.isequal": "^4.5.0",
|
||||
"semver": "^7.3.5",
|
||||
"typed-emitter": "^2.1.0"
|
||||
}
|
||||
},
|
||||
"node_modules/electron-updater/node_modules/fs-extra": {
|
||||
"version": "10.1.0",
|
||||
"resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-10.1.0.tgz",
|
||||
"integrity": "sha512-oRXApq54ETRj4eMiFzGnHWGy+zo5raudjuxN0b8H7s/RU2oW0Wvsx9O0ACRN/kRq9E8Vu/ReskGB5o3ji+FzHQ==",
|
||||
"dev": true,
|
||||
"dependencies": {
|
||||
"graceful-fs": "^4.2.0",
|
||||
"jsonfile": "^6.0.1",
|
||||
"universalify": "^2.0.0"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=12"
|
||||
}
|
||||
},
|
||||
"node_modules/electron-updater/node_modules/jsonfile": {
|
||||
"version": "6.1.0",
|
||||
"resolved": "https://registry.npmjs.org/jsonfile/-/jsonfile-6.1.0.tgz",
|
||||
"integrity": "sha512-5dgndWOriYSm5cnYaJNhalLNDKOqFwyDB/rr1E9ZsGciGvKPs8R2xYGCacuf3z6K1YKDz182fd+fY3cn3pMqXQ==",
|
||||
"dev": true,
|
||||
"dependencies": {
|
||||
"universalify": "^2.0.0"
|
||||
},
|
||||
"optionalDependencies": {
|
||||
"graceful-fs": "^4.1.6"
|
||||
}
|
||||
},
|
||||
"node_modules/electron-updater/node_modules/semver": {
|
||||
"version": "7.3.8",
|
||||
"resolved": "https://registry.npmjs.org/semver/-/semver-7.3.8.tgz",
|
||||
"integrity": "sha512-NB1ctGL5rlHrPJtFDVIVzTyQylMLu9N9VICA6HSFJo8MCGVTMW6gfpicwKmmK/dAjTOrqu5l63JJOpDSrAis3A==",
|
||||
"dev": true,
|
||||
"dependencies": {
|
||||
"lru-cache": "^6.0.0"
|
||||
},
|
||||
"bin": {
|
||||
"semver": "bin/semver.js"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=10"
|
||||
}
|
||||
},
|
||||
"node_modules/electron-updater/node_modules/universalify": {
|
||||
"version": "2.0.0",
|
||||
"resolved": "https://registry.npmjs.org/universalify/-/universalify-2.0.0.tgz",
|
||||
"integrity": "sha512-hAZsKq7Yy11Zu1DE0OzWjw7nnLZmJZYTDZZyEFHZdUhV8FkH5MCfoU1XMaxXovpyW5nq5scPqq0ZDP9Zyl04oQ==",
|
||||
"dev": true,
|
||||
"engines": {
|
||||
"node": ">= 10.0.0"
|
||||
}
|
||||
},
|
||||
"node_modules/emoji-regex": {
|
||||
"version": "8.0.0",
|
||||
"resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz",
|
||||
@ -3943,6 +4025,18 @@
|
||||
"integrity": "sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg==",
|
||||
"dev": true
|
||||
},
|
||||
"node_modules/lodash.escaperegexp": {
|
||||
"version": "4.1.2",
|
||||
"resolved": "https://registry.npmjs.org/lodash.escaperegexp/-/lodash.escaperegexp-4.1.2.tgz",
|
||||
"integrity": "sha512-TM9YBvyC84ZxE3rgfefxUWiQKLilstD6k7PTGt6wfbtXF8ixIJLOL3VYyV/z+ZiPLsVxAsKAFVwWlWeb2Y8Yyw==",
|
||||
"dev": true
|
||||
},
|
||||
"node_modules/lodash.isequal": {
|
||||
"version": "4.5.0",
|
||||
"resolved": "https://registry.npmjs.org/lodash.isequal/-/lodash.isequal-4.5.0.tgz",
|
||||
"integrity": "sha512-pDo3lu8Jhfjqls6GkMgpahsF9kCyayhgykjyLMNFTKWrpVdAQtYyB4muAMWozBB4ig/dtWAmsMxLEI8wuz+DYQ==",
|
||||
"dev": true
|
||||
},
|
||||
"node_modules/lowercase-keys": {
|
||||
"version": "2.0.0",
|
||||
"resolved": "https://registry.npmjs.org/lowercase-keys/-/lowercase-keys-2.0.0.tgz",
|
||||
@ -4676,6 +4770,16 @@
|
||||
"fsevents": "~2.3.2"
|
||||
}
|
||||
},
|
||||
"node_modules/rxjs": {
|
||||
"version": "7.8.0",
|
||||
"resolved": "https://registry.npmjs.org/rxjs/-/rxjs-7.8.0.tgz",
|
||||
"integrity": "sha512-F2+gxDshqmIub1KdvZkaEfGDwLNpPvk9Fs6LD/MyQxNgMds/WH9OdDDXOmxUZpME+iSK3rQCctkL0DYyytUqMg==",
|
||||
"dev": true,
|
||||
"optional": true,
|
||||
"dependencies": {
|
||||
"tslib": "^2.1.0"
|
||||
}
|
||||
},
|
||||
"node_modules/safer-buffer": {
|
||||
"version": "2.1.2",
|
||||
"resolved": "https://registry.npmjs.org/safer-buffer/-/safer-buffer-2.1.2.tgz",
|
||||
@ -5069,6 +5173,13 @@
|
||||
"utf8-byte-length": "^1.0.1"
|
||||
}
|
||||
},
|
||||
"node_modules/tslib": {
|
||||
"version": "2.5.0",
|
||||
"resolved": "https://registry.npmjs.org/tslib/-/tslib-2.5.0.tgz",
|
||||
"integrity": "sha512-336iVw3rtn2BUK7ORdIAHTyxHGRIHVReokCR3XjbckJMK7ms8FysBfhLR8IXnAgy7T0PTPNBWKiH514FOW/WSg==",
|
||||
"dev": true,
|
||||
"optional": true
|
||||
},
|
||||
"node_modules/type-fest": {
|
||||
"version": "0.13.1",
|
||||
"resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.13.1.tgz",
|
||||
@ -5082,6 +5193,15 @@
|
||||
"url": "https://github.com/sponsors/sindresorhus"
|
||||
}
|
||||
},
|
||||
"node_modules/typed-emitter": {
|
||||
"version": "2.1.0",
|
||||
"resolved": "https://registry.npmjs.org/typed-emitter/-/typed-emitter-2.1.0.tgz",
|
||||
"integrity": "sha512-g/KzbYKbH5C2vPkaXGu8DJlHrGKHLsM25Zg9WuC9pMGfuvT+X25tZQWo5fK1BjBm8+UrVE9LDCvaY0CQk+fXDA==",
|
||||
"dev": true,
|
||||
"optionalDependencies": {
|
||||
"rxjs": "*"
|
||||
}
|
||||
},
|
||||
"node_modules/typescript": {
|
||||
"version": "4.9.4",
|
||||
"resolved": "https://registry.npmjs.org/typescript/-/typescript-4.9.4.tgz",
|
||||
|
@ -52,6 +52,7 @@
|
||||
"electron-builder": "^23.6.0",
|
||||
"electron-builder-notarize": "^1.5.1",
|
||||
"electron-store": "^8.1.0",
|
||||
"electron-updater": "^5.3.0",
|
||||
"fs-jetpack": "^5.1.0",
|
||||
"prettier": "^2.8.4",
|
||||
"sass": "^1.57.1",
|
||||
@ -61,5 +62,8 @@
|
||||
"vite-plugin-electron-renderer": "^0.11.4",
|
||||
"vue": "^3.2.45",
|
||||
"vue-tsc": "^1.0.16"
|
||||
},
|
||||
"dependencies": {
|
||||
"electron-log": "^4.4.8"
|
||||
}
|
||||
}
|
||||
|
1
public/icons/update.svg
Normal file
1
public/icons/update.svg
Normal file
@ -0,0 +1 @@
|
||||
<svg viewBox="0 0 32 32" xml:space="preserve" xmlns="http://www.w3.org/2000/svg"><path d="M23.995 13.089c.001-.03.005-.059.005-.089a8 8 0 0 0-8-8c-3.814 0-6.998 2.671-7.8 6.242C5.208 12.038 3 14.757 3 18a7 7 0 0 0 7 7h13a5.997 5.997 0 0 0 .995-11.911zM16 21V11" fill="none" stroke="#ffffff" stroke-linecap="round" stroke-linejoin="round" stroke-miterlimit="10" stroke-width="2" class="stroke-000000"></path><path fill="none" stroke="#ffffff" stroke-linecap="round" stroke-linejoin="round" stroke-miterlimit="10" stroke-width="2" d="m12 17 4 4 4-4" class="stroke-000000"></path></svg>
|
After Width: | Height: | Size: 583 B |
@ -1,5 +1,7 @@
|
||||
<script>
|
||||
import UpdateStatusItem from './UpdateStatusItem.vue'
|
||||
import { LANGUAGES } from '../editor/languages.js'
|
||||
|
||||
const LANGUAGE_MAP = Object.fromEntries(LANGUAGES.map(l => [l.token, l]))
|
||||
const LANGUAGE_NAMES = Object.fromEntries(LANGUAGES.map(l => [l.token, l.name]))
|
||||
|
||||
@ -13,6 +15,10 @@
|
||||
"systemTheme",
|
||||
],
|
||||
|
||||
components: {
|
||||
UpdateStatusItem,
|
||||
},
|
||||
|
||||
mounted() {
|
||||
|
||||
},
|
||||
@ -40,6 +46,7 @@
|
||||
Ln <span class="num">{{ line }}</span>
|
||||
Col <span class="num">{{ column }}</span>
|
||||
</div>
|
||||
<UpdateStatusItem />
|
||||
<div class="spacer"></div>
|
||||
<div
|
||||
@click="$emit('openLanguageSelector')"
|
||||
|
110
src/components/UpdateStatusItem.vue
Normal file
110
src/components/UpdateStatusItem.vue
Normal file
@ -0,0 +1,110 @@
|
||||
<script>
|
||||
export default {
|
||||
data() {
|
||||
return {
|
||||
updateAvailable: false,
|
||||
updateDownloaded: false,
|
||||
downloading: false,
|
||||
updateProgress: {
|
||||
percent: 0.0,
|
||||
transferred: 0.0,
|
||||
total: 0.0,
|
||||
bytesPerSecond: 0.0,
|
||||
}
|
||||
}
|
||||
},
|
||||
|
||||
mounted() {
|
||||
window.heynote.autoUpdate.callbacks({
|
||||
updateAvailable: (info) => {
|
||||
//console.log("updateAvailable", info)
|
||||
this.updateAvailable = true
|
||||
this.currentVersion = info.currentVersion
|
||||
this.version = info.version
|
||||
},
|
||||
updateNotAvailable: () => {
|
||||
//console.log("updateNotAvailable")
|
||||
},
|
||||
updateDownloaded: () => {
|
||||
//console.log("updateDownloaded")
|
||||
this.updateDownloaded = true
|
||||
this.downloading = false
|
||||
},
|
||||
updateError: (error) => {
|
||||
console.log("Update error", error)
|
||||
this.downloading = false
|
||||
},
|
||||
updateDownloadProgress: (progress) => {
|
||||
//console.log("updateDownloadProgress", progress)
|
||||
this.downloading = true
|
||||
this.updateProgress = progress
|
||||
}
|
||||
})
|
||||
},
|
||||
|
||||
computed: {
|
||||
updateAvailableTitle() {
|
||||
return "Update to version " + this.version + " (current version: " + this.currentVersion + ")"
|
||||
},
|
||||
|
||||
restartTitle() {
|
||||
return "Click to restart and update Heynote "
|
||||
},
|
||||
|
||||
updateProgressPercent() {
|
||||
return this.updateProgress.percent.toFixed(0)
|
||||
}
|
||||
},
|
||||
|
||||
methods: {
|
||||
startDownload() {
|
||||
window.heynote.autoUpdate.startDownload()
|
||||
this.downloading = true
|
||||
},
|
||||
|
||||
installAndRestart() {
|
||||
window.heynote.autoUpdate.installAndRestart()
|
||||
},
|
||||
},
|
||||
|
||||
}
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<div v-if="downloading" class="status-block clickable update-status-block">
|
||||
<span class="icon-update"></span>
|
||||
Downloading update… {{ updateProgressPercent }}%
|
||||
</div>
|
||||
<div v-else-if="updateDownloaded" class="status-block clickable update-status-block" @click="installAndRestart" :title="restartTitle">
|
||||
<span class="icon-update"></span>
|
||||
Update & Restart
|
||||
</div>
|
||||
<div v-else-if="updateAvailable" class="status-block clickable update-status-block" :title="updateAvailableTitle" @click="startDownload">
|
||||
<span class="icon-update"></span>
|
||||
New version available!
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<style scoped lang="sass">
|
||||
=dark-mode()
|
||||
@media (prefers-color-scheme: dark)
|
||||
@content
|
||||
|
||||
.status .status-block.update-status-block
|
||||
position: relative
|
||||
padding-left: 30px
|
||||
|
||||
.icon-update
|
||||
display: block
|
||||
position: absolute
|
||||
left: 10px
|
||||
top: 0
|
||||
width: 16px
|
||||
height: 22px
|
||||
+dark-mode
|
||||
opacity: 0.9
|
||||
background-size: 16px
|
||||
background-repeat: no-repeat
|
||||
background-position: center center
|
||||
background-image: url("icons/update.svg")
|
||||
</style>
|
Loading…
Reference in New Issue
Block a user