From 3c0a82293c580b0b49da2a313eed0fc4d23fca28 Mon Sep 17 00:00:00 2001 From: Alex Inkin Date: Sat, 4 Mar 2023 02:31:19 +0800 Subject: [PATCH] Night theme (#2137) * feat: add themes * fix: remove obvious issues with light theme * chore: improve light theme a bit * comment out theme swticher * chore: make login dark * add theme and widgets to seeds * add theme and widgets to migration --------- Co-authored-by: Matt Hill --- backend/src/version/v0_3_3_1.rs | 9 +- frontend/angular.json | 1 - frontend/package-lock.json | 172 +++++++++--------- frontend/package.json | 12 +- frontend/patchdb-ui-seed.json | 4 +- .../src/pages/list/item/item.component.html | 2 +- .../pages/list/search/search.component.html | 2 +- .../src/pages/list/search/search.component.ts | 4 + .../src/pages/list/search/search.module.ts | 3 +- .../projects/shared/assets/img/logo_dark.png | Bin 0 -> 19760 bytes frontend/projects/shared/src/public-api.ts | 6 + .../dark-theme/dark-theme.component.scss | 1 + .../themes/dark-theme/dark-theme.component.ts | 15 ++ .../themes/dark-theme/dark-theme.module.ts | 9 + .../light-theme/light-theme.component.scss | 95 ++++++++++ .../light-theme/light-theme.component.ts | 15 ++ .../themes/light-theme/light-theme.module.ts | 9 + frontend/projects/shared/src/tokens/theme.ts | 6 + .../projects/shared/styles/variables.scss | 4 +- .../projects/ui/src/app/app.component.html | 15 +- .../projects/ui/src/app/app.component.scss | 6 + frontend/projects/ui/src/app/app.component.ts | 6 +- frontend/projects/ui/src/app/app.module.ts | 4 + frontend/projects/ui/src/app/app.providers.ts | 7 +- .../ui/src/app/app/menu/menu.component.html | 9 +- .../ui/src/app/app/menu/menu.component.scss | 11 +- .../ui/src/app/app/menu/menu.component.ts | 11 +- .../app/app/preloader/preloader.component.ts | 1 + .../connection-bar.component.html | 6 +- .../connection-bar.component.ts | 4 - .../form-object/form-object.component.html | 6 +- .../form-object/form-object.component.ts | 6 +- .../generic-input.component.html | 5 +- .../generic-input/generic-input.component.ts | 6 +- .../app-list-pkg/app-list-pkg.component.html | 3 +- .../apps-routes/app-list/app-list.module.ts | 2 + .../app-show-header.component.html | 8 +- .../app-show-header.component.scss | 12 +- .../ui/src/app/pages/login/login.module.ts | 2 +- .../ui/src/app/pages/login/login.page.html | 44 ++--- .../ui/src/app/pages/login/login.page.scss | 64 ++++--- .../server-show/server-show.module.ts | 2 + .../server-show/server-show.page.html | 108 +++++------ .../server-routes/sideload/sideload.page.html | 2 +- .../server-routes/sideload/sideload.page.scss | 2 +- .../theme-switcher.component.html | 23 +++ .../theme-switcher.component.ts | 23 +++ .../theme-switcher/theme-switcher.module.ts | 14 ++ .../src/app/pages/widgets/widgets.page.scss | 2 +- .../ui/src/app/services/api/mock-patch.ts | 1 + .../src/app/services/patch-db/data-model.ts | 1 + .../app/services/theme-switcher.service.ts | 33 ++++ frontend/projects/ui/src/styles.scss | 17 +- 53 files changed, 598 insertions(+), 237 deletions(-) create mode 100644 frontend/projects/shared/assets/img/logo_dark.png create mode 100644 frontend/projects/shared/src/themes/dark-theme/dark-theme.component.scss create mode 100644 frontend/projects/shared/src/themes/dark-theme/dark-theme.component.ts create mode 100644 frontend/projects/shared/src/themes/dark-theme/dark-theme.module.ts create mode 100644 frontend/projects/shared/src/themes/light-theme/light-theme.component.scss create mode 100644 frontend/projects/shared/src/themes/light-theme/light-theme.component.ts create mode 100644 frontend/projects/shared/src/themes/light-theme/light-theme.module.ts create mode 100644 frontend/projects/shared/src/tokens/theme.ts create mode 100644 frontend/projects/ui/src/app/pages/server-routes/theme-switcher/theme-switcher.component.html create mode 100644 frontend/projects/ui/src/app/pages/server-routes/theme-switcher/theme-switcher.component.ts create mode 100644 frontend/projects/ui/src/app/pages/server-routes/theme-switcher/theme-switcher.module.ts create mode 100644 frontend/projects/ui/src/app/services/theme-switcher.service.ts diff --git a/backend/src/version/v0_3_3_1.rs b/backend/src/version/v0_3_3_1.rs index 88874fca5..46cf6b921 100644 --- a/backend/src/version/v0_3_3_1.rs +++ b/backend/src/version/v0_3_3_1.rs @@ -1,6 +1,6 @@ use async_trait::async_trait; use emver::VersionRange; -use serde_json::json; +use serde_json::{json, Value}; use super::v0_3_0::V0_3_0_COMPAT; use super::*; @@ -61,6 +61,8 @@ impl VersionT for Version { .put(db, &parsed_url) .await?; } + ui["theme"] = json!("Dark".to_string()); + ui["widgets"] = json!([]); Ok(()) } async fn down(&self, db: &mut Db) -> Result<(), Error> { @@ -87,6 +89,11 @@ impl VersionT for Version { .await?; } + if let Value::Object(ref mut obj) = *ui { + obj.remove("theme"); + obj.remove("widgets"); + } + ui["marketplace"]["known-hosts"][COMMUNITY_URL].take(); ui.save(db).await?; Ok(()) diff --git a/frontend/angular.json b/frontend/angular.json index 4f716e2df..cd42198b1 100644 --- a/frontend/angular.json +++ b/frontend/angular.json @@ -46,7 +46,6 @@ "node_modules/@taiga-ui/core/styles/taiga-ui-theme.less", "node_modules/@taiga-ui/core/styles/taiga-ui-fonts.less", "node_modules/@taiga-ui/styles/taiga-ui-global.less", - "projects/shared/styles/variables.scss", "projects/shared/styles/global.scss", "projects/shared/styles/shared.scss", "projects/ui/src/styles.scss" diff --git a/frontend/package-lock.json b/frontend/package-lock.json index 3c90f02c7..3b686e6ae 100644 --- a/frontend/package-lock.json +++ b/frontend/package-lock.json @@ -23,12 +23,12 @@ "@ng-web-apis/resize-observer": "^2.0.0", "@start9labs/argon2": "^0.1.0", "@start9labs/emver": "^0.1.5", - "@taiga-ui/addon-charts": "^3.14.0", - "@taiga-ui/cdk": "^3.14.0", - "@taiga-ui/core": "^3.14.0", - "@taiga-ui/icons": "^3.14.0", - "@taiga-ui/kit": "^3.14.0", - "@taiga-ui/styles": "^3.14.0", + "@taiga-ui/addon-charts": "^3.16.0", + "@taiga-ui/cdk": "^3.16.0", + "@taiga-ui/core": "^3.16.0", + "@taiga-ui/icons": "^3.16.0", + "@taiga-ui/kit": "^3.16.0", + "@taiga-ui/styles": "^3.16.0", "angular-svg-round-progressbar": "^9.0.0", "ansi-to-html": "^0.7.2", "base64-js": "^1.5.1", @@ -3277,9 +3277,9 @@ } }, "node_modules/@ng-web-apis/common": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/@ng-web-apis/common/-/common-2.0.1.tgz", - "integrity": "sha512-DqnH+zZFFKeINpbFIzCrBTYksP+7FqrHxWo2+jIXfMLjSngwZ6WYz3F4N9s+tFc8mKe8I1/P7pZtxD7fqSPtlA==", + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/@ng-web-apis/common/-/common-2.1.0.tgz", + "integrity": "sha512-6DLtrsk59z9YwfR8Pm1DiExXpxvMk/RVry/mfsAKkyRmgCGICgDdyQ+eWMVhrOIyUAtt9V+DRvHUeC6iYaHKNQ==", "dependencies": { "tslib": "^2.2.0" }, @@ -3575,30 +3575,30 @@ } }, "node_modules/@taiga-ui/addon-charts": { - "version": "3.14.0", - "resolved": "https://registry.npmjs.org/@taiga-ui/addon-charts/-/addon-charts-3.14.0.tgz", - "integrity": "sha512-KnQ4ioYWjV+xyEj7eTnGScAWLBMFtkEzdnSZdg47HFFKaqg7gW08A0Wx8qNTKeHJK7wwjeVSbcPjZBNfKv4zKQ==", + "version": "3.16.0", + "resolved": "https://registry.npmjs.org/@taiga-ui/addon-charts/-/addon-charts-3.16.0.tgz", + "integrity": "sha512-b4jvFRKle+jBHCq71BH09ut9cs0mztR+ht99c6OZf6IeyHZuNUsVjOqONxpL3FMKbvIWvW+YXQdkcHx3+vDcFA==", "dependencies": { - "tslib": "^2.0.0" + "tslib": ">=2.0.0" }, "peerDependencies": { "@angular/common": ">=12.0.0", "@angular/core": ">=12.0.0", "@ng-web-apis/common": ">=2.0.0", - "@taiga-ui/cdk": ">=3.14.0", - "@taiga-ui/core": ">=3.14.0", + "@taiga-ui/cdk": ">=3.16.0", + "@taiga-ui/core": ">=3.16.0", "@tinkoff/ng-polymorpheus": ">=4.0.0" } }, "node_modules/@taiga-ui/cdk": { - "version": "3.14.0", - "resolved": "https://registry.npmjs.org/@taiga-ui/cdk/-/cdk-3.14.0.tgz", - "integrity": "sha512-Yhk0+IQOWfXmx8UWz61dBexA2hxDOEC0YHmpoQyIVQ6K5GXXpSywkf24WbxWGqQaoKYhECRmL8UxruAYZ8sI9A==", + "version": "3.16.0", + "resolved": "https://registry.npmjs.org/@taiga-ui/cdk/-/cdk-3.16.0.tgz", + "integrity": "sha512-r6buMYMYsQfokYLwUvwZibR0JJODf/jrWDYTITxuHb4ZTVLz0YYNbERiD6Y2cgtBRUhj9W3lr712eWdYJxZpGA==", "dependencies": { - "@ng-web-apis/common": "2.0.1", + "@ng-web-apis/common": "2.1.0", "@ng-web-apis/mutation-observer": "2.0.0", "@ng-web-apis/resize-observer": "2.0.0", - "@tinkoff/ng-event-plugins": "3.0.0", + "@tinkoff/ng-event-plugins": "3.1.0", "@tinkoff/ng-polymorpheus": "4.0.10", "tslib": "^2.0.0" }, @@ -3615,12 +3615,12 @@ } }, "node_modules/@taiga-ui/core": { - "version": "3.14.0", - "resolved": "https://registry.npmjs.org/@taiga-ui/core/-/core-3.14.0.tgz", - "integrity": "sha512-qiURNOAPUmsFPkDm1v8a+4SX+aGJVry9f3+XpCgfNM6boPnZ+ggdFG2KyVow6sCAr+kDuw8aUACYtO/ngxdeuw==", + "version": "3.16.0", + "resolved": "https://registry.npmjs.org/@taiga-ui/core/-/core-3.16.0.tgz", + "integrity": "sha512-HCJhDOIE1hO4JZxL2ZK6+bFkZB/dREIbqBr684GhcBo4s6VA9mW1tqqr4gqXXXu0FvM9FGFzZpF9Gm+teeprXw==", "dependencies": { - "@taiga-ui/i18n": "^3.14.0", - "tslib": "^2.0.0" + "@taiga-ui/i18n": "^3.16.0", + "tslib": ">=2.0.0" }, "peerDependencies": { "@angular/animations": ">=12.0.0", @@ -3631,19 +3631,19 @@ "@angular/router": ">=12.0.0", "@ng-web-apis/common": ">=2.0.0", "@ng-web-apis/mutation-observer": ">=2.0.0", - "@taiga-ui/cdk": ">=3.14.0", - "@taiga-ui/i18n": ">=3.14.0", - "@tinkoff/ng-event-plugins": ">=3.0.0", + "@taiga-ui/cdk": ">=3.16.0", + "@taiga-ui/i18n": ">=3.16.0", + "@tinkoff/ng-event-plugins": ">=3.1.0", "@tinkoff/ng-polymorpheus": ">=4.0.0", "rxjs": ">=6.0.0" } }, "node_modules/@taiga-ui/i18n": { - "version": "3.14.0", - "resolved": "https://registry.npmjs.org/@taiga-ui/i18n/-/i18n-3.14.0.tgz", - "integrity": "sha512-GK4DP+UfBy4AGNsTebfN8TvUKi3QAi2I8+5nMULAjE1qzQd5WEkeXhV+dzLcSkxPbbzPGzSB+23Nnfn/A5IDlQ==", + "version": "3.16.0", + "resolved": "https://registry.npmjs.org/@taiga-ui/i18n/-/i18n-3.16.0.tgz", + "integrity": "sha512-ieFXTSUY4phXL4YuW5+26Ceqxx4JVMj1En3rXUr3mysLDPRYzyKfeW+gqql4n3hmkqGDsdnmtHvkqcEVePzWAw==", "dependencies": { - "tslib": "^2.0.0" + "tslib": ">=2.0.0" }, "peerDependencies": { "@angular/core": ">=12.0.0", @@ -3651,21 +3651,21 @@ } }, "node_modules/@taiga-ui/icons": { - "version": "3.14.0", - "resolved": "https://registry.npmjs.org/@taiga-ui/icons/-/icons-3.14.0.tgz", - "integrity": "sha512-+I2DYwFsRaYxbX92FCYWcRijvMKZWOZDlmzBkZc+CihF5wm46KTQichZ3iMZ3xACY9czDzcy123iUJqKT+fVRw==", + "version": "3.16.0", + "resolved": "https://registry.npmjs.org/@taiga-ui/icons/-/icons-3.16.0.tgz", + "integrity": "sha512-7EeFTUIpwEJbwFmyRmHvgN2rECygVg/VzqCPgjxM4ThS9VNbtTa0rJzORuA4t4jN+vBBA80wMjcxcI5Kq+jvow==", "dependencies": { - "tslib": "^2.0.0" + "tslib": "^2.2.0" } }, "node_modules/@taiga-ui/kit": { - "version": "3.14.0", - "resolved": "https://registry.npmjs.org/@taiga-ui/kit/-/kit-3.14.0.tgz", - "integrity": "sha512-YjSjpuqQYsMsMOLCn7edTGL+VEL3D0wpD7hY1GK4r+TPGTLQi1jby0PxsYbrjGZQ2EavwFuRI59/gqsDis6HIQ==", + "version": "3.16.0", + "resolved": "https://registry.npmjs.org/@taiga-ui/kit/-/kit-3.16.0.tgz", + "integrity": "sha512-HfFGutcJmpzXv+99GxV8ciSOgTyOATls4lYvVoWOwnm+4fJAMJ2vh7OA5+yWBrn8I0XpVXtPGIM7e4H2tXk2HQ==", "dependencies": { "@ng-web-apis/intersection-observer": "^3.0.0", - "text-mask-core": "^5.0.0", - "tslib": "^2.0.0" + "text-mask-core": "^5.1.2", + "tslib": ">=2.0.0" }, "peerDependencies": { "@angular/common": ">=12.0.0", @@ -3674,22 +3674,22 @@ "@angular/router": ">=12.0.0", "@ng-web-apis/common": ">=2.0.0", "@ng-web-apis/mutation-observer": ">=2.0.0", - "@taiga-ui/cdk": ">=3.14.0", - "@taiga-ui/core": ">=3.14.0", - "@taiga-ui/i18n": ">=3.14.0", + "@taiga-ui/cdk": ">=3.16.0", + "@taiga-ui/core": ">=3.16.0", + "@taiga-ui/i18n": ">=3.16.0", "@tinkoff/ng-polymorpheus": ">=4.0.0", "rxjs": ">=6.0.0" } }, "node_modules/@taiga-ui/styles": { - "version": "3.14.0", - "resolved": "https://registry.npmjs.org/@taiga-ui/styles/-/styles-3.14.0.tgz", - "integrity": "sha512-xo/aPqexXPUNesmnPMNhwpz4gj5PVHp+aKDcvv4+MCSBaiPTd6nE4wTXMaOW/EdkXrPHqWnxwnTec8SUwX5D9g==" + "version": "3.16.0", + "resolved": "https://registry.npmjs.org/@taiga-ui/styles/-/styles-3.16.0.tgz", + "integrity": "sha512-Wp2tq5njfdGCgr7t54+5XfI7Bj69+M0BdGYKoXEr74pTzFq2yG2Rqo3vSaujD8L8NnmRfHR7ue9v/BSNgbIcwg==" }, "node_modules/@tinkoff/ng-event-plugins": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/@tinkoff/ng-event-plugins/-/ng-event-plugins-3.0.0.tgz", - "integrity": "sha512-3+5R86ozam9uevQ5N7+B/lPMWYCfQGxUOxuSp6qccpPTWqCjTBGjlhRVdt11r6S+3Gx2r9y4rgZ1Q1/P58MOFA==", + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/@tinkoff/ng-event-plugins/-/ng-event-plugins-3.1.0.tgz", + "integrity": "sha512-HqLBes/3MV469L1S08uBqmPUIwihx43py+8Lee1Me9jMFM1ZMuAC3NcS/njUFI1OzXU2kIPyUDEw2jmVbg8mWQ==", "dependencies": { "tslib": "^2.2.0" }, @@ -17458,9 +17458,9 @@ } }, "@ng-web-apis/common": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/@ng-web-apis/common/-/common-2.0.1.tgz", - "integrity": "sha512-DqnH+zZFFKeINpbFIzCrBTYksP+7FqrHxWo2+jIXfMLjSngwZ6WYz3F4N9s+tFc8mKe8I1/P7pZtxD7fqSPtlA==", + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/@ng-web-apis/common/-/common-2.1.0.tgz", + "integrity": "sha512-6DLtrsk59z9YwfR8Pm1DiExXpxvMk/RVry/mfsAKkyRmgCGICgDdyQ+eWMVhrOIyUAtt9V+DRvHUeC6iYaHKNQ==", "requires": { "tslib": "^2.2.0" } @@ -17672,22 +17672,22 @@ "integrity": "sha512-NLEY8Jq59smyiivBAxHKipsp9YkkW/K/Vm90zAyXQqukb12i2SFucWHJ1Ik7ropVlhmMVvigyxXgRfQ9quIqtg==" }, "@taiga-ui/addon-charts": { - "version": "3.14.0", - "resolved": "https://registry.npmjs.org/@taiga-ui/addon-charts/-/addon-charts-3.14.0.tgz", - "integrity": "sha512-KnQ4ioYWjV+xyEj7eTnGScAWLBMFtkEzdnSZdg47HFFKaqg7gW08A0Wx8qNTKeHJK7wwjeVSbcPjZBNfKv4zKQ==", + "version": "3.16.0", + "resolved": "https://registry.npmjs.org/@taiga-ui/addon-charts/-/addon-charts-3.16.0.tgz", + "integrity": "sha512-b4jvFRKle+jBHCq71BH09ut9cs0mztR+ht99c6OZf6IeyHZuNUsVjOqONxpL3FMKbvIWvW+YXQdkcHx3+vDcFA==", "requires": { - "tslib": "^2.0.0" + "tslib": ">=2.0.0" } }, "@taiga-ui/cdk": { - "version": "3.14.0", - "resolved": "https://registry.npmjs.org/@taiga-ui/cdk/-/cdk-3.14.0.tgz", - "integrity": "sha512-Yhk0+IQOWfXmx8UWz61dBexA2hxDOEC0YHmpoQyIVQ6K5GXXpSywkf24WbxWGqQaoKYhECRmL8UxruAYZ8sI9A==", + "version": "3.16.0", + "resolved": "https://registry.npmjs.org/@taiga-ui/cdk/-/cdk-3.16.0.tgz", + "integrity": "sha512-r6buMYMYsQfokYLwUvwZibR0JJODf/jrWDYTITxuHb4ZTVLz0YYNbERiD6Y2cgtBRUhj9W3lr712eWdYJxZpGA==", "requires": { - "@ng-web-apis/common": "2.0.1", + "@ng-web-apis/common": "2.1.0", "@ng-web-apis/mutation-observer": "2.0.0", "@ng-web-apis/resize-observer": "2.0.0", - "@tinkoff/ng-event-plugins": "3.0.0", + "@tinkoff/ng-event-plugins": "3.1.0", "@tinkoff/ng-polymorpheus": "4.0.10", "ng-morph": "^2.1.0", "parse5": "^6.0.1", @@ -17695,49 +17695,49 @@ } }, "@taiga-ui/core": { - "version": "3.14.0", - "resolved": "https://registry.npmjs.org/@taiga-ui/core/-/core-3.14.0.tgz", - "integrity": "sha512-qiURNOAPUmsFPkDm1v8a+4SX+aGJVry9f3+XpCgfNM6boPnZ+ggdFG2KyVow6sCAr+kDuw8aUACYtO/ngxdeuw==", + "version": "3.16.0", + "resolved": "https://registry.npmjs.org/@taiga-ui/core/-/core-3.16.0.tgz", + "integrity": "sha512-HCJhDOIE1hO4JZxL2ZK6+bFkZB/dREIbqBr684GhcBo4s6VA9mW1tqqr4gqXXXu0FvM9FGFzZpF9Gm+teeprXw==", "requires": { - "@taiga-ui/i18n": "^3.14.0", - "tslib": "^2.0.0" + "@taiga-ui/i18n": "^3.16.0", + "tslib": ">=2.0.0" } }, "@taiga-ui/i18n": { - "version": "3.14.0", - "resolved": "https://registry.npmjs.org/@taiga-ui/i18n/-/i18n-3.14.0.tgz", - "integrity": "sha512-GK4DP+UfBy4AGNsTebfN8TvUKi3QAi2I8+5nMULAjE1qzQd5WEkeXhV+dzLcSkxPbbzPGzSB+23Nnfn/A5IDlQ==", + "version": "3.16.0", + "resolved": "https://registry.npmjs.org/@taiga-ui/i18n/-/i18n-3.16.0.tgz", + "integrity": "sha512-ieFXTSUY4phXL4YuW5+26Ceqxx4JVMj1En3rXUr3mysLDPRYzyKfeW+gqql4n3hmkqGDsdnmtHvkqcEVePzWAw==", "requires": { - "tslib": "^2.0.0" + "tslib": ">=2.0.0" } }, "@taiga-ui/icons": { - "version": "3.14.0", - "resolved": "https://registry.npmjs.org/@taiga-ui/icons/-/icons-3.14.0.tgz", - "integrity": "sha512-+I2DYwFsRaYxbX92FCYWcRijvMKZWOZDlmzBkZc+CihF5wm46KTQichZ3iMZ3xACY9czDzcy123iUJqKT+fVRw==", + "version": "3.16.0", + "resolved": "https://registry.npmjs.org/@taiga-ui/icons/-/icons-3.16.0.tgz", + "integrity": "sha512-7EeFTUIpwEJbwFmyRmHvgN2rECygVg/VzqCPgjxM4ThS9VNbtTa0rJzORuA4t4jN+vBBA80wMjcxcI5Kq+jvow==", "requires": { - "tslib": "^2.0.0" + "tslib": "^2.2.0" } }, "@taiga-ui/kit": { - "version": "3.14.0", - "resolved": "https://registry.npmjs.org/@taiga-ui/kit/-/kit-3.14.0.tgz", - "integrity": "sha512-YjSjpuqQYsMsMOLCn7edTGL+VEL3D0wpD7hY1GK4r+TPGTLQi1jby0PxsYbrjGZQ2EavwFuRI59/gqsDis6HIQ==", + "version": "3.16.0", + "resolved": "https://registry.npmjs.org/@taiga-ui/kit/-/kit-3.16.0.tgz", + "integrity": "sha512-HfFGutcJmpzXv+99GxV8ciSOgTyOATls4lYvVoWOwnm+4fJAMJ2vh7OA5+yWBrn8I0XpVXtPGIM7e4H2tXk2HQ==", "requires": { "@ng-web-apis/intersection-observer": "^3.0.0", - "text-mask-core": "^5.0.0", - "tslib": "^2.0.0" + "text-mask-core": "^5.1.2", + "tslib": ">=2.0.0" } }, "@taiga-ui/styles": { - "version": "3.14.0", - "resolved": "https://registry.npmjs.org/@taiga-ui/styles/-/styles-3.14.0.tgz", - "integrity": "sha512-xo/aPqexXPUNesmnPMNhwpz4gj5PVHp+aKDcvv4+MCSBaiPTd6nE4wTXMaOW/EdkXrPHqWnxwnTec8SUwX5D9g==" + "version": "3.16.0", + "resolved": "https://registry.npmjs.org/@taiga-ui/styles/-/styles-3.16.0.tgz", + "integrity": "sha512-Wp2tq5njfdGCgr7t54+5XfI7Bj69+M0BdGYKoXEr74pTzFq2yG2Rqo3vSaujD8L8NnmRfHR7ue9v/BSNgbIcwg==" }, "@tinkoff/ng-event-plugins": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/@tinkoff/ng-event-plugins/-/ng-event-plugins-3.0.0.tgz", - "integrity": "sha512-3+5R86ozam9uevQ5N7+B/lPMWYCfQGxUOxuSp6qccpPTWqCjTBGjlhRVdt11r6S+3Gx2r9y4rgZ1Q1/P58MOFA==", + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/@tinkoff/ng-event-plugins/-/ng-event-plugins-3.1.0.tgz", + "integrity": "sha512-HqLBes/3MV469L1S08uBqmPUIwihx43py+8Lee1Me9jMFM1ZMuAC3NcS/njUFI1OzXU2kIPyUDEw2jmVbg8mWQ==", "requires": { "tslib": "^2.2.0" } diff --git a/frontend/package.json b/frontend/package.json index 93abdd37f..a511c0d9b 100644 --- a/frontend/package.json +++ b/frontend/package.json @@ -47,12 +47,12 @@ "@ng-web-apis/resize-observer": "^2.0.0", "@start9labs/argon2": "^0.1.0", "@start9labs/emver": "^0.1.5", - "@taiga-ui/addon-charts": "^3.14.0", - "@taiga-ui/cdk": "^3.14.0", - "@taiga-ui/core": "^3.14.0", - "@taiga-ui/icons": "^3.14.0", - "@taiga-ui/kit": "^3.14.0", - "@taiga-ui/styles": "^3.14.0", + "@taiga-ui/addon-charts": "^3.16.0", + "@taiga-ui/cdk": "^3.16.0", + "@taiga-ui/core": "^3.16.0", + "@taiga-ui/icons": "^3.16.0", + "@taiga-ui/kit": "^3.16.0", + "@taiga-ui/styles": "^3.16.0", "angular-svg-round-progressbar": "^9.0.0", "ansi-to-html": "^0.7.2", "base64-js": "^1.5.1", diff --git a/frontend/patchdb-ui-seed.json b/frontend/patchdb-ui-seed.json index deb00df22..c22bbc864 100644 --- a/frontend/patchdb-ui-seed.json +++ b/frontend/patchdb-ui-seed.json @@ -14,5 +14,7 @@ "high-score": 0 } }, - "ack-instructions": {} + "ack-instructions": {}, + "theme": "Dark", + "widgets": [] } diff --git a/frontend/projects/marketplace/src/pages/list/item/item.component.html b/frontend/projects/marketplace/src/pages/list/item/item.component.html index 38ef01e1e..f13992d75 100644 --- a/frontend/projects/marketplace/src/pages/list/item/item.component.html +++ b/frontend/projects/marketplace/src/pages/list/item/item.component.html @@ -1,4 +1,4 @@ - + diff --git a/frontend/projects/marketplace/src/pages/list/search/search.component.html b/frontend/projects/marketplace/src/pages/list/search/search.component.html index 198ff6e95..1b19c8ec0 100644 --- a/frontend/projects/marketplace/src/pages/list/search/search.component.html +++ b/frontend/projects/marketplace/src/pages/list/search/search.component.html @@ -3,7 +3,7 @@ () + readonly theme$ = inject(THEME) + onModelChange(query: string) { this.query = query this.queryChange.emit(query) diff --git a/frontend/projects/marketplace/src/pages/list/search/search.module.ts b/frontend/projects/marketplace/src/pages/list/search/search.module.ts index 79c7b03ad..32aad93bb 100644 --- a/frontend/projects/marketplace/src/pages/list/search/search.module.ts +++ b/frontend/projects/marketplace/src/pages/list/search/search.module.ts @@ -1,3 +1,4 @@ +import { CommonModule } from '@angular/common' import { NgModule } from '@angular/core' import { FormsModule } from '@angular/forms' import { IonicModule } from '@ionic/angular' @@ -6,7 +7,7 @@ import { ResponsiveColModule } from '@start9labs/shared' import { SearchComponent } from './search.component' @NgModule({ - imports: [IonicModule, FormsModule, ResponsiveColModule], + imports: [IonicModule, FormsModule, CommonModule, ResponsiveColModule], declarations: [SearchComponent], exports: [SearchComponent], }) diff --git a/frontend/projects/shared/assets/img/logo_dark.png b/frontend/projects/shared/assets/img/logo_dark.png new file mode 100644 index 0000000000000000000000000000000000000000..6d445af83e29be91dda943ab10bffd4c0eba667e GIT binary patch literal 19760 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 V&y+ZSfsa5#k&{-EDv~fj{69Vi4~_r; literal 0 HcmV?d00001 diff --git a/frontend/projects/shared/src/public-api.ts b/frontend/projects/shared/src/public-api.ts index 1e16f11bb..f651bff44 100644 --- a/frontend/projects/shared/src/public-api.ts +++ b/frontend/projects/shared/src/public-api.ts @@ -46,6 +46,11 @@ export * from './services/emver.service' export * from './services/error-toast.service' export * from './services/http.service' +export * from './themes/dark-theme/dark-theme.component' +export * from './themes/dark-theme/dark-theme.module' +export * from './themes/light-theme/light-theme.component' +export * from './themes/light-theme/light-theme.module' + export * from './types/api' export * from './types/http.types' export * from './types/rpc.types' @@ -53,6 +58,7 @@ export * from './types/url' export * from './types/workspace-config' export * from './tokens/relative-url' +export * from './tokens/theme' export * from './util/base-64' export * from './util/copy-to-clipboard' diff --git a/frontend/projects/shared/src/themes/dark-theme/dark-theme.component.scss b/frontend/projects/shared/src/themes/dark-theme/dark-theme.component.scss new file mode 100644 index 000000000..48e6526df --- /dev/null +++ b/frontend/projects/shared/src/themes/dark-theme/dark-theme.component.scss @@ -0,0 +1 @@ +@import '../../../styles/variables'; diff --git a/frontend/projects/shared/src/themes/dark-theme/dark-theme.component.ts b/frontend/projects/shared/src/themes/dark-theme/dark-theme.component.ts new file mode 100644 index 000000000..2f80a5efb --- /dev/null +++ b/frontend/projects/shared/src/themes/dark-theme/dark-theme.component.ts @@ -0,0 +1,15 @@ +import { + ChangeDetectionStrategy, + Component, + ViewEncapsulation, +} from '@angular/core' +import { AbstractTuiThemeSwitcher } from '@taiga-ui/cdk' + +@Component({ + selector: 'dark-theme', + template: '', + styleUrls: ['./dark-theme.component.scss'], + encapsulation: ViewEncapsulation.None, + changeDetection: ChangeDetectionStrategy.OnPush, +}) +export class DarkThemeComponent extends AbstractTuiThemeSwitcher {} diff --git a/frontend/projects/shared/src/themes/dark-theme/dark-theme.module.ts b/frontend/projects/shared/src/themes/dark-theme/dark-theme.module.ts new file mode 100644 index 000000000..f383e201f --- /dev/null +++ b/frontend/projects/shared/src/themes/dark-theme/dark-theme.module.ts @@ -0,0 +1,9 @@ +import { NgModule } from '@angular/core' + +import { DarkThemeComponent } from './dark-theme.component' + +@NgModule({ + declarations: [DarkThemeComponent], + exports: [DarkThemeComponent], +}) +export class DarkThemeModule {} diff --git a/frontend/projects/shared/src/themes/light-theme/light-theme.component.scss b/frontend/projects/shared/src/themes/light-theme/light-theme.component.scss new file mode 100644 index 000000000..33be8c8a9 --- /dev/null +++ b/frontend/projects/shared/src/themes/light-theme/light-theme.component.scss @@ -0,0 +1,95 @@ +// Ionic Variables and Theming. For more info, please see: +// http://ionicframework.com/docs/theming/ + +/** Ionic CSS Variables **/ +:root { + --ion-color-primary: #0075e1; + --ion-color-primary-rgb: 66, 140, 255; + --ion-color-primary-contrast: #ffffff; + --ion-color-primary-contrast-rgb: 255, 255, 255; + --ion-color-primary-shade: #3a7be0; + --ion-color-primary-tint: #5598ff; + + --ion-color-secondary: #50c8ff; + --ion-color-secondary-rgb: 80, 200, 255; + --ion-color-secondary-contrast: #ffffff; + --ion-color-secondary-contrast-rgb: 255, 255, 255; + --ion-color-secondary-shade: #46b0e0; + --ion-color-secondary-tint: #62ceff; + + --ion-color-tertiary: #6a64ff; + --ion-color-tertiary-rgb: 106, 100, 255; + --ion-color-tertiary-contrast: #ffffff; + --ion-color-tertiary-contrast-rgb: 255, 255, 255; + --ion-color-tertiary-shade: #5d58e0; + --ion-color-tertiary-tint: #7974ff; + + --ion-color-success: #2fdf75; + --ion-color-success-rgb: 47, 223, 117; + --ion-color-success-contrast: #000000; + --ion-color-success-contrast-rgb: 0, 0, 0; + --ion-color-success-shade: #29c467; + --ion-color-success-tint: #44e283; + + --ion-color-warning: #ffb506; + --ion-color-warning-rgb: 255, 213, 52; + --ion-color-warning-contrast: #000000; + --ion-color-warning-contrast-rgb: 0, 0, 0; + --ion-color-warning-shade: #e0bb2e; + --ion-color-warning-tint: #ffd534; + + --ion-color-danger: #ff4961; + --ion-color-danger-rgb: 255, 73, 97; + --ion-color-danger-contrast: #ffffff; + --ion-color-danger-contrast-rgb: 255, 255, 255; + --ion-color-danger-shade: #e04055; + --ion-color-danger-tint: #ff5b71; + + //--ion-color-light: #f4f5f8; + //--ion-color-light-rgb: 244, 245, 248; + //--ion-color-light-contrast: #000000; + //--ion-color-light-contrast-rgb: 0, 0, 0; + //--ion-color-light-shade: #d7d8da; + //--ion-color-light-tint: #f5f6f9; + // + //--ion-color-medium: #f4f5f8; + //--ion-color-medium-rgb: 244, 245, 248; + //--ion-color-medium-contrast: #000000; + //--ion-color-medium-contrast-rgb: 0, 0, 0; + //--ion-color-medium-shade: #d7d8da; + //--ion-color-medium-tint: #f5f6f9; + // + //--ion-color-dark: #92949c; + //--ion-color-dark-rgb: 146, 148, 156; + //--ion-color-dark-contrast: #ffffff; + //--ion-color-dark-contrast-rgb: 255, 255, 255; + //--ion-color-dark-shade: #808289; + //--ion-color-dark-tint: #9d9fa6; + + --ion-color-step-50: #f2f2f2; + --ion-color-step-100: #e6e6e6; + --ion-color-step-150: #d9d9d9; + --ion-color-step-200: #cccccc; + --ion-color-step-250: #bfbfbf; + --ion-color-step-300: #b3b3b3; + --ion-color-step-350: #a6a6a6; + --ion-color-step-400: #999999; + --ion-color-step-450: #8c8c8c; + --ion-color-step-500: #808080; + --ion-color-step-550: #737373; + --ion-color-step-600: #666666; + --ion-color-step-650: #595959; + --ion-color-step-700: #4d4d4d; + --ion-color-step-750: #404040; + --ion-color-step-800: #333333; + --ion-color-step-850: #262626; + --ion-color-step-900: #191919; + --ion-color-step-950: #0d0d0d; + + --alt-red: #ff4961; + --alt-orange: #f89248; + --alt-yellow: #e5d53e; + --alt-green: #3dcf6f; + --alt-blue: #00a8a8; + --alt-purple: #9747ff; +} diff --git a/frontend/projects/shared/src/themes/light-theme/light-theme.component.ts b/frontend/projects/shared/src/themes/light-theme/light-theme.component.ts new file mode 100644 index 000000000..1c3d7d366 --- /dev/null +++ b/frontend/projects/shared/src/themes/light-theme/light-theme.component.ts @@ -0,0 +1,15 @@ +import { + ChangeDetectionStrategy, + Component, + ViewEncapsulation, +} from '@angular/core' +import { AbstractTuiThemeSwitcher } from '@taiga-ui/cdk' + +@Component({ + selector: 'light-theme', + template: '', + styleUrls: ['./light-theme.component.scss'], + encapsulation: ViewEncapsulation.None, + changeDetection: ChangeDetectionStrategy.OnPush, +}) +export class LightThemeComponent extends AbstractTuiThemeSwitcher {} diff --git a/frontend/projects/shared/src/themes/light-theme/light-theme.module.ts b/frontend/projects/shared/src/themes/light-theme/light-theme.module.ts new file mode 100644 index 000000000..a9f9554e9 --- /dev/null +++ b/frontend/projects/shared/src/themes/light-theme/light-theme.module.ts @@ -0,0 +1,9 @@ +import { NgModule } from '@angular/core' + +import { LightThemeComponent } from './light-theme.component' + +@NgModule({ + declarations: [LightThemeComponent], + exports: [LightThemeComponent], +}) +export class LightThemeModule {} diff --git a/frontend/projects/shared/src/tokens/theme.ts b/frontend/projects/shared/src/tokens/theme.ts new file mode 100644 index 000000000..dc6bbc2da --- /dev/null +++ b/frontend/projects/shared/src/tokens/theme.ts @@ -0,0 +1,6 @@ +import { InjectionToken } from '@angular/core' +import { EMPTY, Observable } from 'rxjs' + +export const THEME = new InjectionToken>('App theme', { + factory: () => EMPTY, +}) diff --git a/frontend/projects/shared/styles/variables.scss b/frontend/projects/shared/styles/variables.scss index fa70450e2..baff4ea61 100644 --- a/frontend/projects/shared/styles/variables.scss +++ b/frontend/projects/shared/styles/variables.scss @@ -48,7 +48,7 @@ --ion-color-light: #181818; --ion-color-light-rgb: 24, 24, 24; --ion-color-light-contrast: #ffffff; - --ion-color-light-contrast-rgb: 0, 0, 0; + --ion-color-light-contrast-rgb: 255, 255, 255; --ion-color-light-shade: #000000; --ion-color-light-tint: #000000; @@ -92,4 +92,4 @@ --alt-green: #3DCF6F; --alt-blue: #00A8A8; --alt-purple: #9747FF; -} \ No newline at end of file +} diff --git a/frontend/projects/ui/src/app/app.component.html b/frontend/projects/ui/src/app/app.component.html index c20b99c73..29c7e11a3 100644 --- a/frontend/projects/ui/src/app/app.component.html +++ b/frontend/projects/ui/src/app/app.component.html @@ -1,6 +1,6 @@ @@ -16,7 +16,7 @@ side="start" class="left-menu" > - + @@ -74,4 +74,13 @@ - + + + + + + + diff --git a/frontend/projects/ui/src/app/app.component.scss b/frontend/projects/ui/src/app/app.component.scss index b0e9367b1..55135b1e5 100644 --- a/frontend/projects/ui/src/app/app.component.scss +++ b/frontend/projects/ui/src/app/app.component.scss @@ -11,6 +11,12 @@ tui-root { --side-max-width: 280px; } +.menu { + :host-context(body[data-theme='Light']) & { + --ion-color-base: #F4F4F5 !important; + } +} + .container { transition: filter 0.3s; diff --git a/frontend/projects/ui/src/app/app.component.ts b/frontend/projects/ui/src/app/app.component.ts index d3e731e74..46a150b83 100644 --- a/frontend/projects/ui/src/app/app.component.ts +++ b/frontend/projects/ui/src/app/app.component.ts @@ -1,4 +1,4 @@ -import { Component, OnDestroy } from '@angular/core' +import { Component, inject, OnDestroy } from '@angular/core' import { merge } from 'rxjs' import { AuthService } from './services/auth.service' import { SplitPaneTracker } from './services/split-pane.service' @@ -11,6 +11,8 @@ import { ClientStorageService, WidgetDrawer, } from './services/client-storage.service' +import { ThemeSwitcherService } from './services/theme-switcher.service' +import { THEME } from '@start9labs/shared' @Component({ selector: 'app-root', @@ -21,6 +23,7 @@ export class AppComponent implements OnDestroy { readonly subscription = merge(this.patchData, this.patchMonitor).subscribe() readonly sidebarOpen$ = this.splitPane.sidebarOpen$ readonly widgetDrawer$ = this.clientStorageService.widgetDrawer$ + readonly theme$ = inject(THEME) constructor( private readonly titleService: Title, @@ -31,6 +34,7 @@ export class AppComponent implements OnDestroy { readonly authService: AuthService, readonly connection: ConnectionService, readonly clientStorageService: ClientStorageService, + readonly themeSwitcher: ThemeSwitcherService, ) {} ngOnInit() { diff --git a/frontend/projects/ui/src/app/app.module.ts b/frontend/projects/ui/src/app/app.module.ts index 23a0bd26a..2b3a5aae5 100644 --- a/frontend/projects/ui/src/app/app.module.ts +++ b/frontend/projects/ui/src/app/app.module.ts @@ -11,8 +11,10 @@ import { IonicModule } from '@ionic/angular' import { MonacoEditorModule } from '@materia-ui/ngx-monaco-editor' import { MarkdownModule, + DarkThemeModule, ResponsiveColModule, SharedPipesModule, + LightThemeModule, } from '@start9labs/shared' import { AppComponent } from './app.component' @@ -58,6 +60,8 @@ import { WidgetsPageModule } from './pages/widgets/widgets.module' TuiThemeNightModule, WidgetsPageModule, ResponsiveColModule, + DarkThemeModule, + LightThemeModule, ], providers: APP_PROVIDERS, bootstrap: [AppComponent], diff --git a/frontend/projects/ui/src/app/app.providers.ts b/frontend/projects/ui/src/app/app.providers.ts index d716dbb13..5d0ccc4f2 100644 --- a/frontend/projects/ui/src/app/app.providers.ts +++ b/frontend/projects/ui/src/app/app.providers.ts @@ -2,13 +2,14 @@ import { APP_INITIALIZER, Provider } from '@angular/core' import { UntypedFormBuilder } from '@angular/forms' import { Router, RouteReuseStrategy } from '@angular/router' import { IonicRouteStrategy, IonNav } from '@ionic/angular' -import { RELATIVE_URL, WorkspaceConfig } from '@start9labs/shared' +import { RELATIVE_URL, THEME, WorkspaceConfig } from '@start9labs/shared' import { ApiService } from './services/api/embassy-api.service' import { MockApiService } from './services/api/embassy-mock-api.service' import { LiveApiService } from './services/api/embassy-live-api.service' import { AuthService } from './services/auth.service' import { ClientStorageService } from './services/client-storage.service' import { FilterPackagesPipe } from '../../../marketplace/src/pipes/filter-packages.pipe' +import { ThemeSwitcherService } from './services/theme-switcher.service' const { useMocks, @@ -37,6 +38,10 @@ export const APP_PROVIDERS: Provider[] = [ provide: RELATIVE_URL, useValue: `/${api.url}/${api.version}`, }, + { + provide: THEME, + useExisting: ThemeSwitcherService, + }, ] export function appInitializer( diff --git a/frontend/projects/ui/src/app/app/menu/menu.component.html b/frontend/projects/ui/src/app/app/menu/menu.component.html index f84e96e2a..bd9a2ce2c 100644 --- a/frontend/projects/ui/src/app/app/menu/menu.component.html +++ b/frontend/projects/ui/src/app/app/menu/menu.component.html @@ -1,11 +1,17 @@ - , private readonly eosService: EOSService, diff --git a/frontend/projects/ui/src/app/app/preloader/preloader.component.ts b/frontend/projects/ui/src/app/app/preloader/preloader.component.ts index 604900062..d12f4743d 100644 --- a/frontend/projects/ui/src/app/app/preloader/preloader.component.ts +++ b/frontend/projects/ui/src/app/app/preloader/preloader.component.ts @@ -10,6 +10,7 @@ const ICONS = [ 'arrow-forward', 'arrow-up', 'briefcase-outline', + 'brush-outline', 'bookmark-outline', 'cellular-outline', 'chatbubbles-outline', diff --git a/frontend/projects/ui/src/app/components/connection-bar/connection-bar.component.html b/frontend/projects/ui/src/app/components/connection-bar/connection-bar.component.html index d6aba1358..3af0f2120 100644 --- a/frontend/projects/ui/src/app/components/connection-bar/connection-bar.component.html +++ b/frontend/projects/ui/src/app/components/connection-bar/connection-bar.component.html @@ -4,11 +4,7 @@ [color]="connection.color" >
- +

{{ connection.message }}

= combineLatest([ this.connectionService.networkConnected$, @@ -27,7 +26,6 @@ export class ConnectionBarComponent { message: 'No Internet', color: 'danger', icon: 'cloud-offline-outline', - iconColor: 'dark', dots: false, } if (!websocket) @@ -35,7 +33,6 @@ export class ConnectionBarComponent { message: 'Connecting', color: 'warning', icon: 'cloud-offline-outline', - iconColor: 'light', dots: true, } @@ -43,7 +40,6 @@ export class ConnectionBarComponent { message: 'Connected', color: 'success', icon: 'cloud-done', - iconColor: 'light', dots: false, } }), diff --git a/frontend/projects/ui/src/app/components/form-object/form-object.component.html b/frontend/projects/ui/src/app/components/form-object/form-object.component.html index 8cc2afadd..4332f112b 100644 --- a/frontend/projects/ui/src/app/components/form-object/form-object.component.html +++ b/frontend/projects/ui/src/app/components/form-object/form-object.component.html @@ -15,7 +15,7 @@ }" > - + - +

{{ options.label }}

- + @@ -9,7 +10,7 @@ -

{{ manifest.title }}

+

{{ manifest.title }}

{{ manifest.version | displayEmver }}

- - - - +
+

{{ pkg.manifest.version | displayEmver }}

- +
diff --git a/frontend/projects/ui/src/app/pages/apps-routes/app-show/components/app-show-header/app-show-header.component.scss b/frontend/projects/ui/src/app/pages/apps-routes/app-show/components/app-show-header/app-show-header.component.scss index ff3ff0ceb..2be7a3c4d 100644 --- a/frontend/projects/ui/src/app/pages/apps-routes/app-show/components/app-show-header/app-show-header.component.scss +++ b/frontend/projects/ui/src/app/pages/apps-routes/app-show/components/app-show-header/app-show-header.component.scss @@ -1,3 +1,13 @@ .less-large { font-size: 18px !important; -} \ No newline at end of file +} + +.header { + display: flex; +} + +.logo { + height: 54px; + width: 54px; + margin: 0 16px; +} diff --git a/frontend/projects/ui/src/app/pages/login/login.module.ts b/frontend/projects/ui/src/app/pages/login/login.module.ts index 3c815b035..937eb4885 100644 --- a/frontend/projects/ui/src/app/pages/login/login.module.ts +++ b/frontend/projects/ui/src/app/pages/login/login.module.ts @@ -18,8 +18,8 @@ const routes: Routes = [ CommonModule, FormsModule, IonicModule, - RouterModule.forChild(routes), SharedPipesModule, + RouterModule.forChild(routes), ], declarations: [LoginPage], }) diff --git a/frontend/projects/ui/src/app/pages/login/login.page.html b/frontend/projects/ui/src/app/pages/login/login.page.html index d9f55f4d2..651094664 100644 --- a/frontend/projects/ui/src/app/pages/login/login.page.html +++ b/frontend/projects/ui/src/app/pages/login/login.page.html @@ -1,41 +1,35 @@ - - - - -
- -
+ + + + + - - - Embassy Login + + + Embassy Login - -
+ + - + - + @@ -46,12 +40,12 @@ expand="block" color="tertiary" > - Login + Login -

- {{ error }} -

+

+ {{ error }} +

diff --git a/frontend/projects/ui/src/app/pages/login/login.page.scss b/frontend/projects/ui/src/app/pages/login/login.page.scss index fdc001e12..02c13e12f 100644 --- a/frontend/projects/ui/src/app/pages/login/login.page.scss +++ b/frontend/projects/ui/src/app/pages/login/login.page.scss @@ -1,10 +1,37 @@ -ion-card-title { - margin: 24px 0; - font-family: 'Montserrat'; - font-weight: 500; - font-size: x-large; - font-variant: all-small-caps; - --color: var(--ion-color-dark); +.content { + --background: #222428; +} + +.card { + background: #414141; +} + +.title { + margin: 24px 0 16px; + color: #e0e0e0; + text-transform: uppercase; +} + +.grid { + height: 100%; + max-width: 540px; +} + +.row { + height: 90%; + align-items: center; + text-align: center; +} + +.logo { + max-width: 240px; + padding-bottom: 16px; +} + +.error { + display: block; + text-align: left; + padding-top: 4px; } ion-button { @@ -15,8 +42,7 @@ ion-item { --border-style: solid; --border-color: var(--ion-color-light); --border-radius: 4px 0 0 4px; - box-shadow: 0 3px 1px -2px rgba(0, 0, 0, 0.2), - 0 2px 2px 0 rgba(0, 0, 0, 0.14), + box-shadow: 0 3px 1px -2px rgba(0, 0, 0, 0.2), 0 2px 2px 0 rgba(0, 0, 0, 0.14), 0 1px 5px 0 rgba(0, 0, 0, 0.12); ion-button { @@ -26,26 +52,22 @@ ion-item { ion-card { background: var(--ion-color-step-200); - box-shadow: 0px 4px 4px rgba(0, 0, 0, 0.25); + box-shadow: 0 4px 4px rgba(0, 0, 0, 0.25); border-radius: 44px; min-height: 16rem; } -.input-label { - text-align: left; - padding-bottom: 2px; - font-size: small; - font-weight: bold; - color: var(--ion-color-dark); -} - .login-button { margin-inline-start: 0; margin-inline-end: 0; height: 49px; + font-size: larger; + font-weight: bold; } -.inline { +.form { + margin-bottom: 12px; + * { display: inline-block; vertical-align: middle; @@ -53,5 +75,5 @@ ion-card { } .item-interactive { - --highlight-background: var(--ion-color-tertiary) !important; -} \ No newline at end of file + --highlight-background: #5260ff !important; +} diff --git a/frontend/projects/ui/src/app/pages/server-routes/server-show/server-show.module.ts b/frontend/projects/ui/src/app/pages/server-routes/server-show/server-show.module.ts index 15fa48397..137a13430 100644 --- a/frontend/projects/ui/src/app/pages/server-routes/server-show/server-show.module.ts +++ b/frontend/projects/ui/src/app/pages/server-routes/server-show/server-show.module.ts @@ -8,6 +8,7 @@ import { TextSpinnerComponentModule } from '@start9labs/shared' import { BadgeMenuComponentModule } from 'src/app/components/badge-menu-button/badge-menu.component.module' import { OSUpdatePageModule } from 'src/app/modals/os-update/os-update.page.module' import { BackupColorPipeModule } from 'src/app/pipes/backup-color/backup-color.module' +import { ThemeSwitcherModule } from '../theme-switcher/theme-switcher.module' const routes: Routes = [ { @@ -26,6 +27,7 @@ const routes: Routes = [ BadgeMenuComponentModule, OSUpdatePageModule, BackupColorPipeModule, + ThemeSwitcherModule, ], declarations: [ServerShowPage], }) diff --git a/frontend/projects/ui/src/app/pages/server-routes/server-show/server-show.page.html b/frontend/projects/ui/src/app/pages/server-routes/server-show/server-show.page.html index eebfd2c17..6698f5ce2 100644 --- a/frontend/projects/ui/src/app/pages/server-routes/server-show/server-show.page.html +++ b/frontend/projects/ui/src/app/pages/server-routes/server-show/server-show.page.html @@ -38,65 +38,65 @@ {{ cat.key }} - - - - -

{{ button.title }}

-

{{ button.description }}

+ + + + +

{{ button.title }}

+

{{ button.description }}

- -

- - - Last Backup: {{ server['last-backup'] ? (server['last-backup'] - | date: 'medium') : 'never' }} - - - - Backing up - - -

- -

+ +

+ - Update Complete. Restart to apply changes + Last Backup: {{ server['last-backup'] ? (server['last-backup'] | + date: 'medium') : 'never' }} - - - - - Update Available - - - - - - Check for updates - - + + + Backing up + + +

+ +

+ + Update Complete. Restart to apply changes + + + + + + Update Available + + + + + + Check for updates + -

-
-
-
+ +

+
+
diff --git a/frontend/projects/ui/src/app/pages/server-routes/sideload/sideload.page.html b/frontend/projects/ui/src/app/pages/server-routes/sideload/sideload.page.html index b12ab3e5b..0778b3ae7 100644 --- a/frontend/projects/ui/src/app/pages/server-routes/sideload/sideload.page.html +++ b/frontend/projects/ui/src/app/pages/server-routes/sideload/sideload.page.html @@ -56,7 +56,7 @@ {{ uploadState?.message }}
-
+
+ + +

Theme

+

{{ value }}

+
+ + + + + diff --git a/frontend/projects/ui/src/app/pages/server-routes/theme-switcher/theme-switcher.component.ts b/frontend/projects/ui/src/app/pages/server-routes/theme-switcher/theme-switcher.component.ts new file mode 100644 index 000000000..0af1672fd --- /dev/null +++ b/frontend/projects/ui/src/app/pages/server-routes/theme-switcher/theme-switcher.component.ts @@ -0,0 +1,23 @@ +import { ChangeDetectionStrategy, Component } from '@angular/core' + +import { ThemeSwitcherService } from '../../../services/theme-switcher.service' + +@Component({ + selector: 'theme-switcher', + templateUrl: './theme-switcher.component.html', + changeDetection: ChangeDetectionStrategy.OnPush, +}) +export class ThemeSwitcherComponent { + value = this.switcher.value + + open = false + + readonly themes = ['Dark', 'Light'] + + constructor(private readonly switcher: ThemeSwitcherService) {} + + onChange(value: string): void { + this.value = value + this.switcher.next(value) + } +} diff --git a/frontend/projects/ui/src/app/pages/server-routes/theme-switcher/theme-switcher.module.ts b/frontend/projects/ui/src/app/pages/server-routes/theme-switcher/theme-switcher.module.ts new file mode 100644 index 000000000..4d817e933 --- /dev/null +++ b/frontend/projects/ui/src/app/pages/server-routes/theme-switcher/theme-switcher.module.ts @@ -0,0 +1,14 @@ +import { NgModule } from '@angular/core' +import { FormsModule } from '@angular/forms' +import { IonicModule } from '@ionic/angular' +import { TuiDialogModule } from '@taiga-ui/core' +import { TuiRadioListModule } from '@taiga-ui/kit' + +import { ThemeSwitcherComponent } from './theme-switcher.component' + +@NgModule({ + imports: [IonicModule, FormsModule, TuiDialogModule, TuiRadioListModule], + declarations: [ThemeSwitcherComponent], + exports: [ThemeSwitcherComponent], +}) +export class ThemeSwitcherModule {} diff --git a/frontend/projects/ui/src/app/pages/widgets/widgets.page.scss b/frontend/projects/ui/src/app/pages/widgets/widgets.page.scss index e2f672237..cf27b504b 100644 --- a/frontend/projects/ui/src/app/pages/widgets/widgets.page.scss +++ b/frontend/projects/ui/src/app/pages/widgets/widgets.page.scss @@ -57,7 +57,7 @@ .content { height: 100%; text-align: center; - background: #333; + background: var(--tui-base-02); border-radius: 24px; padding: 24px; box-sizing: border-box; diff --git a/frontend/projects/ui/src/app/services/api/mock-patch.ts b/frontend/projects/ui/src/app/services/api/mock-patch.ts index f70dc2008..ace194349 100644 --- a/frontend/projects/ui/src/app/services/api/mock-patch.ts +++ b/frontend/projects/ui/src/app/services/api/mock-patch.ts @@ -14,6 +14,7 @@ export const mockPatchData: DataModel = { ui: { name: `Matt's Embassy`, 'ack-welcome': '1.0.0', + theme: 'Dark', widgets: BUILT_IN_WIDGETS.filter( ({ id }) => id === 'favorites' || diff --git a/frontend/projects/ui/src/app/services/patch-db/data-model.ts b/frontend/projects/ui/src/app/services/patch-db/data-model.ts index 25e1677ba..6f87edfb4 100644 --- a/frontend/projects/ui/src/app/services/patch-db/data-model.ts +++ b/frontend/projects/ui/src/app/services/patch-db/data-model.ts @@ -20,6 +20,7 @@ export interface UIData { } } 'ack-instructions': Record + theme: string widgets: readonly Widget[] } diff --git a/frontend/projects/ui/src/app/services/theme-switcher.service.ts b/frontend/projects/ui/src/app/services/theme-switcher.service.ts new file mode 100644 index 000000000..9c93283ab --- /dev/null +++ b/frontend/projects/ui/src/app/services/theme-switcher.service.ts @@ -0,0 +1,33 @@ +import { Inject, Injectable } from '@angular/core' +import { WINDOW } from '@ng-web-apis/common' +import { PatchDB } from 'patch-db-client' +import { BehaviorSubject } from 'rxjs' +import { ApiService } from './api/embassy-api.service' +import { DataModel } from './patch-db/data-model' +import { filter, take } from 'rxjs/operators' + +@Injectable({ + providedIn: 'root', +}) +export class ThemeSwitcherService extends BehaviorSubject { + constructor( + private readonly patch: PatchDB, + private readonly embassyApi: ApiService, + @Inject(WINDOW) private readonly windowRef: Window, + ) { + super('Dark') + + this.patch + .watch$('ui', 'theme') + .pipe(take(1), filter(Boolean)) + .subscribe(theme => { + this.next(theme) + }) + } + + override next(currentTheme: string): void { + this.embassyApi.setDbValue(['theme'], currentTheme) + this.windowRef.document.body.setAttribute('data-theme', currentTheme) + super.next(currentTheme) + } +} diff --git a/frontend/projects/ui/src/styles.scss b/frontend/projects/ui/src/styles.scss index fe4beccf7..280467a06 100644 --- a/frontend/projects/ui/src/styles.scss +++ b/frontend/projects/ui/src/styles.scss @@ -306,7 +306,22 @@ ion-footer.with-widgets { width: calc(100% - var(--widgets-width)); } +body[data-theme='Light'] { + .service-card { + --background: #f4f4f5; + --inner-border-width: 0; + } + + ion-header { + box-shadow: 0 1px #e0e0e0; + + &::after { + display: none; + } + } +} + ul { padding-left: 40px; list-style-type: disc; -} \ No newline at end of file +}