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 000000000..6d445af83 Binary files /dev/null and b/frontend/projects/shared/assets/img/logo_dark.png differ 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 +}