diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml new file mode 100644 index 0000000..077854f --- /dev/null +++ b/.github/workflows/release.yml @@ -0,0 +1,41 @@ +name: Mac release + +on: [release] + +jobs: + build: + runs-on: ${{ matrix.os }} + strategy: + matrix: + os: [macos-latest] + + steps: + - uses: actions/checkout@v1 + - name: Use Node.js 10.x + uses: actions/setup-node@v1 + with: + node-version: 10.x + - name: Dump runner context + env: + RUNNER_CONTEXT: ${{ toJson(runner) }} + run: echo "$RUNNER_CONTEXT" + - name: Windows build tools + if: runner.os == 'Windows' + run: npm install --vs2015 --global windows-build-tools + - name: Download newer npm + if: runner.os == 'Windows' + run: npm install npm@next -g + - name: npm install + run: npm ci --prefer-offline --no-audit + - name: npm lint + run: npm run lint + - name: npm build + run: npm run build + - name: Release + env: + GH_TOKEN: ${{ secrets.GH_TOKEN }} + APPLE_ID: ${{ secrets.APPLE_ID }} + APPLE_ID_PASSWORD: ${{ secrets.APPLE_ID_PASSWORD }} + CSC_LINK: ${{ secrets.CSC_LINK_MAC }} + CSC_KEY_PASSWORD: ${{ secrets.CSC_KEY_PASSWORD_MAC }} + run: npm run release diff --git a/README.md b/README.md index da576ad..f2c0b16 100644 --- a/README.md +++ b/README.md @@ -1,4 +1,8 @@ -# timenaut +# Timenaut + +![dashboard](/docs/dashboard.png) + +![processes](/docs/processes.png) ## Downloading diff --git a/build/afterSignHook.js b/build/afterSignHook.js new file mode 100644 index 0000000..df12567 --- /dev/null +++ b/build/afterSignHook.js @@ -0,0 +1,36 @@ +// See: https://medium.com/@TwitterArchiveEraser/notarize-electron-apps-7a5f988406db + +const fs = require('fs'); +const path = require('path'); +var electron_notarize = require('electron-notarize'); + +module.exports = async function (params) { + // Only notarize the app on Mac OS only. + if (process.platform !== 'darwin') { + return; + } + console.log('afterSign hook triggered', params); + + // Same appId in electron-builder. + let appId = 'app.timenaut.timenaut' + + let appPath = path.join(params.appOutDir, `${params.packager.appInfo.productFilename}.app`); + if (!fs.existsSync(appPath)) { + throw new Error(`Cannot find application at: ${appPath}`); + } + + console.log(`Notarizing ${appId} found at ${appPath}`); + + try { + await electron_notarize.notarize({ + appBundleId: appId, + appPath: appPath, + appleId: process.env.APPLE_ID, + appleIdPassword: process.env.APPLE_ID_PASSWORD, + }); + } catch (error) { + console.error(error); + } + + console.log(`Done notarizing ${appId}`); +}; \ No newline at end of file diff --git a/build/timenaut.entitlements b/build/timenaut.entitlements new file mode 100644 index 0000000..25c48f7 --- /dev/null +++ b/build/timenaut.entitlements @@ -0,0 +1,26 @@ + + + + + com.apple.security.automation.apple-events + + com.apple.security.cs.allow-dyld-environment-variables + + com.apple.security.cs.allow-jit + + com.apple.security.cs.allow-unsigned-executable-memory + + com.apple.security.cs.debugger + + com.apple.security.cs.disable-executable-page-protection + + com.apple.security.cs.disable-library-validation + + com.apple.security.files.user-selected.read-only + + com.apple.security.network.client + + com.apple.security.network.server + + + diff --git a/docs/dashboard.png b/docs/dashboard.png new file mode 100644 index 0000000..20d4099 Binary files /dev/null and b/docs/dashboard.png differ diff --git a/docs/processes.png b/docs/processes.png new file mode 100644 index 0000000..0999a61 Binary files /dev/null and b/docs/processes.png differ diff --git a/package-lock.json b/package-lock.json index bd2ca16..dd30228 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,6 +1,6 @@ { "name": "timenaut", - "version": "0.0.7-snapshot", + "version": "0.1.0", "lockfileVersion": 1, "requires": true, "dependencies": { @@ -1360,6 +1360,15 @@ "integrity": "sha512-aX+gFgA5GHcDi89KG5keey2zf0WfZk/HAQotEamsK2kbey+8yGKcson0hbK8E+v0NArlCJQCqMP161YhV6ZXLg==", "dev": true }, + "@types/node-schedule": { + "version": "1.2.4", + "resolved": "https://registry.npmjs.org/@types/node-schedule/-/node-schedule-1.2.4.tgz", + "integrity": "sha512-s8ie8rUwAtX0Si75SiKH14akE/Ofw/Hx4Exbulv4wOQJEDerI7zeOaDODr/a1UEaHN19VkmZCt9Q0rFEKrVE5g==", + "dev": true, + "requires": { + "@types/node": "*" + } + }, "@types/normalize-package-data": { "version": "2.4.0", "resolved": "https://registry.npmjs.org/@types/normalize-package-data/-/normalize-package-data-2.4.0.tgz", @@ -4342,6 +4351,15 @@ "sha.js": "^2.4.8" } }, + "cron-parser": { + "version": "2.13.0", + "resolved": "https://registry.npmjs.org/cron-parser/-/cron-parser-2.13.0.tgz", + "integrity": "sha512-UWeIpnRb0eyoWPVk+pD3TDpNx3KCFQeezO224oJIkktBrcW6RoAPOx5zIKprZGfk6vcYSmA8yQXItejSaDBhbQ==", + "requires": { + "is-nan": "^1.2.1", + "moment-timezone": "^0.5.25" + } + }, "cross-spawn": { "version": "6.0.5", "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-6.0.5.tgz", @@ -4864,7 +4882,6 @@ "version": "1.1.3", "resolved": "https://registry.npmjs.org/define-properties/-/define-properties-1.1.3.tgz", "integrity": "sha512-3MqfYKj2lLzdMSf8ZIZE/V+Zuy+BgD6f164e8K2w7dgnpKArBDerGYpM46IYYcjnkdPNMjPk9A6VFB8+3SKlXQ==", - "dev": true, "requires": { "object-keys": "^1.0.12" } @@ -5357,6 +5374,29 @@ "integrity": "sha512-W5pjj9DtXjSHaJWH1VWSgBweJxeZ6OEBAIOzSbu6coKFYxXPGRyg9FAILYbnDt0iJT8r6YQqjEnYgmGJn/LoAg==", "dev": true }, + "electron-notarize": { + "version": "0.1.1", + "resolved": "https://registry.npmjs.org/electron-notarize/-/electron-notarize-0.1.1.tgz", + "integrity": "sha512-TpKfJcz4LXl5jiGvZTs5fbEx+wUFXV5u8voeG5WCHWfY/cdgdD8lDZIZRqLVOtR3VO+drgJ9aiSHIO9TYn/fKg==", + "dev": true, + "requires": { + "debug": "^4.1.1", + "fs-extra": "^8.0.1" + }, + "dependencies": { + "fs-extra": { + "version": "8.1.0", + "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-8.1.0.tgz", + "integrity": "sha512-yhlQgA6mnOJUKOsRUFsgJdQCvkKhcz8tlZG5HBQfReYZy46OwLcY+Zia0mtdHsOo9y/hP+CxMN0TU9QxoOtG4g==", + "dev": true, + "requires": { + "graceful-fs": "^4.2.0", + "jsonfile": "^4.0.0", + "universalify": "^0.1.0" + } + } + } + }, "electron-publish": { "version": "21.2.0", "resolved": "https://registry.npmjs.org/electron-publish/-/electron-publish-21.2.0.tgz", @@ -8444,6 +8484,14 @@ } } }, + "is-nan": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/is-nan/-/is-nan-1.2.1.tgz", + "integrity": "sha1-n69ltvttskt/XAYoR16nH5iEAeI=", + "requires": { + "define-properties": "^1.1.1" + } + }, "is-npm": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/is-npm/-/is-npm-3.0.0.tgz", @@ -9111,6 +9159,11 @@ "integrity": "sha512-LoEDv5pgpvWgPF4kNYuIp0qqSJVWak/dML0RY74xlzMZiT9w77teNAwKYKWBTYjlokMirg+o3jBwp+vlLrcfAA==", "dev": true }, + "long-timeout": { + "version": "0.1.1", + "resolved": "https://registry.npmjs.org/long-timeout/-/long-timeout-0.1.1.tgz", + "integrity": "sha1-lyHXiLR+C8taJMLivuGg2lXatRQ=" + }, "loose-envify": { "version": "1.4.0", "resolved": "https://registry.npmjs.org/loose-envify/-/loose-envify-1.4.0.tgz", @@ -9519,6 +9572,14 @@ "resolved": "https://registry.npmjs.org/moment/-/moment-2.24.0.tgz", "integrity": "sha512-bV7f+6l2QigeBBZSM/6yTNq4P2fNpSWj/0e7jQcy87A8e7o2nAfP/34/2ky5Vw4B9S446EtIhodAzkFCcR4dQg==" }, + "moment-timezone": { + "version": "0.5.26", + "resolved": "https://registry.npmjs.org/moment-timezone/-/moment-timezone-0.5.26.tgz", + "integrity": "sha512-sFP4cgEKTCymBBKgoxZjYzlSovC20Y6J7y3nanDc5RoBIXKlZhoYwBoZGe3flwU6A372AcRwScH8KiwV6zjy1g==", + "requires": { + "moment": ">= 2.9.0" + } + }, "move-concurrently": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/move-concurrently/-/move-concurrently-1.0.1.tgz", @@ -9706,6 +9767,16 @@ "semver": "^5.3.0" } }, + "node-schedule": { + "version": "1.3.2", + "resolved": "https://registry.npmjs.org/node-schedule/-/node-schedule-1.3.2.tgz", + "integrity": "sha512-GIND2pHMHiReSZSvS6dpZcDH7pGPGFfWBIEud6S00Q8zEIzAs9ommdyRK1ZbQt8y1LyZsJYZgPnyi7gpU2lcdw==", + "requires": { + "cron-parser": "^2.7.3", + "long-timeout": "0.1.1", + "sorted-array-functions": "^1.0.0" + } + }, "normalize-package-data": { "version": "2.5.0", "resolved": "https://registry.npmjs.org/normalize-package-data/-/normalize-package-data-2.5.0.tgz", @@ -9856,8 +9927,7 @@ "object-keys": { "version": "1.1.1", "resolved": "https://registry.npmjs.org/object-keys/-/object-keys-1.1.1.tgz", - "integrity": "sha512-NuAESUOUMrlIXOfHKzD6bpPu3tYt3xvjNdRIQ+FeT0lNb4K8WR70CaDxhuNguS2XG+GjkyMwOzsN5ZktImfhLA==", - "dev": true + "integrity": "sha512-NuAESUOUMrlIXOfHKzD6bpPu3tYt3xvjNdRIQ+FeT0lNb4K8WR70CaDxhuNguS2XG+GjkyMwOzsN5ZktImfhLA==" }, "object-visit": { "version": "1.0.1", @@ -12648,6 +12718,11 @@ "is-plain-obj": "^1.0.0" } }, + "sorted-array-functions": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/sorted-array-functions/-/sorted-array-functions-1.2.0.tgz", + "integrity": "sha512-sWpjPhIZJtqO77GN+LD8dDsDKcWZ9GCOJNqKzi1tvtjGIzwfoyuRH8S0psunmc6Z5P+qfDqztSbwYR5X/e1UTg==" + }, "source-list-map": { "version": "2.0.1", "resolved": "https://registry.npmjs.org/source-list-map/-/source-list-map-2.0.1.tgz", diff --git a/package.json b/package.json index 441cd5a..e619067 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "timenaut", - "version": "0.0.9", + "version": "0.1.0", "author": "Karl Martin Teras", "description": "Timenaut is software to monitor your computer usage and give you feedback to help you improve.", "private": true, @@ -26,11 +26,13 @@ "vue-class-component": "^7.0.2", "vue-property-decorator": "^8.1.0", "auto-launch": "^5.0.5", - "electron-updater": "^4.1.2" + "electron-updater": "^4.1.2", + "node-schedule": "^1.3.2" }, "devDependencies": { - "@types/better-sqlite3": "^5.4.0", "@types/auto-launch": "^5.0.1", + "@types/better-sqlite3": "^5.4.0", + "@types/node-schedule": "^1.2.4", "@vue/cli-plugin-babel": "^3.10.0", "@vue/cli-plugin-eslint": "^3.10.0", "@vue/cli-plugin-typescript": "^3.10.0", @@ -40,6 +42,7 @@ "electron": "^6.0.0", "electron-icon-builder": "^1.0.1", "electron-log": "^3.0.7", + "electron-notarize": "^0.1.1", "eslint": "^5.16.0", "eslint-plugin-vue": "^5.0.0", "typescript": "^3.4.3", diff --git a/src/app.vue b/src/app.vue index 97cbee7..24845fc 100644 --- a/src/app.vue +++ b/src/app.vue @@ -15,7 +15,7 @@ import Updatable from "@/components/updatable"; interface PageComponent { - new (): Updatable; + new(): Updatable; } type NavigationItem = { @@ -99,4 +99,33 @@ .bold { font-weight: bold; } + + input[type=text], + input[type=number], + input[type=password] + { + padding-top: 8px; + padding-bottom: 8px; + border-width: 1px; + border-radius: 4px; + border-color: #cbd5e0; + border-style: solid; + line-height: 1.25; + color: #2d3748; + font-size: 16px; + padding-left: 12px; + padding-right: 12px; + margin-left: 10px; + box-shadow: 0 1px 3px 0 rgba(0,0,0,.1), 0 1px 2px 0 rgba(0,0,0,.06); + height: 35px; + } + + input[type=checkbox]{ + margin-left: 12px; + position: absolute; + cursor: pointer; + width: 18px; + height: 18px; + } + diff --git a/src/background.ts b/src/background.ts index c89c4d0..c77d409 100644 --- a/src/background.ts +++ b/src/background.ts @@ -10,6 +10,7 @@ import AutoLaunch from 'auto-launch'; import path from 'path'; import log from 'electron-log' import Settings from "@/services/settings"; +import {scheduleJob} from 'node-schedule' const isDevelopment = process.env.NODE_ENV !== 'production'; @@ -49,6 +50,12 @@ let menuItems = [ { type: 'separator' }, + { + label: "Check for updates", + click() { + autoUpdaterService.check(); + } + }, { label: 'Quit', click() { @@ -127,6 +134,8 @@ async function createWindow() { autoUpdaterService.check(); + scheduleJob("* * 14 * *", autoUpdaterService.check); + autoLauncher = new AutoLaunch(autostartOptions); if (process.env.WEBPACK_DEV_SERVER_URL) { diff --git a/src/components/settings.vue b/src/components/settings.vue index 5c2723d..1acd325 100644 --- a/src/components/settings.vue +++ b/src/components/settings.vue @@ -1,28 +1,36 @@