From 39722d66149ebec1bbef18c0f7233984dd937562 Mon Sep 17 00:00:00 2001 From: Warinyourself Date: Fri, 25 Nov 2022 10:20:24 +0300 Subject: [PATCH] Add app bar for nody-greeter --- .eslintrc.js | 2 + README.md | 5 +- acpi.ts | 66 +++++ src/App.tsx | 2 + src/components/app/AppBar.tsx | 35 +++ src/components/app/AppIcon.vue | 51 ++++ src/components/app/AppMenu.tsx | 8 +- src/components/app/AppSelector.tsx | 15 +- src/components/base/BatteryIcon.tsx | 29 +++ src/components/base/UserAvatar.tsx | 28 +-- .../base/settings/SettingsCustom.tsx | 17 +- .../base/settings/general/SettingsGeneral.tsx | 9 +- src/components/themes/agida/index.tsx | 34 +-- src/components/themes/infinity.tsx | 4 +- src/locales/en.json | 1 + src/locales/ru.json | 4 +- src/models/app.ts | 15 +- src/models/lightdm.ts | 75 +++--- src/store/app.ts | 20 +- src/style/components/bar.styl | 64 +++++ src/style/components/index.styl | 9 +- src/style/components/login.styl | 14 +- src/style/components/selector.styl | 1 + src/style/components/slider.styl | 2 +- src/style/index.styl | 19 +- src/style/setup.styl | 4 - src/utils/constant.ts | 10 + src/utils/helper.ts | 9 +- src/utils/lightdm.ts | 230 +++++++++++------- src/utils/time.ts | 41 ++++ src/views/Home.tsx | 6 + test-greeter.sh | 5 +- 32 files changed, 621 insertions(+), 213 deletions(-) create mode 100644 acpi.ts create mode 100644 src/components/app/AppBar.tsx create mode 100644 src/components/base/BatteryIcon.tsx create mode 100644 src/style/components/bar.styl create mode 100644 src/utils/time.ts diff --git a/.eslintrc.js b/.eslintrc.js index e10e39f..d8d0939 100644 --- a/.eslintrc.js +++ b/.eslintrc.js @@ -12,6 +12,8 @@ module.exports = { indent: 'off', 'multiline-ternary': 'off', 'space-before-function-paren': [2, 'never'], + 'no-use-before-define': 'off', + '@typescript-eslint/no-use-before-define': 'warn', 'vue/array-bracket-spacing': 'error', 'vue/arrow-spacing': 'error', 'vue/block-spacing': 'error', diff --git a/README.md b/README.md index 847c61a..a0e7e8f 100644 --- a/README.md +++ b/README.md @@ -12,7 +12,7 @@ yay -S lightdm-webkit-theme-osmos ### Manual installation -Or set `greeter-session=lightdm-webkit2-greeter` in `/etc/lightdm/lightdm.conf`, then edit `/etc/lightdm/lightdm-webkit2-greeter.conf` to set `webkit_theme=lightdm-webkit-theme-osmos`. +Or set `greeter-session=lightdm-webkit2-greeter` in `/etc/lightdm/lightdm.conf`, then edit `/etc/lightdm/lightdm-webkit2-greeter.conf` to set `webkit_theme=osmos`. ## Themes ### [Random](https://warinyourself.github.io/lightdm-webkit-theme-osmos/?pxratio=0.8&animation-speed=5&symmetry=0.01&thickness=0.1&hue=360&brightness=1&invert=false&blur=false&no-transition=false&show-framerate=false&only-ui=true&themeName=Random) @@ -35,3 +35,6 @@ Or set `greeter-session=lightdm-webkit2-greeter` in `/etc/lightdm/lightdm.conf`, ### [Infinity](https://warinyourself.github.io/lightdm-webkit-theme-osmos/?palette=3&size=11&amount=50&animation-speed=20&blur=false&no-transition=false&show-framerate=false&only-ui=true&themeName=Infinity) ![Infinity](https://user-images.githubusercontent.com/83131232/153943210-e4cc3bc3-3ade-4323-a216-acf787b61d76.png) + +### Roadmap +- Integrates with \ No newline at end of file diff --git a/acpi.ts b/acpi.ts new file mode 100644 index 0000000..8a6105b --- /dev/null +++ b/acpi.ts @@ -0,0 +1,66 @@ +const child_process = require('child_process') +// import * as child_process from 'child_process' +// import { logger } from '../logger' + +const logger = { + error: console.error, + debug: console.log +} + +type Callback = (data: string) => void; + +class ACPIController { + public constructor() { + if (this.checkAcpi()) this.listen() + else logger.error('ACPI: acpi_listen does not exists') + } + + protected tries = 0; + protected callbacks: Callback[] = []; + + public connect(cb: Callback): void { + this.callbacks.push(cb) + } + + public disconnect(cb: Callback): void { + const ind = this.callbacks.findIndex((c) => { + return c === cb + }) + if (ind == -1) return + this.callbacks.splice(ind, 1) + } + + private checkAcpi(): boolean { + const res = child_process.spawnSync('which', ['acpi_listen'], { + encoding: 'utf-8' + }) + if (res.status == 0) return true + else return false + } + + private listen(): void { + const acpi = child_process.spawn('acpi_listen') + acpi.on('error', (err) => { + logger.error('ACPI: ' + err.message) + }) + acpi.on('close', () => { + if (this.tries < 5) { + this.tries++ + logger.debug('Restarting acpi_listen') + return this.listen() + } + }) + + acpi.stdout.addListener('data', (d: Buffer) => { + const data = d.toString().trim() + this.callbacks.forEach((cb) => { + console.log({ data }) + if (cb !== undefined) cb(data) + }) + }) + } +} + +const ACPI = new ACPIController() + +export { ACPI } diff --git a/src/App.tsx b/src/App.tsx index e9acf5a..af83927 100644 --- a/src/App.tsx +++ b/src/App.tsx @@ -4,6 +4,7 @@ import { AppModule } from '@/store/app' import { PageModule } from './store/page' import { Debounce, focusInputPassword } from './utils/helper' import { hotkeys } from '@/utils/hotkeys' +import { initTimer } from './utils/time' @Component export default class MainApp extends Vue { @@ -24,6 +25,7 @@ export default class MainApp extends Vue { created() { AppModule.setUpSettings() this.initKeybinds() + initTimer() } initKeybinds() { diff --git a/src/components/app/AppBar.tsx b/src/components/app/AppBar.tsx new file mode 100644 index 0000000..29397e2 --- /dev/null +++ b/src/components/app/AppBar.tsx @@ -0,0 +1,35 @@ +import { AppModule } from '@/store/app' +import { Component, Vue } from 'vue-property-decorator' +import AppIcon from './AppIcon.vue' +import timer from '@/utils/time' +import BatteryIcon from '../base/BatteryIcon' + +@Component({ + components: { AppIcon, BatteryIcon } +}) +export default class AppSelector extends Vue { + get batteryLevel() { + return AppModule.batteryLevel + } + + get brightLevel() { + return AppModule.brightness + } + + get currentTime() { + return timer.longTime + } + + render() { + return
+
{ timer.longTime }
+
+ +
+ + { this.brightLevel } +
+
+
+ } +} diff --git a/src/components/app/AppIcon.vue b/src/components/app/AppIcon.vue index 09af832..2e5b3f6 100644 --- a/src/components/app/AppIcon.vue +++ b/src/components/app/AppIcon.vue @@ -48,6 +48,57 @@ /> + + + + + + + + + + + + + + + + { this.handleCallback(item) }} > - { item.text } - { item.icon && } + { text } + { icon && } } diff --git a/src/components/app/AppSelector.tsx b/src/components/app/AppSelector.tsx index 8120c8c..cd531ea 100644 --- a/src/components/app/AppSelector.tsx +++ b/src/components/app/AppSelector.tsx @@ -19,12 +19,13 @@ export default class AppSelector extends Vue implements AppSelectorProps { selectedValue: null | AppMenuItem | string = null - get fullItem() { + get fullSelectedItem() { const selected = this.value !== null ? this.value : this.selectedValue + const finalSelectedValue = typeof selected === 'object' ? selected?.value : selected - return this.items.find(({ value }) => { - const finalValue = typeof selected === 'object' ? selected?.value : selected - return value === finalValue + return this.items.find((item) => { + const finalValue = typeof item === 'object' ? item?.value : item + return finalValue === finalSelectedValue }) } @@ -37,7 +38,7 @@ export default class AppSelector extends Vue implements AppSelectorProps { } get currentValueLabel() { - const selected = this.fullItem ?? this.selectedValue + const selected = this.fullSelectedItem ?? this.selectedValue return typeof selected === 'object' ? selected?.text : selected } @@ -65,10 +66,10 @@ export default class AppSelector extends Vue implements AppSelectorProps { } render() { - const selectorIcon = this.fullItem?.icon ? : null diff --git a/src/components/base/BatteryIcon.tsx b/src/components/base/BatteryIcon.tsx new file mode 100644 index 0000000..e421f49 --- /dev/null +++ b/src/components/base/BatteryIcon.tsx @@ -0,0 +1,29 @@ +import { AppModule } from '@/store/app' +import { Component, Vue } from 'vue-property-decorator' +import AppIcon from '@/components/app/AppIcon.vue' + +@Component({ + components: { AppIcon } +}) +export default class BatteryIcon extends Vue { + get batteryLevel() { + return AppModule.batteryLevel + } + + get isCharging() { + return AppModule.isCharging + } + + render() { + return
+
+
+ { this.isCharging && } +
+ { this.batteryLevel }% +
+ } +} diff --git a/src/components/base/UserAvatar.tsx b/src/components/base/UserAvatar.tsx index 4d5609d..03316f7 100644 --- a/src/components/base/UserAvatar.tsx +++ b/src/components/base/UserAvatar.tsx @@ -4,30 +4,14 @@ import { AppModule } from '@/store/app' import AppIcon from '@/components/app/AppIcon.vue' import { LightdmUsers } from '@/models/lightdm' import { PageModule } from '@/store/page' -import { DateTimeFormatOptions } from 'vue-i18n' +import timer from '@/utils/time' @Component({ components: { AppIcon } }) export default class UserAvatar extends Vue { - updater = new Date().getTime() - get currentTime() { - const options: DateTimeFormatOptions = { - month: 'short', - day: 'numeric', - hour: 'numeric', - minute: 'numeric', - hour12: false - } - - if (this.isOpenSettings) { - options.month = 'long' - options.day = 'numeric' - options.weekday = 'short' - } - - return new Intl.DateTimeFormat(this.locale, options).format(new Date()) + return this.isOpenSettings ? timer.longTime : timer.shortTime } get isOpenSettings() { @@ -46,12 +30,6 @@ export default class UserAvatar extends Vue { return AppModule.users } - mounted() { - this.updater = new Date().getTime() - - setInterval(() => { this.updater = new Date().getTime() }, 1000) - } - buildUserAvatar(image: string | undefined) { const defaultAvatar = const userAvatar =
-

{ this.currentTime }

+

{ this.currentTime }

{ this.buildUserAvatar(user?.image) }
{ user?.display_name }
diff --git a/src/components/base/settings/SettingsCustom.tsx b/src/components/base/settings/SettingsCustom.tsx index c80e911..6d0ed6e 100644 --- a/src/components/base/settings/SettingsCustom.tsx +++ b/src/components/base/settings/SettingsCustom.tsx @@ -1,7 +1,7 @@ import { Component, Vue } from 'vue-property-decorator' import { AppModule } from '@/store/app' -import { AppInputButton, AppInputColor, AppInputThemeGeneral, AppInputThemeSlider, AppTheme } from '@/models/app' +import { AppInputButton, AppInputColor, AppInputThemeGeneral, AppInputThemePalette, AppInputThemeSelector, AppInputThemeSlider, AppTheme } from '@/models/app' import AppSlider from '@/components/app/AppSlider' import AppButton from '@/components/app/AppButton' @@ -53,6 +53,16 @@ export default class SettingsCustom extends Vue { return } + buildSelector(input: AppInputThemeSelector) { + const { label, value, values } = input + const props = { label, value, items: values } + const handler = (value: number) => { + AppModule.changeSettingsThemeInput({ key: input.name, value }) + } + + return + } + buildColor(input: AppInputThemeGeneral) { const { label, value, options } = input const props = { label, value } @@ -81,7 +91,7 @@ export default class SettingsCustom extends Vue { return } - buildPalette(input: AppInputThemeGeneral) { + buildPalette(input: AppInputThemePalette) { const { label, value, values } = input const props = { label, value, values } const handler = (value: boolean) => { @@ -109,7 +119,8 @@ export default class SettingsCustom extends Vue { slider: this.buildSlider, checkbox: this.buildCheckbox, palette: this.buildPalette, - button: this.buildButton + button: this.buildButton, + selector: this.buildSelector } return