diff --git a/package-lock.json b/package-lock.json
index a24d5e6..3c7f16c 100644
--- a/package-lock.json
+++ b/package-lock.json
@@ -1,12 +1,12 @@
{
"name": "twirch",
- "version": "0.0.1",
+ "version": "0.3.0",
"lockfileVersion": 2,
"requires": true,
"packages": {
"": {
"name": "twirch",
- "version": "0.0.1",
+ "version": "0.3.0",
"license": "MIT",
"dependencies": {
"cors": "^2.8.5",
diff --git a/package.json b/package.json
index 28d6a06..6de88c9 100644
--- a/package.json
+++ b/package.json
@@ -1,6 +1,6 @@
{
"name": "twirch",
- "version": "0.0.1",
+ "version": "0.3.0",
"description": "App for viewing multiple Twitch chats in a single feed",
"author": "Michael McBride",
"license": "MIT",
diff --git a/server.js b/server.js
index 055554b..bb97b09 100644
--- a/server.js
+++ b/server.js
@@ -18,7 +18,8 @@ const io = new Server(httpServer, {
cors: {
origin: [
'https://twirch.io',
- 'http://localhost:3080'
+ 'http://localhost:3080',
+ 'http://localhost:4200'
],
preflightContinue: true
}
diff --git a/twirch/package-lock.json b/twirch/package-lock.json
index b7d263e..749863c 100644
--- a/twirch/package-lock.json
+++ b/twirch/package-lock.json
@@ -1,18 +1,20 @@
{
"name": "twirch",
- "version": "0.0.0",
+ "version": "0.3.0",
"lockfileVersion": 3,
"requires": true,
"packages": {
"": {
"name": "twirch",
- "version": "0.0.0",
+ "version": "0.3.0",
"dependencies": {
"@angular/animations": "^15.2.0",
+ "@angular/cdk": "^15.2.6",
"@angular/common": "^15.2.0",
"@angular/compiler": "^15.2.0",
"@angular/core": "^15.2.0",
"@angular/forms": "^15.2.0",
+ "@angular/material": "^15.2.6",
"@angular/platform-browser": "^15.2.0",
"@angular/platform-browser-dynamic": "^15.2.0",
"@angular/router": "^15.2.0",
@@ -343,6 +345,46 @@
"@angular/core": "15.2.2"
}
},
+ "node_modules/@angular/cdk": {
+ "version": "15.2.6",
+ "resolved": "https://registry.npmjs.org/@angular/cdk/-/cdk-15.2.6.tgz",
+ "integrity": "sha512-c6XFKMFowllHxb4tUt9en3bXBDqXKG2k4O9XGggJ1TL668d3Uhlk9qULywFNVWmNQSamkERmhFKAN4hEO3TPAQ==",
+ "dependencies": {
+ "tslib": "^2.3.0"
+ },
+ "optionalDependencies": {
+ "parse5": "^7.1.2"
+ },
+ "peerDependencies": {
+ "@angular/common": "^15.0.0 || ^16.0.0",
+ "@angular/core": "^15.0.0 || ^16.0.0",
+ "rxjs": "^6.5.3 || ^7.4.0"
+ }
+ },
+ "node_modules/@angular/cdk/node_modules/entities": {
+ "version": "4.4.0",
+ "resolved": "https://registry.npmjs.org/entities/-/entities-4.4.0.tgz",
+ "integrity": "sha512-oYp7156SP8LkeGD0GF85ad1X9Ai79WtRsZ2gxJqtBuzH+98YUV6jkHEKlZkMbcrjJjIVJNIDP/3WL9wQkoPbWA==",
+ "optional": true,
+ "engines": {
+ "node": ">=0.12"
+ },
+ "funding": {
+ "url": "https://github.com/fb55/entities?sponsor=1"
+ }
+ },
+ "node_modules/@angular/cdk/node_modules/parse5": {
+ "version": "7.1.2",
+ "resolved": "https://registry.npmjs.org/parse5/-/parse5-7.1.2.tgz",
+ "integrity": "sha512-Czj1WaSVpaoj0wbhMzLmWD69anp2WH7FXMB9n1Sy8/ZFF9jolSQVMu1Ij5WIyGmcBmhk7EOndpO4mIpihVqAXw==",
+ "optional": true,
+ "dependencies": {
+ "entities": "^4.4.0"
+ },
+ "funding": {
+ "url": "https://github.com/inikulin/parse5?sponsor=1"
+ }
+ },
"node_modules/@angular/cli": {
"version": "15.2.4",
"resolved": "https://registry.npmjs.org/@angular/cli/-/cli-15.2.4.tgz",
@@ -524,6 +566,70 @@
"rxjs": "^6.5.3 || ^7.4.0"
}
},
+ "node_modules/@angular/material": {
+ "version": "15.2.6",
+ "resolved": "https://registry.npmjs.org/@angular/material/-/material-15.2.6.tgz",
+ "integrity": "sha512-r5feEcgs+xufI+GaO01XCehpnJVNB8sMS4l8DRV72DzgEIXhqYoLSWnQy7gYOKRXCUT66r1BxDmPG5fGa7jNzg==",
+ "dependencies": {
+ "@material/animation": "15.0.0-canary.684e33d25.0",
+ "@material/auto-init": "15.0.0-canary.684e33d25.0",
+ "@material/banner": "15.0.0-canary.684e33d25.0",
+ "@material/base": "15.0.0-canary.684e33d25.0",
+ "@material/button": "15.0.0-canary.684e33d25.0",
+ "@material/card": "15.0.0-canary.684e33d25.0",
+ "@material/checkbox": "15.0.0-canary.684e33d25.0",
+ "@material/chips": "15.0.0-canary.684e33d25.0",
+ "@material/circular-progress": "15.0.0-canary.684e33d25.0",
+ "@material/data-table": "15.0.0-canary.684e33d25.0",
+ "@material/density": "15.0.0-canary.684e33d25.0",
+ "@material/dialog": "15.0.0-canary.684e33d25.0",
+ "@material/dom": "15.0.0-canary.684e33d25.0",
+ "@material/drawer": "15.0.0-canary.684e33d25.0",
+ "@material/elevation": "15.0.0-canary.684e33d25.0",
+ "@material/fab": "15.0.0-canary.684e33d25.0",
+ "@material/feature-targeting": "15.0.0-canary.684e33d25.0",
+ "@material/floating-label": "15.0.0-canary.684e33d25.0",
+ "@material/form-field": "15.0.0-canary.684e33d25.0",
+ "@material/icon-button": "15.0.0-canary.684e33d25.0",
+ "@material/image-list": "15.0.0-canary.684e33d25.0",
+ "@material/layout-grid": "15.0.0-canary.684e33d25.0",
+ "@material/line-ripple": "15.0.0-canary.684e33d25.0",
+ "@material/linear-progress": "15.0.0-canary.684e33d25.0",
+ "@material/list": "15.0.0-canary.684e33d25.0",
+ "@material/menu": "15.0.0-canary.684e33d25.0",
+ "@material/menu-surface": "15.0.0-canary.684e33d25.0",
+ "@material/notched-outline": "15.0.0-canary.684e33d25.0",
+ "@material/radio": "15.0.0-canary.684e33d25.0",
+ "@material/ripple": "15.0.0-canary.684e33d25.0",
+ "@material/rtl": "15.0.0-canary.684e33d25.0",
+ "@material/segmented-button": "15.0.0-canary.684e33d25.0",
+ "@material/select": "15.0.0-canary.684e33d25.0",
+ "@material/shape": "15.0.0-canary.684e33d25.0",
+ "@material/slider": "15.0.0-canary.684e33d25.0",
+ "@material/snackbar": "15.0.0-canary.684e33d25.0",
+ "@material/switch": "15.0.0-canary.684e33d25.0",
+ "@material/tab": "15.0.0-canary.684e33d25.0",
+ "@material/tab-bar": "15.0.0-canary.684e33d25.0",
+ "@material/tab-indicator": "15.0.0-canary.684e33d25.0",
+ "@material/tab-scroller": "15.0.0-canary.684e33d25.0",
+ "@material/textfield": "15.0.0-canary.684e33d25.0",
+ "@material/theme": "15.0.0-canary.684e33d25.0",
+ "@material/tooltip": "15.0.0-canary.684e33d25.0",
+ "@material/top-app-bar": "15.0.0-canary.684e33d25.0",
+ "@material/touch-target": "15.0.0-canary.684e33d25.0",
+ "@material/typography": "15.0.0-canary.684e33d25.0",
+ "tslib": "^2.3.0"
+ },
+ "peerDependencies": {
+ "@angular/animations": "^15.0.0 || ^16.0.0",
+ "@angular/cdk": "15.2.6",
+ "@angular/common": "^15.0.0 || ^16.0.0",
+ "@angular/core": "^15.0.0 || ^16.0.0",
+ "@angular/forms": "^15.0.0 || ^16.0.0",
+ "@angular/platform-browser": "^15.0.0 || ^16.0.0",
+ "rxjs": "^6.5.3 || ^7.4.0"
+ }
+ },
"node_modules/@angular/platform-browser": {
"version": "15.2.2",
"resolved": "https://registry.npmjs.org/@angular/platform-browser/-/platform-browser-15.2.2.tgz",
@@ -2750,6 +2856,757 @@
"integrity": "sha512-Hcv+nVC0kZnQ3tD9GVu5xSMR4VVYOteQIr/hwFPVEvPdlXqgGEuRjiheChHgdM+JyqdgNcmzZOX/tnl0JOiI7A==",
"dev": true
},
+ "node_modules/@material/animation": {
+ "version": "15.0.0-canary.684e33d25.0",
+ "resolved": "https://registry.npmjs.org/@material/animation/-/animation-15.0.0-canary.684e33d25.0.tgz",
+ "integrity": "sha512-5osi1z4JQIXcklPALbH/zTfOm2pDzHt9Fxm7ZyURy250xIZj6QjULRzPTnzOhC2ropfix9ra2Cfggbf0dcRbEQ==",
+ "dependencies": {
+ "tslib": "^2.1.0"
+ }
+ },
+ "node_modules/@material/auto-init": {
+ "version": "15.0.0-canary.684e33d25.0",
+ "resolved": "https://registry.npmjs.org/@material/auto-init/-/auto-init-15.0.0-canary.684e33d25.0.tgz",
+ "integrity": "sha512-OigQTmrVzkcGvxNjOaIe5oItTFPgrO9xLewvharDI6m6yvO1z7OBnkcW+sFN6ggLNYNxd0O1u9v64vMsmeDABQ==",
+ "dependencies": {
+ "@material/base": "15.0.0-canary.684e33d25.0",
+ "tslib": "^2.1.0"
+ }
+ },
+ "node_modules/@material/banner": {
+ "version": "15.0.0-canary.684e33d25.0",
+ "resolved": "https://registry.npmjs.org/@material/banner/-/banner-15.0.0-canary.684e33d25.0.tgz",
+ "integrity": "sha512-PqtGp3KWzdu58rWv/DIvSfe38m5YKOBbAAbBinSvgadBb/da+IE1t5F7YPNKE1T5lJsQBGVUYx6QBIeXm+aI/A==",
+ "dependencies": {
+ "@material/base": "15.0.0-canary.684e33d25.0",
+ "@material/button": "15.0.0-canary.684e33d25.0",
+ "@material/dom": "15.0.0-canary.684e33d25.0",
+ "@material/elevation": "15.0.0-canary.684e33d25.0",
+ "@material/feature-targeting": "15.0.0-canary.684e33d25.0",
+ "@material/ripple": "15.0.0-canary.684e33d25.0",
+ "@material/rtl": "15.0.0-canary.684e33d25.0",
+ "@material/shape": "15.0.0-canary.684e33d25.0",
+ "@material/theme": "15.0.0-canary.684e33d25.0",
+ "@material/tokens": "15.0.0-canary.684e33d25.0",
+ "@material/typography": "15.0.0-canary.684e33d25.0",
+ "tslib": "^2.1.0"
+ }
+ },
+ "node_modules/@material/base": {
+ "version": "15.0.0-canary.684e33d25.0",
+ "resolved": "https://registry.npmjs.org/@material/base/-/base-15.0.0-canary.684e33d25.0.tgz",
+ "integrity": "sha512-oOaqb/SfjWwTKsdJUZmeh/Qrs41nIJI0N+zELsxnvbGjSIN1ZMAKYZFPMahqvC68OJ6+5CvJM8PoTNs5l+B8IQ==",
+ "dependencies": {
+ "tslib": "^2.1.0"
+ }
+ },
+ "node_modules/@material/button": {
+ "version": "15.0.0-canary.684e33d25.0",
+ "resolved": "https://registry.npmjs.org/@material/button/-/button-15.0.0-canary.684e33d25.0.tgz",
+ "integrity": "sha512-Nkekk4edeX+ObVOa7UlwavaHdmckPV5wU4SAJf3iA3R61cmz+KsgAgpzfcwv5WfNhIlc2nLu8QYEecpHdo9d/w==",
+ "dependencies": {
+ "@material/density": "15.0.0-canary.684e33d25.0",
+ "@material/dom": "15.0.0-canary.684e33d25.0",
+ "@material/elevation": "15.0.0-canary.684e33d25.0",
+ "@material/feature-targeting": "15.0.0-canary.684e33d25.0",
+ "@material/focus-ring": "15.0.0-canary.684e33d25.0",
+ "@material/ripple": "15.0.0-canary.684e33d25.0",
+ "@material/rtl": "15.0.0-canary.684e33d25.0",
+ "@material/shape": "15.0.0-canary.684e33d25.0",
+ "@material/theme": "15.0.0-canary.684e33d25.0",
+ "@material/tokens": "15.0.0-canary.684e33d25.0",
+ "@material/touch-target": "15.0.0-canary.684e33d25.0",
+ "@material/typography": "15.0.0-canary.684e33d25.0",
+ "tslib": "^2.1.0"
+ }
+ },
+ "node_modules/@material/card": {
+ "version": "15.0.0-canary.684e33d25.0",
+ "resolved": "https://registry.npmjs.org/@material/card/-/card-15.0.0-canary.684e33d25.0.tgz",
+ "integrity": "sha512-xhyB7XX5KkEiCEqwSPkl58ZGYL6xFdnY62zimyBXJRG/Eaa0Swj3kW20hVCpt4f7c9Zmp8Se27rg8vnKmhvO3g==",
+ "dependencies": {
+ "@material/dom": "15.0.0-canary.684e33d25.0",
+ "@material/elevation": "15.0.0-canary.684e33d25.0",
+ "@material/feature-targeting": "15.0.0-canary.684e33d25.0",
+ "@material/ripple": "15.0.0-canary.684e33d25.0",
+ "@material/rtl": "15.0.0-canary.684e33d25.0",
+ "@material/shape": "15.0.0-canary.684e33d25.0",
+ "@material/theme": "15.0.0-canary.684e33d25.0",
+ "@material/tokens": "15.0.0-canary.684e33d25.0",
+ "tslib": "^2.1.0"
+ }
+ },
+ "node_modules/@material/checkbox": {
+ "version": "15.0.0-canary.684e33d25.0",
+ "resolved": "https://registry.npmjs.org/@material/checkbox/-/checkbox-15.0.0-canary.684e33d25.0.tgz",
+ "integrity": "sha512-NFpM3TS924PmVsk2KQLNU95OYCf8ZwYgzeqfnAexU0bEfjUJXINBun2Go0AaeOUMjuvWUe+byjrXgv8SFYbMUA==",
+ "dependencies": {
+ "@material/animation": "15.0.0-canary.684e33d25.0",
+ "@material/base": "15.0.0-canary.684e33d25.0",
+ "@material/density": "15.0.0-canary.684e33d25.0",
+ "@material/dom": "15.0.0-canary.684e33d25.0",
+ "@material/feature-targeting": "15.0.0-canary.684e33d25.0",
+ "@material/focus-ring": "15.0.0-canary.684e33d25.0",
+ "@material/ripple": "15.0.0-canary.684e33d25.0",
+ "@material/theme": "15.0.0-canary.684e33d25.0",
+ "@material/touch-target": "15.0.0-canary.684e33d25.0",
+ "tslib": "^2.1.0"
+ }
+ },
+ "node_modules/@material/chips": {
+ "version": "15.0.0-canary.684e33d25.0",
+ "resolved": "https://registry.npmjs.org/@material/chips/-/chips-15.0.0-canary.684e33d25.0.tgz",
+ "integrity": "sha512-z4ajQ4NnsAQ/Si9tZ4xmxzjj2Qb+vW++4QjCjjjwAGIZbCe0xglAnMh2t66XLJUxt7RoKZuZVEO7ZqcFZpvJFQ==",
+ "dependencies": {
+ "@material/animation": "15.0.0-canary.684e33d25.0",
+ "@material/base": "15.0.0-canary.684e33d25.0",
+ "@material/checkbox": "15.0.0-canary.684e33d25.0",
+ "@material/density": "15.0.0-canary.684e33d25.0",
+ "@material/dom": "15.0.0-canary.684e33d25.0",
+ "@material/elevation": "15.0.0-canary.684e33d25.0",
+ "@material/feature-targeting": "15.0.0-canary.684e33d25.0",
+ "@material/focus-ring": "15.0.0-canary.684e33d25.0",
+ "@material/ripple": "15.0.0-canary.684e33d25.0",
+ "@material/rtl": "15.0.0-canary.684e33d25.0",
+ "@material/shape": "15.0.0-canary.684e33d25.0",
+ "@material/theme": "15.0.0-canary.684e33d25.0",
+ "@material/tokens": "15.0.0-canary.684e33d25.0",
+ "@material/touch-target": "15.0.0-canary.684e33d25.0",
+ "@material/typography": "15.0.0-canary.684e33d25.0",
+ "safevalues": "^0.3.4",
+ "tslib": "^2.1.0"
+ }
+ },
+ "node_modules/@material/circular-progress": {
+ "version": "15.0.0-canary.684e33d25.0",
+ "resolved": "https://registry.npmjs.org/@material/circular-progress/-/circular-progress-15.0.0-canary.684e33d25.0.tgz",
+ "integrity": "sha512-G6qD0nGNtEUwWnAMJuA9INYFpZoKtx7KFjBaPF4Ol2YLHtmShALNAYyn54TMAK8AZ2IpW08PXjGS7Ye88vrdEQ==",
+ "dependencies": {
+ "@material/animation": "15.0.0-canary.684e33d25.0",
+ "@material/base": "15.0.0-canary.684e33d25.0",
+ "@material/dom": "15.0.0-canary.684e33d25.0",
+ "@material/feature-targeting": "15.0.0-canary.684e33d25.0",
+ "@material/progress-indicator": "15.0.0-canary.684e33d25.0",
+ "@material/rtl": "15.0.0-canary.684e33d25.0",
+ "@material/theme": "15.0.0-canary.684e33d25.0",
+ "tslib": "^2.1.0"
+ }
+ },
+ "node_modules/@material/data-table": {
+ "version": "15.0.0-canary.684e33d25.0",
+ "resolved": "https://registry.npmjs.org/@material/data-table/-/data-table-15.0.0-canary.684e33d25.0.tgz",
+ "integrity": "sha512-+wDw1DDDFfAsKAMzs84f/5GCjux39zjNfW8tL4wFbkWNwewmQrG9zaQMJhBpVOtLCrM8Gj6SOgOANqgqoCjvGg==",
+ "dependencies": {
+ "@material/animation": "15.0.0-canary.684e33d25.0",
+ "@material/base": "15.0.0-canary.684e33d25.0",
+ "@material/checkbox": "15.0.0-canary.684e33d25.0",
+ "@material/density": "15.0.0-canary.684e33d25.0",
+ "@material/dom": "15.0.0-canary.684e33d25.0",
+ "@material/elevation": "15.0.0-canary.684e33d25.0",
+ "@material/feature-targeting": "15.0.0-canary.684e33d25.0",
+ "@material/icon-button": "15.0.0-canary.684e33d25.0",
+ "@material/linear-progress": "15.0.0-canary.684e33d25.0",
+ "@material/list": "15.0.0-canary.684e33d25.0",
+ "@material/menu": "15.0.0-canary.684e33d25.0",
+ "@material/rtl": "15.0.0-canary.684e33d25.0",
+ "@material/select": "15.0.0-canary.684e33d25.0",
+ "@material/shape": "15.0.0-canary.684e33d25.0",
+ "@material/theme": "15.0.0-canary.684e33d25.0",
+ "@material/tokens": "15.0.0-canary.684e33d25.0",
+ "@material/touch-target": "15.0.0-canary.684e33d25.0",
+ "@material/typography": "15.0.0-canary.684e33d25.0",
+ "tslib": "^2.1.0"
+ }
+ },
+ "node_modules/@material/density": {
+ "version": "15.0.0-canary.684e33d25.0",
+ "resolved": "https://registry.npmjs.org/@material/density/-/density-15.0.0-canary.684e33d25.0.tgz",
+ "integrity": "sha512-661yEVRMGrlq6S6WuSbPRO+ZwpdUOg2glCc7y96doM6itSLOa3UEAldjOLfsYZVB74GnKCiuDp//QmfoRyYTfA==",
+ "dependencies": {
+ "tslib": "^2.1.0"
+ }
+ },
+ "node_modules/@material/dialog": {
+ "version": "15.0.0-canary.684e33d25.0",
+ "resolved": "https://registry.npmjs.org/@material/dialog/-/dialog-15.0.0-canary.684e33d25.0.tgz",
+ "integrity": "sha512-szn0dHnfeQTSOC6SSRSGAzX6Tnx+4NnSMUwNkXm+3bwjds8ZVK26+DXwLrP5f3ID5F1K5sFsRf2INo5/TNTHyQ==",
+ "dependencies": {
+ "@material/animation": "15.0.0-canary.684e33d25.0",
+ "@material/base": "15.0.0-canary.684e33d25.0",
+ "@material/button": "15.0.0-canary.684e33d25.0",
+ "@material/dom": "15.0.0-canary.684e33d25.0",
+ "@material/elevation": "15.0.0-canary.684e33d25.0",
+ "@material/feature-targeting": "15.0.0-canary.684e33d25.0",
+ "@material/icon-button": "15.0.0-canary.684e33d25.0",
+ "@material/ripple": "15.0.0-canary.684e33d25.0",
+ "@material/rtl": "15.0.0-canary.684e33d25.0",
+ "@material/shape": "15.0.0-canary.684e33d25.0",
+ "@material/theme": "15.0.0-canary.684e33d25.0",
+ "@material/tokens": "15.0.0-canary.684e33d25.0",
+ "@material/touch-target": "15.0.0-canary.684e33d25.0",
+ "@material/typography": "15.0.0-canary.684e33d25.0",
+ "tslib": "^2.1.0"
+ }
+ },
+ "node_modules/@material/dom": {
+ "version": "15.0.0-canary.684e33d25.0",
+ "resolved": "https://registry.npmjs.org/@material/dom/-/dom-15.0.0-canary.684e33d25.0.tgz",
+ "integrity": "sha512-7pEJLYov+tGgfuD8mZxoVU6rWtPI8ppjTAhz+F27Hz9FG0JETMWTKpDPBXLnKvX7vhIxL83GvZ9geNHCe8Hfog==",
+ "dependencies": {
+ "@material/feature-targeting": "15.0.0-canary.684e33d25.0",
+ "@material/rtl": "15.0.0-canary.684e33d25.0",
+ "tslib": "^2.1.0"
+ }
+ },
+ "node_modules/@material/drawer": {
+ "version": "15.0.0-canary.684e33d25.0",
+ "resolved": "https://registry.npmjs.org/@material/drawer/-/drawer-15.0.0-canary.684e33d25.0.tgz",
+ "integrity": "sha512-/KMckLf1PYU/H3PXnS4e0aFl03qG3JlSv4LGgX6juJufcONqGTl/m63EMO/L/eUy6H1CRrXmVDjik/jzHLyDhg==",
+ "dependencies": {
+ "@material/animation": "15.0.0-canary.684e33d25.0",
+ "@material/base": "15.0.0-canary.684e33d25.0",
+ "@material/dom": "15.0.0-canary.684e33d25.0",
+ "@material/elevation": "15.0.0-canary.684e33d25.0",
+ "@material/feature-targeting": "15.0.0-canary.684e33d25.0",
+ "@material/list": "15.0.0-canary.684e33d25.0",
+ "@material/ripple": "15.0.0-canary.684e33d25.0",
+ "@material/rtl": "15.0.0-canary.684e33d25.0",
+ "@material/shape": "15.0.0-canary.684e33d25.0",
+ "@material/theme": "15.0.0-canary.684e33d25.0",
+ "@material/typography": "15.0.0-canary.684e33d25.0",
+ "tslib": "^2.1.0"
+ }
+ },
+ "node_modules/@material/elevation": {
+ "version": "15.0.0-canary.684e33d25.0",
+ "resolved": "https://registry.npmjs.org/@material/elevation/-/elevation-15.0.0-canary.684e33d25.0.tgz",
+ "integrity": "sha512-WDF8SsRtq3rXUbVVbd9K4DUijIPH0bUFSOreVYxudpuxAfTlDS5+aeS1EK9UIBFYLuba4u5wVT2tDv6e1RTfrQ==",
+ "dependencies": {
+ "@material/animation": "15.0.0-canary.684e33d25.0",
+ "@material/base": "15.0.0-canary.684e33d25.0",
+ "@material/feature-targeting": "15.0.0-canary.684e33d25.0",
+ "@material/rtl": "15.0.0-canary.684e33d25.0",
+ "@material/theme": "15.0.0-canary.684e33d25.0",
+ "tslib": "^2.1.0"
+ }
+ },
+ "node_modules/@material/fab": {
+ "version": "15.0.0-canary.684e33d25.0",
+ "resolved": "https://registry.npmjs.org/@material/fab/-/fab-15.0.0-canary.684e33d25.0.tgz",
+ "integrity": "sha512-KCu87rWOKEAe9vZcAm6K8XazYSWPNjMG+OhrbPjHW6bCO7as1YCgtmkBkhff7csY/rFmcVpIy884xtUfLmSudQ==",
+ "dependencies": {
+ "@material/animation": "15.0.0-canary.684e33d25.0",
+ "@material/dom": "15.0.0-canary.684e33d25.0",
+ "@material/elevation": "15.0.0-canary.684e33d25.0",
+ "@material/feature-targeting": "15.0.0-canary.684e33d25.0",
+ "@material/focus-ring": "15.0.0-canary.684e33d25.0",
+ "@material/ripple": "15.0.0-canary.684e33d25.0",
+ "@material/rtl": "15.0.0-canary.684e33d25.0",
+ "@material/shape": "15.0.0-canary.684e33d25.0",
+ "@material/theme": "15.0.0-canary.684e33d25.0",
+ "@material/tokens": "15.0.0-canary.684e33d25.0",
+ "@material/touch-target": "15.0.0-canary.684e33d25.0",
+ "@material/typography": "15.0.0-canary.684e33d25.0",
+ "tslib": "^2.1.0"
+ }
+ },
+ "node_modules/@material/feature-targeting": {
+ "version": "15.0.0-canary.684e33d25.0",
+ "resolved": "https://registry.npmjs.org/@material/feature-targeting/-/feature-targeting-15.0.0-canary.684e33d25.0.tgz",
+ "integrity": "sha512-HyH1erNTSjS63sigNSUMaCd0nJhTNdDFeC+myrxwtDaQm+uYJ8troCNtQM3g6mx0XATNtX5aTOoPmrM6yVVi1A==",
+ "dependencies": {
+ "tslib": "^2.1.0"
+ }
+ },
+ "node_modules/@material/floating-label": {
+ "version": "15.0.0-canary.684e33d25.0",
+ "resolved": "https://registry.npmjs.org/@material/floating-label/-/floating-label-15.0.0-canary.684e33d25.0.tgz",
+ "integrity": "sha512-f7TPp6bKpGvV3sYYiZHSGlrixXKkXXITW3Esp7KB9jRq42c0H82novmdwvY0eTef4ootmA2JEysr78KQfHBUPg==",
+ "dependencies": {
+ "@material/animation": "15.0.0-canary.684e33d25.0",
+ "@material/base": "15.0.0-canary.684e33d25.0",
+ "@material/dom": "15.0.0-canary.684e33d25.0",
+ "@material/feature-targeting": "15.0.0-canary.684e33d25.0",
+ "@material/rtl": "15.0.0-canary.684e33d25.0",
+ "@material/theme": "15.0.0-canary.684e33d25.0",
+ "@material/typography": "15.0.0-canary.684e33d25.0",
+ "tslib": "^2.1.0"
+ }
+ },
+ "node_modules/@material/focus-ring": {
+ "version": "15.0.0-canary.684e33d25.0",
+ "resolved": "https://registry.npmjs.org/@material/focus-ring/-/focus-ring-15.0.0-canary.684e33d25.0.tgz",
+ "integrity": "sha512-ikw2RVUfgzXChpWIzPH1VzRvTjYb5ZKj4H+CZf7jqPUXMstFOZg90Bp7ARLZHqYiyNMuUq3zUTHozS6iHorSqg==",
+ "dependencies": {
+ "@material/dom": "15.0.0-canary.684e33d25.0",
+ "@material/feature-targeting": "15.0.0-canary.684e33d25.0",
+ "@material/rtl": "15.0.0-canary.684e33d25.0"
+ }
+ },
+ "node_modules/@material/form-field": {
+ "version": "15.0.0-canary.684e33d25.0",
+ "resolved": "https://registry.npmjs.org/@material/form-field/-/form-field-15.0.0-canary.684e33d25.0.tgz",
+ "integrity": "sha512-vpF9N/uq5no/7+8GAbEH0868FhOuBgxAWRr1Sfb+jthKfBr8OS/wPU/AHzZHdHdAm7PQynbeOXfDsX2dI//PDA==",
+ "dependencies": {
+ "@material/base": "15.0.0-canary.684e33d25.0",
+ "@material/feature-targeting": "15.0.0-canary.684e33d25.0",
+ "@material/ripple": "15.0.0-canary.684e33d25.0",
+ "@material/rtl": "15.0.0-canary.684e33d25.0",
+ "@material/theme": "15.0.0-canary.684e33d25.0",
+ "@material/typography": "15.0.0-canary.684e33d25.0",
+ "tslib": "^2.1.0"
+ }
+ },
+ "node_modules/@material/icon-button": {
+ "version": "15.0.0-canary.684e33d25.0",
+ "resolved": "https://registry.npmjs.org/@material/icon-button/-/icon-button-15.0.0-canary.684e33d25.0.tgz",
+ "integrity": "sha512-wMI+XGzmIN/o2ePBKg2hLyx7H4pXCRAyyIKMQS1FMp1UKa2tYmiHVX/V8skhKwCqxg3i6Ls/LxMjfPxTR18WvQ==",
+ "dependencies": {
+ "@material/base": "15.0.0-canary.684e33d25.0",
+ "@material/density": "15.0.0-canary.684e33d25.0",
+ "@material/dom": "15.0.0-canary.684e33d25.0",
+ "@material/elevation": "15.0.0-canary.684e33d25.0",
+ "@material/feature-targeting": "15.0.0-canary.684e33d25.0",
+ "@material/focus-ring": "15.0.0-canary.684e33d25.0",
+ "@material/ripple": "15.0.0-canary.684e33d25.0",
+ "@material/rtl": "15.0.0-canary.684e33d25.0",
+ "@material/theme": "15.0.0-canary.684e33d25.0",
+ "@material/touch-target": "15.0.0-canary.684e33d25.0",
+ "tslib": "^2.1.0"
+ }
+ },
+ "node_modules/@material/image-list": {
+ "version": "15.0.0-canary.684e33d25.0",
+ "resolved": "https://registry.npmjs.org/@material/image-list/-/image-list-15.0.0-canary.684e33d25.0.tgz",
+ "integrity": "sha512-Ol+uaHYBe5R/cgzlfh5ONnMVX0wO6fV74JMUcQCQlxP6lXau/edARo4tkRc7A7UJUkU3VRv0EpEjLoCRNUPGaA==",
+ "dependencies": {
+ "@material/feature-targeting": "15.0.0-canary.684e33d25.0",
+ "@material/shape": "15.0.0-canary.684e33d25.0",
+ "@material/theme": "15.0.0-canary.684e33d25.0",
+ "@material/typography": "15.0.0-canary.684e33d25.0",
+ "tslib": "^2.1.0"
+ }
+ },
+ "node_modules/@material/layout-grid": {
+ "version": "15.0.0-canary.684e33d25.0",
+ "resolved": "https://registry.npmjs.org/@material/layout-grid/-/layout-grid-15.0.0-canary.684e33d25.0.tgz",
+ "integrity": "sha512-ALXE1mqFNb/RB2lVRQ3/r1Aufw2mFZnOjRE+boYDVepmAG/xWyPCyaGoavELJF5l4GAb0tXi8wA/8HeGbLOpuA==",
+ "dependencies": {
+ "tslib": "^2.1.0"
+ }
+ },
+ "node_modules/@material/line-ripple": {
+ "version": "15.0.0-canary.684e33d25.0",
+ "resolved": "https://registry.npmjs.org/@material/line-ripple/-/line-ripple-15.0.0-canary.684e33d25.0.tgz",
+ "integrity": "sha512-7hRx8C/e9i0P6pgQpNOMfTwSS2r1fwEvBL72QDVGLtLuoKKwsjjgP6Z0Jat/GeHJe87u9LQvGBoD4upt+of/HA==",
+ "dependencies": {
+ "@material/animation": "15.0.0-canary.684e33d25.0",
+ "@material/base": "15.0.0-canary.684e33d25.0",
+ "@material/feature-targeting": "15.0.0-canary.684e33d25.0",
+ "@material/theme": "15.0.0-canary.684e33d25.0",
+ "tslib": "^2.1.0"
+ }
+ },
+ "node_modules/@material/linear-progress": {
+ "version": "15.0.0-canary.684e33d25.0",
+ "resolved": "https://registry.npmjs.org/@material/linear-progress/-/linear-progress-15.0.0-canary.684e33d25.0.tgz",
+ "integrity": "sha512-iJclt7mKmcMk6pqD7ocXKfCWZhqBoODp7N593jYlxVpTJuEz2wiVAjZUDn/YGj/Uz3CRH+2YFfOiLr9pwWjhDg==",
+ "dependencies": {
+ "@material/animation": "15.0.0-canary.684e33d25.0",
+ "@material/base": "15.0.0-canary.684e33d25.0",
+ "@material/dom": "15.0.0-canary.684e33d25.0",
+ "@material/feature-targeting": "15.0.0-canary.684e33d25.0",
+ "@material/progress-indicator": "15.0.0-canary.684e33d25.0",
+ "@material/rtl": "15.0.0-canary.684e33d25.0",
+ "@material/theme": "15.0.0-canary.684e33d25.0",
+ "tslib": "^2.1.0"
+ }
+ },
+ "node_modules/@material/list": {
+ "version": "15.0.0-canary.684e33d25.0",
+ "resolved": "https://registry.npmjs.org/@material/list/-/list-15.0.0-canary.684e33d25.0.tgz",
+ "integrity": "sha512-rQ+FCSdzmwTcT00IYE0uRV3CS4oGSccKFl9hkcF+aHFW61L7ORh/SCGUDPrEfQFrFkMn5f8qroVJjpUAMXBz4g==",
+ "dependencies": {
+ "@material/base": "15.0.0-canary.684e33d25.0",
+ "@material/density": "15.0.0-canary.684e33d25.0",
+ "@material/dom": "15.0.0-canary.684e33d25.0",
+ "@material/feature-targeting": "15.0.0-canary.684e33d25.0",
+ "@material/ripple": "15.0.0-canary.684e33d25.0",
+ "@material/rtl": "15.0.0-canary.684e33d25.0",
+ "@material/shape": "15.0.0-canary.684e33d25.0",
+ "@material/theme": "15.0.0-canary.684e33d25.0",
+ "@material/tokens": "15.0.0-canary.684e33d25.0",
+ "@material/typography": "15.0.0-canary.684e33d25.0",
+ "tslib": "^2.1.0"
+ }
+ },
+ "node_modules/@material/menu": {
+ "version": "15.0.0-canary.684e33d25.0",
+ "resolved": "https://registry.npmjs.org/@material/menu/-/menu-15.0.0-canary.684e33d25.0.tgz",
+ "integrity": "sha512-r7wzDLSGSI9629/mfpvsMzkVxpmV75kcD3IrW0Pcu6/Bv/1xi0EvjcUXzNJJoQlwN4Zj35Ymz/PCjZkIDIz68Q==",
+ "dependencies": {
+ "@material/base": "15.0.0-canary.684e33d25.0",
+ "@material/dom": "15.0.0-canary.684e33d25.0",
+ "@material/elevation": "15.0.0-canary.684e33d25.0",
+ "@material/feature-targeting": "15.0.0-canary.684e33d25.0",
+ "@material/list": "15.0.0-canary.684e33d25.0",
+ "@material/menu-surface": "15.0.0-canary.684e33d25.0",
+ "@material/ripple": "15.0.0-canary.684e33d25.0",
+ "@material/rtl": "15.0.0-canary.684e33d25.0",
+ "@material/shape": "15.0.0-canary.684e33d25.0",
+ "@material/theme": "15.0.0-canary.684e33d25.0",
+ "@material/tokens": "15.0.0-canary.684e33d25.0",
+ "tslib": "^2.1.0"
+ }
+ },
+ "node_modules/@material/menu-surface": {
+ "version": "15.0.0-canary.684e33d25.0",
+ "resolved": "https://registry.npmjs.org/@material/menu-surface/-/menu-surface-15.0.0-canary.684e33d25.0.tgz",
+ "integrity": "sha512-RVO5GAYcfWPaKwxsF/NhUAmrYXQCQBKvRQW0TIlbmAJz6lcFeTs6YZqF3u1C7qrL3ZQGz+sur/7ywj6QU0oMow==",
+ "dependencies": {
+ "@material/animation": "15.0.0-canary.684e33d25.0",
+ "@material/base": "15.0.0-canary.684e33d25.0",
+ "@material/elevation": "15.0.0-canary.684e33d25.0",
+ "@material/feature-targeting": "15.0.0-canary.684e33d25.0",
+ "@material/rtl": "15.0.0-canary.684e33d25.0",
+ "@material/shape": "15.0.0-canary.684e33d25.0",
+ "@material/theme": "15.0.0-canary.684e33d25.0",
+ "tslib": "^2.1.0"
+ }
+ },
+ "node_modules/@material/notched-outline": {
+ "version": "15.0.0-canary.684e33d25.0",
+ "resolved": "https://registry.npmjs.org/@material/notched-outline/-/notched-outline-15.0.0-canary.684e33d25.0.tgz",
+ "integrity": "sha512-9YHcBkvJLPVYzkHcWoTpBZAFrEd+j1hjhGxLhh0LuNrZe8VroUkZD1TTnUAPHRG3os6EqEWWaKb0RN+aPIF2yQ==",
+ "dependencies": {
+ "@material/base": "15.0.0-canary.684e33d25.0",
+ "@material/feature-targeting": "15.0.0-canary.684e33d25.0",
+ "@material/floating-label": "15.0.0-canary.684e33d25.0",
+ "@material/rtl": "15.0.0-canary.684e33d25.0",
+ "@material/shape": "15.0.0-canary.684e33d25.0",
+ "@material/theme": "15.0.0-canary.684e33d25.0",
+ "tslib": "^2.1.0"
+ }
+ },
+ "node_modules/@material/progress-indicator": {
+ "version": "15.0.0-canary.684e33d25.0",
+ "resolved": "https://registry.npmjs.org/@material/progress-indicator/-/progress-indicator-15.0.0-canary.684e33d25.0.tgz",
+ "integrity": "sha512-c0icji4faeNWUoqGENGC7Hav0Puxh0RwXIDVizffaUxKIGbajpIp5+4Zop73fK/xFLGMB/npg7TbP+aCGjQ3fw==",
+ "dependencies": {
+ "tslib": "^2.1.0"
+ }
+ },
+ "node_modules/@material/radio": {
+ "version": "15.0.0-canary.684e33d25.0",
+ "resolved": "https://registry.npmjs.org/@material/radio/-/radio-15.0.0-canary.684e33d25.0.tgz",
+ "integrity": "sha512-U3Eh8sNUA8trDla1Bq8Bo02foxYvtoewaKeF8A8tAju81XZ4jRiftfOsOWZDZEHCVbbCB2QwvutvFlnay5n+Aw==",
+ "dependencies": {
+ "@material/animation": "15.0.0-canary.684e33d25.0",
+ "@material/base": "15.0.0-canary.684e33d25.0",
+ "@material/density": "15.0.0-canary.684e33d25.0",
+ "@material/dom": "15.0.0-canary.684e33d25.0",
+ "@material/feature-targeting": "15.0.0-canary.684e33d25.0",
+ "@material/focus-ring": "15.0.0-canary.684e33d25.0",
+ "@material/ripple": "15.0.0-canary.684e33d25.0",
+ "@material/theme": "15.0.0-canary.684e33d25.0",
+ "@material/touch-target": "15.0.0-canary.684e33d25.0",
+ "tslib": "^2.1.0"
+ }
+ },
+ "node_modules/@material/ripple": {
+ "version": "15.0.0-canary.684e33d25.0",
+ "resolved": "https://registry.npmjs.org/@material/ripple/-/ripple-15.0.0-canary.684e33d25.0.tgz",
+ "integrity": "sha512-RyePu7SjIm/OuyyEieZ/gxiPYkNZOZHeid72WRcN9ofdlljj2pifcdPvcfZA+v/DMS33xo5GjG2L/Qj6ClWrKw==",
+ "dependencies": {
+ "@material/animation": "15.0.0-canary.684e33d25.0",
+ "@material/base": "15.0.0-canary.684e33d25.0",
+ "@material/dom": "15.0.0-canary.684e33d25.0",
+ "@material/feature-targeting": "15.0.0-canary.684e33d25.0",
+ "@material/rtl": "15.0.0-canary.684e33d25.0",
+ "@material/theme": "15.0.0-canary.684e33d25.0",
+ "tslib": "^2.1.0"
+ }
+ },
+ "node_modules/@material/rtl": {
+ "version": "15.0.0-canary.684e33d25.0",
+ "resolved": "https://registry.npmjs.org/@material/rtl/-/rtl-15.0.0-canary.684e33d25.0.tgz",
+ "integrity": "sha512-NqdJl8Ayupp1Th+vCNCpVQHbUFOuF7TCte9LD1norTIBUF/QizIxWby2W5uUEiPbnh5j9PmE1CJtfLwKun3pcw==",
+ "dependencies": {
+ "@material/theme": "15.0.0-canary.684e33d25.0",
+ "tslib": "^2.1.0"
+ }
+ },
+ "node_modules/@material/segmented-button": {
+ "version": "15.0.0-canary.684e33d25.0",
+ "resolved": "https://registry.npmjs.org/@material/segmented-button/-/segmented-button-15.0.0-canary.684e33d25.0.tgz",
+ "integrity": "sha512-bEGgg8vgXNLyukyV8HRjFMuQ6t6nm5LQ4Pgm22um61Yc8qyi0BOqV41OR4SVdUrUqZxh1aVD+p+4NN03+LfQXw==",
+ "dependencies": {
+ "@material/base": "15.0.0-canary.684e33d25.0",
+ "@material/elevation": "15.0.0-canary.684e33d25.0",
+ "@material/feature-targeting": "15.0.0-canary.684e33d25.0",
+ "@material/ripple": "15.0.0-canary.684e33d25.0",
+ "@material/theme": "15.0.0-canary.684e33d25.0",
+ "@material/touch-target": "15.0.0-canary.684e33d25.0",
+ "@material/typography": "15.0.0-canary.684e33d25.0",
+ "tslib": "^2.1.0"
+ }
+ },
+ "node_modules/@material/select": {
+ "version": "15.0.0-canary.684e33d25.0",
+ "resolved": "https://registry.npmjs.org/@material/select/-/select-15.0.0-canary.684e33d25.0.tgz",
+ "integrity": "sha512-kf178/2TeEinTv0mgmSBcmmExQ2h7a7dtR1E3WuqQgisJ/R6+zVLMkC2CnfIyzxYX2vkuUTG0ue3Reh/6XiqSg==",
+ "dependencies": {
+ "@material/animation": "15.0.0-canary.684e33d25.0",
+ "@material/base": "15.0.0-canary.684e33d25.0",
+ "@material/density": "15.0.0-canary.684e33d25.0",
+ "@material/dom": "15.0.0-canary.684e33d25.0",
+ "@material/elevation": "15.0.0-canary.684e33d25.0",
+ "@material/feature-targeting": "15.0.0-canary.684e33d25.0",
+ "@material/floating-label": "15.0.0-canary.684e33d25.0",
+ "@material/line-ripple": "15.0.0-canary.684e33d25.0",
+ "@material/list": "15.0.0-canary.684e33d25.0",
+ "@material/menu": "15.0.0-canary.684e33d25.0",
+ "@material/menu-surface": "15.0.0-canary.684e33d25.0",
+ "@material/notched-outline": "15.0.0-canary.684e33d25.0",
+ "@material/ripple": "15.0.0-canary.684e33d25.0",
+ "@material/rtl": "15.0.0-canary.684e33d25.0",
+ "@material/shape": "15.0.0-canary.684e33d25.0",
+ "@material/theme": "15.0.0-canary.684e33d25.0",
+ "@material/tokens": "15.0.0-canary.684e33d25.0",
+ "@material/typography": "15.0.0-canary.684e33d25.0",
+ "tslib": "^2.1.0"
+ }
+ },
+ "node_modules/@material/shape": {
+ "version": "15.0.0-canary.684e33d25.0",
+ "resolved": "https://registry.npmjs.org/@material/shape/-/shape-15.0.0-canary.684e33d25.0.tgz",
+ "integrity": "sha512-aEelpaTFmpnCji3TUGP9bVCS/bRVjUmLTHBPZtuu1gOrUVVtJ6kYOg73dZNJF+XOoNL2yOX/LRcKwsop29tptA==",
+ "dependencies": {
+ "@material/feature-targeting": "15.0.0-canary.684e33d25.0",
+ "@material/rtl": "15.0.0-canary.684e33d25.0",
+ "@material/theme": "15.0.0-canary.684e33d25.0",
+ "tslib": "^2.1.0"
+ }
+ },
+ "node_modules/@material/slider": {
+ "version": "15.0.0-canary.684e33d25.0",
+ "resolved": "https://registry.npmjs.org/@material/slider/-/slider-15.0.0-canary.684e33d25.0.tgz",
+ "integrity": "sha512-WVyK+2pSNSZmj07M2K/a3TADoQ9FBCndfNC/vE7/wGIg4dddJJK5KvQ+yruf9R2cSzTL/S1sZ5WpyyeM8E9HTw==",
+ "dependencies": {
+ "@material/animation": "15.0.0-canary.684e33d25.0",
+ "@material/base": "15.0.0-canary.684e33d25.0",
+ "@material/dom": "15.0.0-canary.684e33d25.0",
+ "@material/elevation": "15.0.0-canary.684e33d25.0",
+ "@material/feature-targeting": "15.0.0-canary.684e33d25.0",
+ "@material/ripple": "15.0.0-canary.684e33d25.0",
+ "@material/rtl": "15.0.0-canary.684e33d25.0",
+ "@material/theme": "15.0.0-canary.684e33d25.0",
+ "@material/tokens": "15.0.0-canary.684e33d25.0",
+ "@material/typography": "15.0.0-canary.684e33d25.0",
+ "tslib": "^2.1.0"
+ }
+ },
+ "node_modules/@material/snackbar": {
+ "version": "15.0.0-canary.684e33d25.0",
+ "resolved": "https://registry.npmjs.org/@material/snackbar/-/snackbar-15.0.0-canary.684e33d25.0.tgz",
+ "integrity": "sha512-itO+DCkOannZzR1/cCHcqAm7ifhuFvXmDItNoA8qLEcAyJDJJRkhpwj3XQ01yuo9gBFcSctp7Txt7e+Hncm/Jg==",
+ "dependencies": {
+ "@material/animation": "15.0.0-canary.684e33d25.0",
+ "@material/base": "15.0.0-canary.684e33d25.0",
+ "@material/button": "15.0.0-canary.684e33d25.0",
+ "@material/dom": "15.0.0-canary.684e33d25.0",
+ "@material/elevation": "15.0.0-canary.684e33d25.0",
+ "@material/feature-targeting": "15.0.0-canary.684e33d25.0",
+ "@material/icon-button": "15.0.0-canary.684e33d25.0",
+ "@material/ripple": "15.0.0-canary.684e33d25.0",
+ "@material/rtl": "15.0.0-canary.684e33d25.0",
+ "@material/shape": "15.0.0-canary.684e33d25.0",
+ "@material/theme": "15.0.0-canary.684e33d25.0",
+ "@material/tokens": "15.0.0-canary.684e33d25.0",
+ "@material/typography": "15.0.0-canary.684e33d25.0",
+ "tslib": "^2.1.0"
+ }
+ },
+ "node_modules/@material/switch": {
+ "version": "15.0.0-canary.684e33d25.0",
+ "resolved": "https://registry.npmjs.org/@material/switch/-/switch-15.0.0-canary.684e33d25.0.tgz",
+ "integrity": "sha512-Jxi0gl92yvvZZsAPxvVHzXx2ga+T/djMow98jvEczmpUorWnAhgiCr9CsSSRoosahWyRB8NLZOxUQrACxvffjw==",
+ "dependencies": {
+ "@material/animation": "15.0.0-canary.684e33d25.0",
+ "@material/base": "15.0.0-canary.684e33d25.0",
+ "@material/density": "15.0.0-canary.684e33d25.0",
+ "@material/dom": "15.0.0-canary.684e33d25.0",
+ "@material/elevation": "15.0.0-canary.684e33d25.0",
+ "@material/feature-targeting": "15.0.0-canary.684e33d25.0",
+ "@material/focus-ring": "15.0.0-canary.684e33d25.0",
+ "@material/ripple": "15.0.0-canary.684e33d25.0",
+ "@material/rtl": "15.0.0-canary.684e33d25.0",
+ "@material/shape": "15.0.0-canary.684e33d25.0",
+ "@material/theme": "15.0.0-canary.684e33d25.0",
+ "@material/tokens": "15.0.0-canary.684e33d25.0",
+ "safevalues": "^0.3.4",
+ "tslib": "^2.1.0"
+ }
+ },
+ "node_modules/@material/tab": {
+ "version": "15.0.0-canary.684e33d25.0",
+ "resolved": "https://registry.npmjs.org/@material/tab/-/tab-15.0.0-canary.684e33d25.0.tgz",
+ "integrity": "sha512-WQL3wj9syHNcfe8KbgGGUcA34M8C/xZ+n0Fkkh8Kk6puVwaU+xqUNihsxPY6YzKpmh4PZ4oJaBdiN8zvFT1zqQ==",
+ "dependencies": {
+ "@material/base": "15.0.0-canary.684e33d25.0",
+ "@material/elevation": "15.0.0-canary.684e33d25.0",
+ "@material/feature-targeting": "15.0.0-canary.684e33d25.0",
+ "@material/focus-ring": "15.0.0-canary.684e33d25.0",
+ "@material/ripple": "15.0.0-canary.684e33d25.0",
+ "@material/rtl": "15.0.0-canary.684e33d25.0",
+ "@material/tab-indicator": "15.0.0-canary.684e33d25.0",
+ "@material/theme": "15.0.0-canary.684e33d25.0",
+ "@material/tokens": "15.0.0-canary.684e33d25.0",
+ "@material/typography": "15.0.0-canary.684e33d25.0",
+ "tslib": "^2.1.0"
+ }
+ },
+ "node_modules/@material/tab-bar": {
+ "version": "15.0.0-canary.684e33d25.0",
+ "resolved": "https://registry.npmjs.org/@material/tab-bar/-/tab-bar-15.0.0-canary.684e33d25.0.tgz",
+ "integrity": "sha512-SW/cMaDsIGGkM1ag3A7GJRlmr8eXmObWsvitQJzh6Azr5zzZtSI+GQygkMesAEE1gbpqOVN8d40rh3H7VVIAcA==",
+ "dependencies": {
+ "@material/animation": "15.0.0-canary.684e33d25.0",
+ "@material/base": "15.0.0-canary.684e33d25.0",
+ "@material/density": "15.0.0-canary.684e33d25.0",
+ "@material/elevation": "15.0.0-canary.684e33d25.0",
+ "@material/feature-targeting": "15.0.0-canary.684e33d25.0",
+ "@material/tab": "15.0.0-canary.684e33d25.0",
+ "@material/tab-indicator": "15.0.0-canary.684e33d25.0",
+ "@material/tab-scroller": "15.0.0-canary.684e33d25.0",
+ "@material/theme": "15.0.0-canary.684e33d25.0",
+ "@material/tokens": "15.0.0-canary.684e33d25.0",
+ "@material/typography": "15.0.0-canary.684e33d25.0",
+ "tslib": "^2.1.0"
+ }
+ },
+ "node_modules/@material/tab-indicator": {
+ "version": "15.0.0-canary.684e33d25.0",
+ "resolved": "https://registry.npmjs.org/@material/tab-indicator/-/tab-indicator-15.0.0-canary.684e33d25.0.tgz",
+ "integrity": "sha512-kKICqSPqOlaf0lzaFFCmuOqPXJC+cK48Qmsc+m5o6fJhkmuZRCYpIwB2JeP+uZSOq/bTH+SrPtCtnVlgWg6ksA==",
+ "dependencies": {
+ "@material/animation": "15.0.0-canary.684e33d25.0",
+ "@material/base": "15.0.0-canary.684e33d25.0",
+ "@material/feature-targeting": "15.0.0-canary.684e33d25.0",
+ "@material/theme": "15.0.0-canary.684e33d25.0",
+ "tslib": "^2.1.0"
+ }
+ },
+ "node_modules/@material/tab-scroller": {
+ "version": "15.0.0-canary.684e33d25.0",
+ "resolved": "https://registry.npmjs.org/@material/tab-scroller/-/tab-scroller-15.0.0-canary.684e33d25.0.tgz",
+ "integrity": "sha512-H6EU/TSiK/M2DyyORX5GEtXD9rKYxTMHC2VxsNWARPMFJGzgeW2ugYkFv+rKI1/c0bs0CJ4e+qFnOlBsQXZvyQ==",
+ "dependencies": {
+ "@material/animation": "15.0.0-canary.684e33d25.0",
+ "@material/base": "15.0.0-canary.684e33d25.0",
+ "@material/dom": "15.0.0-canary.684e33d25.0",
+ "@material/feature-targeting": "15.0.0-canary.684e33d25.0",
+ "@material/tab": "15.0.0-canary.684e33d25.0",
+ "tslib": "^2.1.0"
+ }
+ },
+ "node_modules/@material/textfield": {
+ "version": "15.0.0-canary.684e33d25.0",
+ "resolved": "https://registry.npmjs.org/@material/textfield/-/textfield-15.0.0-canary.684e33d25.0.tgz",
+ "integrity": "sha512-OvgpDXjvpyJTtAWskO69IDybFvDNzr9w2PN/Fk7yFm+uNVupaWz1Ew8lZ4gGslaTNSVmh2XcsvmzxcLINSiiNg==",
+ "dependencies": {
+ "@material/animation": "15.0.0-canary.684e33d25.0",
+ "@material/base": "15.0.0-canary.684e33d25.0",
+ "@material/density": "15.0.0-canary.684e33d25.0",
+ "@material/dom": "15.0.0-canary.684e33d25.0",
+ "@material/feature-targeting": "15.0.0-canary.684e33d25.0",
+ "@material/floating-label": "15.0.0-canary.684e33d25.0",
+ "@material/line-ripple": "15.0.0-canary.684e33d25.0",
+ "@material/notched-outline": "15.0.0-canary.684e33d25.0",
+ "@material/ripple": "15.0.0-canary.684e33d25.0",
+ "@material/rtl": "15.0.0-canary.684e33d25.0",
+ "@material/shape": "15.0.0-canary.684e33d25.0",
+ "@material/theme": "15.0.0-canary.684e33d25.0",
+ "@material/tokens": "15.0.0-canary.684e33d25.0",
+ "@material/typography": "15.0.0-canary.684e33d25.0",
+ "tslib": "^2.1.0"
+ }
+ },
+ "node_modules/@material/theme": {
+ "version": "15.0.0-canary.684e33d25.0",
+ "resolved": "https://registry.npmjs.org/@material/theme/-/theme-15.0.0-canary.684e33d25.0.tgz",
+ "integrity": "sha512-AZxaXXAvRKzAi20RlMxzt2U5UmkCWyv7DMWEBXsxtG5Tk54mi1HsbVUp3fxDPTlmL7Pq8p1/DESg/o7TgRCVlw==",
+ "dependencies": {
+ "@material/feature-targeting": "15.0.0-canary.684e33d25.0",
+ "tslib": "^2.1.0"
+ }
+ },
+ "node_modules/@material/tokens": {
+ "version": "15.0.0-canary.684e33d25.0",
+ "resolved": "https://registry.npmjs.org/@material/tokens/-/tokens-15.0.0-canary.684e33d25.0.tgz",
+ "integrity": "sha512-wVwbQOTCXDPKYPdHQHLr026y36MMFelID1CmbfRk6mSol4O8yE9U0fXcShfRDW8Qo5E3X31w9c2A6T3neJY7wQ==",
+ "dependencies": {
+ "@material/elevation": "15.0.0-canary.684e33d25.0"
+ }
+ },
+ "node_modules/@material/tooltip": {
+ "version": "15.0.0-canary.684e33d25.0",
+ "resolved": "https://registry.npmjs.org/@material/tooltip/-/tooltip-15.0.0-canary.684e33d25.0.tgz",
+ "integrity": "sha512-dtm26QjxyQdinc8btgz6yys07b7bUW4FZgNF2EBPeGrICrPg7jf+JEvDziz5g8VMaTBQLOQRSCGy0MKuRlOjLw==",
+ "dependencies": {
+ "@material/animation": "15.0.0-canary.684e33d25.0",
+ "@material/base": "15.0.0-canary.684e33d25.0",
+ "@material/button": "15.0.0-canary.684e33d25.0",
+ "@material/dom": "15.0.0-canary.684e33d25.0",
+ "@material/elevation": "15.0.0-canary.684e33d25.0",
+ "@material/feature-targeting": "15.0.0-canary.684e33d25.0",
+ "@material/rtl": "15.0.0-canary.684e33d25.0",
+ "@material/shape": "15.0.0-canary.684e33d25.0",
+ "@material/theme": "15.0.0-canary.684e33d25.0",
+ "@material/tokens": "15.0.0-canary.684e33d25.0",
+ "@material/typography": "15.0.0-canary.684e33d25.0",
+ "safevalues": "^0.3.4",
+ "tslib": "^2.1.0"
+ }
+ },
+ "node_modules/@material/top-app-bar": {
+ "version": "15.0.0-canary.684e33d25.0",
+ "resolved": "https://registry.npmjs.org/@material/top-app-bar/-/top-app-bar-15.0.0-canary.684e33d25.0.tgz",
+ "integrity": "sha512-1M+oupUxflfW7u81P1XlxoLZB8bLzwtpKofIfDNRbEsiKhlLTERJR3Yak3BGE9xakNMysAaBHlkb5MrN5bNPFw==",
+ "dependencies": {
+ "@material/animation": "15.0.0-canary.684e33d25.0",
+ "@material/base": "15.0.0-canary.684e33d25.0",
+ "@material/elevation": "15.0.0-canary.684e33d25.0",
+ "@material/ripple": "15.0.0-canary.684e33d25.0",
+ "@material/rtl": "15.0.0-canary.684e33d25.0",
+ "@material/shape": "15.0.0-canary.684e33d25.0",
+ "@material/theme": "15.0.0-canary.684e33d25.0",
+ "@material/typography": "15.0.0-canary.684e33d25.0",
+ "tslib": "^2.1.0"
+ }
+ },
+ "node_modules/@material/touch-target": {
+ "version": "15.0.0-canary.684e33d25.0",
+ "resolved": "https://registry.npmjs.org/@material/touch-target/-/touch-target-15.0.0-canary.684e33d25.0.tgz",
+ "integrity": "sha512-zdE69Slg8+T7sTn1OwqZ6H7WBYac9mxJ/JlJqfTqthzIjZRcCxBSYymQJcDHjsrPnUojOtr9U4Tpm5YZ96TEkQ==",
+ "dependencies": {
+ "@material/base": "15.0.0-canary.684e33d25.0",
+ "@material/feature-targeting": "15.0.0-canary.684e33d25.0",
+ "@material/rtl": "15.0.0-canary.684e33d25.0",
+ "@material/theme": "15.0.0-canary.684e33d25.0",
+ "tslib": "^2.1.0"
+ }
+ },
+ "node_modules/@material/typography": {
+ "version": "15.0.0-canary.684e33d25.0",
+ "resolved": "https://registry.npmjs.org/@material/typography/-/typography-15.0.0-canary.684e33d25.0.tgz",
+ "integrity": "sha512-aVnvgMwcfNa/K4wujzpKDIxjGl2hbkEL+m+OKDSQqWYjKcP9QrbzCXJruJBqxrBoPRHLbqo47k5f9uT8raSgjw==",
+ "dependencies": {
+ "@material/feature-targeting": "15.0.0-canary.684e33d25.0",
+ "@material/theme": "15.0.0-canary.684e33d25.0",
+ "tslib": "^2.1.0"
+ }
+ },
"node_modules/@ngtools/webpack": {
"version": "15.2.4",
"resolved": "https://registry.npmjs.org/@ngtools/webpack/-/webpack-15.2.4.tgz",
@@ -9628,6 +10485,11 @@
"integrity": "sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==",
"devOptional": true
},
+ "node_modules/safevalues": {
+ "version": "0.3.4",
+ "resolved": "https://registry.npmjs.org/safevalues/-/safevalues-0.3.4.tgz",
+ "integrity": "sha512-LRneZZRXNgjzwG4bDQdOTSbze3fHm1EAKN/8bePxnlEZiBmkYEDggaHbuvHI9/hoqHbGfsEA7tWS9GhYHZBBsw=="
+ },
"node_modules/sass": {
"version": "1.58.1",
"resolved": "https://registry.npmjs.org/sass/-/sass-1.58.1.tgz",
diff --git a/twirch/package.json b/twirch/package.json
index 5d5217e..1bb8547 100644
--- a/twirch/package.json
+++ b/twirch/package.json
@@ -1,6 +1,6 @@
{
"name": "twirch",
- "version": "0.0.0",
+ "version": "0.3.0",
"scripts": {
"ng": "ng",
"start": "ng serve",
@@ -11,10 +11,12 @@
"private": true,
"dependencies": {
"@angular/animations": "^15.2.0",
+ "@angular/cdk": "^15.2.6",
"@angular/common": "^15.2.0",
"@angular/compiler": "^15.2.0",
"@angular/core": "^15.2.0",
"@angular/forms": "^15.2.0",
+ "@angular/material": "^15.2.6",
"@angular/platform-browser": "^15.2.0",
"@angular/platform-browser-dynamic": "^15.2.0",
"@angular/router": "^15.2.0",
@@ -39,4 +41,4 @@
"karma-jasmine-html-reporter": "~2.0.0",
"typescript": "~4.9.4"
}
-}
+}
\ No newline at end of file
diff --git a/twirch/src/_variables.scss b/twirch/src/_variables.scss
new file mode 100644
index 0000000..2b96b47
--- /dev/null
+++ b/twirch/src/_variables.scss
@@ -0,0 +1,5 @@
+$background-color: rgb(15, 15, 15);
+$background-alt-row-color: rgb(41, 41, 41);
+$text-color: rgb(224, 224, 224);
+$channel-color: rgb(150, 150, 150);
+$timestamp-color: rgb(105, 105, 105);
\ No newline at end of file
diff --git a/twirch/src/app/app.component.html b/twirch/src/app/app.component.html
index 4a686ef..a54030d 100644
--- a/twirch/src/app/app.component.html
+++ b/twirch/src/app/app.component.html
@@ -1,10 +1,13 @@
-
-
+
+
twirch
+


+
-
({{message.channel}})
{{message.timestamp | date:'h:mm'}}
+
{{message['display-name']}}:
diff --git a/twirch/src/app/app.component.scss b/twirch/src/app/app.component.scss
index 92be210..2c69e2b 100644
--- a/twirch/src/app/app.component.scss
+++ b/twirch/src/app/app.component.scss
@@ -1,8 +1,43 @@
-$background-color: rgb(15, 15, 15);
-$background-alt-row-color: rgb(41, 41, 41);
-$text-color: rgb(224, 224, 224);
-$channel-color: rgb(150, 150, 150);
-$timestamp-color: rgb(105, 105, 105);
+@use '../variables';
+
+#navBar {
+ background:rgba(0, 0, 0, 0.75);
+ color: variables.$text-color;
+ position: fixed;
+ top: 0;
+ left: 0;
+ right: 0;
+ height: 32px;
+ line-height: 32px;
+ padding: 0px 8px;
+ display: flex;
+ flex-direction: row;
+ align-items: center;
+ justify-content: space-between;
+ gap: 16px;
+ z-index: 1;
+}
+
+#main {
+ z-index: 0;
+}
+
+.flexSpacer {
+ flex-grow: 99;
+ text-align: center;
+}
+
+.icon {
+ position: relative;
+ color: inherit;
+ top: 0px;
+ width: 24px;
+ height: 24px;
+}
+
+.icon:hover {
+ cursor: pointer;
+}
#messages {
list-style-type: none;
@@ -11,17 +46,28 @@ $timestamp-color: rgb(105, 105, 105);
bottom: 0;
left: 0;
right: 0;
- overflow: auto;
+ overflow: overlay;
overflow-y: scroll;
margin: 32px 0 0 0;
padding: 0;
}
+
+#messages::-webkit-scrollbar {
+ width: 4px;
+}
+
+#messages::-webkit-scrollbar-track {
+ background: rgba(0, 0, 0, 0);
+}
+
+#messages::-webkit-scrollbar-thumb {
+ background-color: variables.$timestamp-color;
+ border-radius: 10px;
+}
+
#messages > li {
padding: 0.5rem 0.5rem;
}
-#messages > li:nth-child(odd) {
- background: $background-alt-row-color;
-}
.messageContainer {
word-wrap: break-word;
@@ -30,27 +76,37 @@ $timestamp-color: rgb(105, 105, 105);
}
.messageChannel {
- color: $channel-color;
+ color: variables.$channel-color;
padding-right: 4px;
}
.messageTimestamp {
- color: $timestamp-color;
+ color: variables.$timestamp-color;
padding-right: 4px;
}
+.messageBadges {
+ padding-right: 2px;
+}
+
.messageUsername {
- color: $text-color;
+ color: variables.$text-color;
font-weight: 600;
padding-right: 4px;
}
.messageText {
- color: $text-color;
+ color: variables.$text-color;
}
img.twitch-emote {
margin: -0.5rem 0;
position: relative;
vertical-align: initial;
+}
+
+img.twitch-badge {
+ position: relative;
+ vertical-align: text-top;
+ padding-right: 2px;
}
\ No newline at end of file
diff --git a/twirch/src/app/app.component.ts b/twirch/src/app/app.component.ts
index ee87686..a19817c 100644
--- a/twirch/src/app/app.component.ts
+++ b/twirch/src/app/app.component.ts
@@ -1,10 +1,13 @@
import { AfterViewChecked, Component, ElementRef, OnDestroy, OnInit, ViewChild, ViewEncapsulation } from '@angular/core';
import { Location } from '@angular/common';
+import { MatDialog, MatDialogConfig } from '@angular/material/dialog';
import { Subscription } from 'rxjs';
import { EmoteOptions, parse } from 'simple-tmi-emotes'
import { Message } from './models/message';
import { ChannelService } from './services/channel-service.service';
+import { BadgeService } from './services/Badges.service';
+import { AboutDialogComponent } from './components/aboutDialog/aboutDialog.component';
@Component({
selector: 'app-root',
@@ -20,7 +23,7 @@ export class AppComponent implements OnInit, OnDestroy, AfterViewChecked {
private _msgSub?: Subscription;
- constructor(private location: Location, private channelService: ChannelService) {
+ constructor(private location: Location, private channelService: ChannelService, private badgeService: BadgeService, private dialog: MatDialog) {
channelService.selectChannels(location.path().split('/').splice(1));
}
@@ -36,6 +39,16 @@ export class AppComponent implements OnInit, OnDestroy, AfterViewChecked {
this._msgSub?.unsubscribe();
}
+ openAbout() {
+ const dialogConfig = new MatDialogConfig();
+
+ dialogConfig.panelClass = 'aboutPanel';
+ dialogConfig.maxHeight = '90%';
+ dialogConfig.maxWidth = '90%';
+
+ this.dialog.open(AboutDialogComponent, dialogConfig);
+ }
+
private processMessage(msg: Message): void {
// Add timestamp
msg.timestamp = new Date(Date.now());
@@ -53,6 +66,10 @@ export class AppComponent implements OnInit, OnDestroy, AfterViewChecked {
msg.message = parse(msg.message, msg.emotes, options);
}
+ if (msg.badges) {
+ msg['badges-raw'] = this.badgeService.parseBadges(msg.badges);
+ }
+
// Push to bound array
this.messages.push(msg);
}
diff --git a/twirch/src/app/app.module.ts b/twirch/src/app/app.module.ts
index 7886805..98f98ce 100644
--- a/twirch/src/app/app.module.ts
+++ b/twirch/src/app/app.module.ts
@@ -5,26 +5,32 @@ import { SocketIoModule, SocketIoConfig } from 'ngx-socket-io';
import { AppRoutingModule } from './app-routing.module';
import { AppComponent } from './app.component';
-import { ToolbarComponent } from './components/toolbar/toolbar.component';
+import { AboutDialogComponent } from './components/aboutDialog/aboutDialog.component';
+import { MatDialogModule } from '@angular/material/dialog';
+import { HttpClientModule } from '@angular/common/http';
const config: SocketIoConfig = {
url: 'https://twirch.io',
options: {
- transports: ['polling', 'websocket']
- }
+ transports: ['polling', 'websocket'],
+ closeOnBeforeunload: true
+ },
};
@NgModule({
declarations: [
AppComponent,
- ToolbarComponent
+ AboutDialogComponent
],
imports: [
BrowserModule,
AppRoutingModule,
- SocketIoModule.forRoot(config)
+ SocketIoModule.forRoot(config),
+ MatDialogModule,
+ HttpClientModule
],
providers: [],
- bootstrap: [AppComponent]
+ bootstrap: [AppComponent],
+ entryComponents: [AboutDialogComponent]
})
export class AppModule { }
diff --git a/twirch/src/app/components/aboutDialog/aboutDialog.component.html b/twirch/src/app/components/aboutDialog/aboutDialog.component.html
new file mode 100644
index 0000000..ede8581
--- /dev/null
+++ b/twirch/src/app/components/aboutDialog/aboutDialog.component.html
@@ -0,0 +1,10 @@
+
+
What is twirch?
+
twirch is a simple web application designed to combine multiple Twitch chats into a single scrolling window.
+
How do I use it?
+
Type the channels that you want to combine into the URL bar, separated by slashes (/). For example, if you want to
+ combine Channel1 and Channel2, your twirch URL would be twirch.io/channel1/channel2
+
Who makes this?
+
I'm Michael "UrzaMTG" McBride, I develop this in my downtime. If you see any issues, the project is on GitHub at
+ https://github.com/UrzaMTG/twirch
+
diff --git a/twirch/src/app/components/aboutDialog/aboutDialog.component.scss b/twirch/src/app/components/aboutDialog/aboutDialog.component.scss
new file mode 100644
index 0000000..e120f1d
--- /dev/null
+++ b/twirch/src/app/components/aboutDialog/aboutDialog.component.scss
@@ -0,0 +1,6 @@
+@use '../../../variables';
+
+#aboutContent {
+ width: 100%;
+ height: 100%;
+}
diff --git a/twirch/src/app/components/toolbar/toolbar.component.spec.ts b/twirch/src/app/components/aboutDialog/aboutDialog.component.spec.ts
similarity index 61%
rename from twirch/src/app/components/toolbar/toolbar.component.spec.ts
rename to twirch/src/app/components/aboutDialog/aboutDialog.component.spec.ts
index 4ace9e8..2b7fd75 100644
--- a/twirch/src/app/components/toolbar/toolbar.component.spec.ts
+++ b/twirch/src/app/components/aboutDialog/aboutDialog.component.spec.ts
@@ -3,21 +3,21 @@ import { async, ComponentFixture, TestBed } from '@angular/core/testing';
import { By } from '@angular/platform-browser';
import { DebugElement } from '@angular/core';
-import { ToolbarComponent } from './toolbar.component';
+import { AboutDialogComponent } from './aboutDialog.component';
-describe('ToolbarComponent', () => {
- let component: ToolbarComponent;
- let fixture: ComponentFixture;
+describe('AboutDialogComponent', () => {
+ let component: AboutDialogComponent;
+ let fixture: ComponentFixture;
beforeEach(async(() => {
TestBed.configureTestingModule({
- declarations: [ ToolbarComponent ]
+ declarations: [ AboutDialogComponent ]
})
.compileComponents();
}));
beforeEach(() => {
- fixture = TestBed.createComponent(ToolbarComponent);
+ fixture = TestBed.createComponent(AboutDialogComponent);
component = fixture.componentInstance;
fixture.detectChanges();
});
diff --git a/twirch/src/app/components/aboutDialog/aboutDialog.component.ts b/twirch/src/app/components/aboutDialog/aboutDialog.component.ts
new file mode 100644
index 0000000..79c9d65
--- /dev/null
+++ b/twirch/src/app/components/aboutDialog/aboutDialog.component.ts
@@ -0,0 +1,16 @@
+import { Component, OnInit } from '@angular/core';
+import { MatDialogRef } from '@angular/material/dialog';
+
+@Component({
+ selector: 'app-aboutDialog',
+ templateUrl: './aboutDialog.component.html',
+ styleUrls: ['./aboutDialog.component.scss']
+})
+export class AboutDialogComponent implements OnInit {
+
+ constructor(public dialogRef: MatDialogRef) { }
+
+ ngOnInit() {
+ }
+
+}
diff --git a/twirch/src/app/components/toolbar/toolbar.component.html b/twirch/src/app/components/toolbar/toolbar.component.html
deleted file mode 100644
index 5b726b8..0000000
--- a/twirch/src/app/components/toolbar/toolbar.component.html
+++ /dev/null
@@ -1,4 +0,0 @@
-
-
twirch
-


-
diff --git a/twirch/src/app/components/toolbar/toolbar.component.scss b/twirch/src/app/components/toolbar/toolbar.component.scss
deleted file mode 100644
index 0d6c6a5..0000000
--- a/twirch/src/app/components/toolbar/toolbar.component.scss
+++ /dev/null
@@ -1,30 +0,0 @@
-#navBar {
- background:rgba(0, 0, 0, 0.75);
- color: rgba(224, 224, 224, 1);
- position: fixed;
- top: 0;
- left: 0;
- right: 0;
- height: 32px;
- line-height: 32px;
- padding: 0px 8px;
- display: flex;
- flex-direction: row;
- align-items: center;
- justify-content: space-between;
- gap: 16px;
- z-index: 1;
-}
-
-.flexSpacer {
- flex-grow: 99;
- text-align: center;
-}
-
-.icon {
- position: relative;
- color: inherit;
- top: 0px;
- width: 24px;
- height: 24px;
-}
\ No newline at end of file
diff --git a/twirch/src/app/components/toolbar/toolbar.component.ts b/twirch/src/app/components/toolbar/toolbar.component.ts
deleted file mode 100644
index edf00f1..0000000
--- a/twirch/src/app/components/toolbar/toolbar.component.ts
+++ /dev/null
@@ -1,15 +0,0 @@
-import { Component, OnInit } from '@angular/core';
-
-@Component({
- selector: 'app-toolbar',
- templateUrl: './toolbar.component.html',
- styleUrls: ['./toolbar.component.scss']
-})
-export class ToolbarComponent implements OnInit {
-
- constructor() { }
-
- ngOnInit() {
- }
-
-}
diff --git a/twirch/src/app/models/BadgeData.ts b/twirch/src/app/models/BadgeData.ts
new file mode 100644
index 0000000..480ee6e
--- /dev/null
+++ b/twirch/src/app/models/BadgeData.ts
@@ -0,0 +1,12 @@
+export interface BadgeData {
+ badge_sets: {[id: string]: FullBadge};
+}
+
+export interface FullBadge {
+ versions: {[version: string]: BadgeVersion};
+}
+
+export interface BadgeVersion {
+ image_url_1x: string;
+ title: string;
+}
\ No newline at end of file
diff --git a/twirch/src/app/services/Badges.service.spec.ts b/twirch/src/app/services/Badges.service.spec.ts
new file mode 100644
index 0000000..4967171
--- /dev/null
+++ b/twirch/src/app/services/Badges.service.spec.ts
@@ -0,0 +1,16 @@
+/* tslint:disable:no-unused-variable */
+
+import { TestBed, async, inject } from '@angular/core/testing';
+import { BadgeService } from './Badges.service';
+
+describe('Service: Badges', () => {
+ beforeEach(() => {
+ TestBed.configureTestingModule({
+ providers: [BadgeService]
+ });
+ });
+
+ it('should ...', inject([BadgeService], (service: BadgeService) => {
+ expect(service).toBeTruthy();
+ }));
+});
diff --git a/twirch/src/app/services/Badges.service.ts b/twirch/src/app/services/Badges.service.ts
new file mode 100644
index 0000000..7c9439d
--- /dev/null
+++ b/twirch/src/app/services/Badges.service.ts
@@ -0,0 +1,57 @@
+import { Injectable } from '@angular/core';
+import { HttpClient } from "@angular/common/http";
+
+import { Badges } from 'tmi.js';
+import { BadgeData } from '../models/BadgeData';
+
+@Injectable({
+ providedIn: 'root'
+})
+export class BadgeService {
+ private data?: BadgeData;
+
+ constructor(private http: HttpClient) {
+ const url = 'https://badges.twitch.tv/v1/badges/global/display';
+ this.http.get(url).subscribe( (res) => {
+ this.data = res;
+ })
+ }
+
+ /**
+ * Create a string of img tags with the badges from the object
+ * @param badges An object with keys equal to the badge id and the value set to the version of that badge to use
+ * @returns A string with one or more img tags with src and title set
+ */
+ parseBadges(badges: Badges): string {
+ let retVal = "";
+
+ if (this.data) {
+ for (const [k, v] of Object.entries(badges)) {
+ if (v) {
+ if (k === 'subscriber') {
+ let maxMonths: number = 0;
+ let msgMonths = Number.parseInt(v);
+ for (const [months, v2] of Object.entries(this.data.badge_sets[k].versions)) {
+ let monthNum: number = Number.parseInt(months);
+ maxMonths = Math.max(maxMonths, monthNum);
+ if (monthNum === msgMonths) {
+ retVal += `
`;
+ break;
+ }
+ }
+
+ if (msgMonths > maxMonths) {
+ retVal += `
`;
+ }
+ }
+ else {
+ retVal += `
`;
+ }
+ }
+ }
+ }
+
+ return retVal;
+ }
+
+}
diff --git a/twirch/src/app/services/channel-service.service.ts b/twirch/src/app/services/channel-service.service.ts
index f277489..9c60966 100644
--- a/twirch/src/app/services/channel-service.service.ts
+++ b/twirch/src/app/services/channel-service.service.ts
@@ -10,12 +10,19 @@ const _chatMessage: string = 'chat message';
})
export class ChannelService {
+ keepAliveTimer;
chatMessage = this.socket.fromEvent(_chatMessage);
- constructor(private socket: Socket) { }
+ constructor(private socket: Socket) {
+ this.keepAliveTimer = setInterval(this.keepAlive, 60000);
+ }
selectChannels(channels: string[]): void {
this.socket.emit(_joinChannels, channels);
}
+ keepAlive(): void {
+ this.socket.emit('keepAlive', 'keepAlive');
+ }
+
}
diff --git a/twirch/src/styles.scss b/twirch/src/styles.scss
index 5d8fa32..c205b99 100644
--- a/twirch/src/styles.scss
+++ b/twirch/src/styles.scss
@@ -1,6 +1,57 @@
+@use './variables';
+
+// Custom Theming for Angular Material
+// For more information: https://material.angular.io/guide/theming
+@use '@angular/material' as mat;
+// Plus imports for other components in your app.
+
+// Include the common styles for Angular Material. We include this here so that you only
+// have to load a single css file for Angular Material in your app.
+// Be sure that you only ever include this mixin once!
+@include mat.core();
+
+// Define the palettes for your theme using the Material Design palettes available in palette.scss
+// (imported above). For each palette, you can optionally specify a default, lighter, and darker
+// hue. Available color palettes: https://material.io/design/color/
+/*$twirch-primary: mat.define-palette(mat.$indigo-palette);
+$twirch-accent: mat.define-palette(mat.$pink-palette, A200, A100, A400);*/
+
+// The warn palette is optional (defaults to red).
+//$twirch-warn: mat.define-palette(mat.$red-palette);
+
+// Create the theme object. A theme consists of configurations for individual
+// theming systems such as "color" or "typography".
+/*$twirch-theme: mat.define-light-theme((
+ color: (
+ primary: $twirch-primary,
+ accent: $twirch-accent,
+ warn: $twirch-warn,
+ )
+));*/
+
+// Include theme styles for core and each component used in your app.
+// Alternatively, you can import and @include the theme mixins for each component
+// that you are using.
+//@include mat.all-component-themes($twirch-theme);
+
/* You can add global styles to this file, and also import other style files */
-body {
+html, body {
+ height: 100%;
margin: 0;
font-family: Inter, Roobert, Helvetica Neue, Helvetica, Arial, sans-serif;
- background: rgb(15, 15, 15);
+ background: rgb(15, 15, 15);
+}
+
+.aboutPanel .mat-mdc-dialog-container .mdc-dialog__surface {
+ padding: 8px;
+ background: variables.$background-color;
+ color: variables.$text-color;
+}
+
+a {
+ color: variables.$text-color;
+}
+
+a:visited {
+ color: variables.$text-color;
}
\ No newline at end of file