feat(portal): add scrolling to the desktop (#2410)

* feat(portal): add scrolling to the desktop

* chore: comments

* chore: fix
This commit is contained in:
Alex Inkin
2023-09-13 22:52:25 +04:00
committed by GitHub
parent f7b079b1b4
commit 7e18aafe20
32 changed files with 325 additions and 256 deletions

View File

@@ -23,11 +23,12 @@
"@start9labs/argon2": "^0.1.0",
"@start9labs/emver": "^0.1.5",
"@start9labs/start-sdk": "0.4.0-rev0.lib0.rc8.beta2",
"@taiga-ui/addon-charts": "3.39.1",
"@taiga-ui/cdk": "3.39.1",
"@taiga-ui/core": "3.39.1",
"@taiga-ui/icons": "3.39.1",
"@taiga-ui/kit": "3.39.1",
"@taiga-ui/addon-charts": "3.44.0",
"@taiga-ui/cdk": "3.44.0",
"@taiga-ui/core": "3.44.0",
"@taiga-ui/experimental": "3.44.0",
"@taiga-ui/icons": "3.44.0",
"@taiga-ui/kit": "3.44.0",
"@tinkoff/ng-dompurify": "4.0.0",
"ansi-to-html": "^0.7.2",
"base64-js": "^1.5.1",
@@ -3590,31 +3591,31 @@
"dev": true
},
"node_modules/@maskito/angular": {
"version": "1.4.0",
"resolved": "https://registry.npmjs.org/@maskito/angular/-/angular-1.4.0.tgz",
"integrity": "sha512-JQqcqgHxF8pz8B6J69I7sbXGuM3DKfpmmaDO1MO0RPOWVDoH2tjuC/VBmSvjnR4sRlvJOsj1aHEQt6cVaSeTog==",
"version": "1.5.1",
"resolved": "https://registry.npmjs.org/@maskito/angular/-/angular-1.5.1.tgz",
"integrity": "sha512-unT8l4CLuehliS8alLYyPVLZHI+KyIm53Yll3yHJEtJy3Wz5rmCuj0h9IPaJ2clR/gXFAi5e5rLEX5SD1uWl4g==",
"dependencies": {
"tslib": "^2.3.0"
"tslib": "2.6.2"
},
"peerDependencies": {
"@angular/common": ">=12.0.0",
"@angular/core": ">=12.0.0",
"@angular/forms": ">=12.0.0",
"@maskito/core": "^1.4.0",
"@maskito/core": "^1.5.1",
"rxjs": ">=6.0.0"
}
},
"node_modules/@maskito/core": {
"version": "1.4.0",
"resolved": "https://registry.npmjs.org/@maskito/core/-/core-1.4.0.tgz",
"integrity": "sha512-Q5o3vQ4c52VzJf6dvA1RgruMHM3uwPCjw2ghwJDNeU7W9xn/iuI61KN/kyuMeZDicRQwE+ddVokg2jEtYiPfJw=="
"version": "1.5.1",
"resolved": "https://registry.npmjs.org/@maskito/core/-/core-1.5.1.tgz",
"integrity": "sha512-AkwUyNjtf4cIAluJc459jf2YRVTVvreMNUpnStx6Kzne1DHf5RZUNeVba+6QYQHe0Mn0E8ftYoYOT5Ac8Wd1ow=="
},
"node_modules/@maskito/kit": {
"version": "1.4.0",
"resolved": "https://registry.npmjs.org/@maskito/kit/-/kit-1.4.0.tgz",
"integrity": "sha512-1hILMNvXbX2GisdrvnFmqqWrjsD4jhUJUWAviIXUBXlxGuh++yqBxx07XEC6BwtYeMDxHD/dF0i5xQ9/oNdxcg==",
"version": "1.5.1",
"resolved": "https://registry.npmjs.org/@maskito/kit/-/kit-1.5.1.tgz",
"integrity": "sha512-/jMMAAmjUqplY62+UGVNwXjK+7XihYRpw4C51WpszrSlH6Sj//bEDcLIA5iqkJD+cK5ROoEyQ63XDRo0D9tUGg==",
"peerDependencies": {
"@maskito/core": "^1.4.0"
"@maskito/core": "^1.5.1"
}
},
"node_modules/@materia-ui/ngx-monaco-editor": {
@@ -3633,7 +3634,6 @@
"version": "3.0.2",
"resolved": "https://registry.npmjs.org/@ng-web-apis/common/-/common-3.0.2.tgz",
"integrity": "sha512-PWMegIsuxfmya8AgSx4fQR5mt4ozaSflJARN6I4W6kGKxX/MnHGt86+djN3P6KVoWjI+bcQt2UlF1jlW9DgWiQ==",
"peer": true,
"dependencies": {
"tslib": "^2.2.0"
},
@@ -3644,9 +3644,9 @@
}
},
"node_modules/@ng-web-apis/intersection-observer": {
"version": "3.1.1",
"resolved": "https://registry.npmjs.org/@ng-web-apis/intersection-observer/-/intersection-observer-3.1.1.tgz",
"integrity": "sha512-DjJK2LiZlfoS5IxeYCV8Qq+ebgEg5sAXRGWYyh/URDzKM6zZeYl+Wf09KVFW4NXgRUPcpBanhOL3DFAdMKEpaQ==",
"version": "3.1.2",
"resolved": "https://registry.npmjs.org/@ng-web-apis/intersection-observer/-/intersection-observer-3.1.2.tgz",
"integrity": "sha512-AojVoHWCS62lJ6LE4BHzyY9E0CXIX8OLmdBw4q6PBJOSZan4vlpup/f9Pl2FPMvw2tVu986IvORFShu1d98y0g==",
"dependencies": {
"tslib": "^2.2.0"
},
@@ -3659,7 +3659,6 @@
"version": "3.0.2",
"resolved": "https://registry.npmjs.org/@ng-web-apis/mutation-observer/-/mutation-observer-3.0.2.tgz",
"integrity": "sha512-x1cq/Vznmz4aJ7STbZmA+4HCE+jxDiw2J359+iyiB+xyCVfZTECrJYP9g/hhzIRxyVPFznrPp61TDCRnLVyNWw==",
"peer": true,
"dependencies": {
"tslib": "^2.2.0"
},
@@ -3672,7 +3671,6 @@
"version": "3.0.2",
"resolved": "https://registry.npmjs.org/@ng-web-apis/resize-observer/-/resize-observer-3.0.2.tgz",
"integrity": "sha512-4aTZNHztwyJe4nJY/++0diUcd8jL7kQS+doPCREE6U4niM8Xvc98uK4qD340Faw9pmybkgsKD7EinyyPE5DIFQ==",
"peer": true,
"dependencies": {
"tslib": "^2.2.0"
},
@@ -4042,9 +4040,9 @@
}
},
"node_modules/@taiga-ui/addon-charts": {
"version": "3.39.1",
"resolved": "https://registry.npmjs.org/@taiga-ui/addon-charts/-/addon-charts-3.39.1.tgz",
"integrity": "sha512-gWae4F0d4Ya4bvKmS6T16SNNkMwCXnsw3LeJhV5lx3jvNr6T8BGGsFZz/+HUrzNsCz+EWhWnZw/zIdusw+wgqg==",
"version": "3.44.0",
"resolved": "https://registry.npmjs.org/@taiga-ui/addon-charts/-/addon-charts-3.44.0.tgz",
"integrity": "sha512-yC42GGVMBgAZm+6ej+UlQNO6Jl4JKT7cGRmz07Jvw+cd2KXDv6+A2cNqmI7EfJnig/3/Lfh560QIRz1uKcTQQw==",
"dependencies": {
"tslib": ">=2.0.0"
},
@@ -4052,22 +4050,22 @@
"@angular/common": ">=12.0.0",
"@angular/core": ">=12.0.0",
"@ng-web-apis/common": ">=3.0.0",
"@taiga-ui/cdk": ">=3.39.1",
"@taiga-ui/core": ">=3.39.1",
"@taiga-ui/cdk": ">=3.44.0",
"@taiga-ui/core": ">=3.44.0",
"@tinkoff/ng-polymorpheus": ">=4.0.0"
}
},
"node_modules/@taiga-ui/cdk": {
"version": "3.39.1",
"resolved": "https://registry.npmjs.org/@taiga-ui/cdk/-/cdk-3.39.1.tgz",
"integrity": "sha512-58DPLyB1bvFHcvn2f5TtXTML0acsXKzXRryyBwQcq3Y7m6DpzmLYWCtcqoYjKk2hN/MVn651GJ8oAqtMZxjmhQ==",
"version": "3.44.0",
"resolved": "https://registry.npmjs.org/@taiga-ui/cdk/-/cdk-3.44.0.tgz",
"integrity": "sha512-sr0vqcuc/ziMjdQTcVPOayhmDwPp4GW1W3lBeUmmuXJpGm7DKrohA0CRUZG+2QZvw7ePVG/G2jBM8268k4I2mw==",
"dependencies": {
"@ng-web-apis/common": "3.0.1",
"@ng-web-apis/mutation-observer": "3.0.1",
"@ng-web-apis/resize-observer": "3.0.1",
"@ng-web-apis/common": "3.0.2",
"@ng-web-apis/mutation-observer": "3.0.2",
"@ng-web-apis/resize-observer": "3.0.2",
"@tinkoff/ng-event-plugins": "3.1.0",
"@tinkoff/ng-polymorpheus": "4.1.0",
"tslib": "2.6.1"
"tslib": "2.6.2"
},
"optionalDependencies": {
"ng-morph": "2.2.5",
@@ -4081,49 +4079,12 @@
"rxjs": ">=6.0.0"
}
},
"node_modules/@taiga-ui/cdk/node_modules/@ng-web-apis/common": {
"version": "3.0.1",
"resolved": "https://registry.npmjs.org/@ng-web-apis/common/-/common-3.0.1.tgz",
"integrity": "sha512-pk0ibndaku/uip6MNST3/SA+sUcQZoajV2y4Mg6frfJzLq3wnKMQH25voL7wgG+XTaWvsS2OPDddPRFLn6qM7g==",
"dependencies": {
"tslib": "^2.2.0"
},
"peerDependencies": {
"@angular/common": ">=12.0.0",
"@angular/core": ">=12.0.0",
"rxjs": ">=6.4.0"
}
},
"node_modules/@taiga-ui/cdk/node_modules/@ng-web-apis/mutation-observer": {
"version": "3.0.1",
"resolved": "https://registry.npmjs.org/@ng-web-apis/mutation-observer/-/mutation-observer-3.0.1.tgz",
"integrity": "sha512-ChzNd/Q4R+wZEHBIqnffX9BsWlHgLxhA0BtJ5OLLnBeUQ/A1O+6v20qfrVmjMzgFqB8SpF+0c9j6SpWpsZHjWw==",
"dependencies": {
"tslib": "^2.2.0"
},
"peerDependencies": {
"@angular/core": ">=12.0.0",
"@ng-web-apis/common": ">=2.0.0"
}
},
"node_modules/@taiga-ui/cdk/node_modules/@ng-web-apis/resize-observer": {
"version": "3.0.1",
"resolved": "https://registry.npmjs.org/@ng-web-apis/resize-observer/-/resize-observer-3.0.1.tgz",
"integrity": "sha512-2rtkX3EeS0Qk6s1lzI5PaLYvDPuC4FT4WBS0yhmI6e8ipoJttNNB+sCLgd5aWarcMXMFWIcWqpmcJxzFFF73Fg==",
"dependencies": {
"tslib": "^2.2.0"
},
"peerDependencies": {
"@angular/core": ">=12.0.0",
"@ng-web-apis/common": ">=2.0.0"
}
},
"node_modules/@taiga-ui/core": {
"version": "3.39.1",
"resolved": "https://registry.npmjs.org/@taiga-ui/core/-/core-3.39.1.tgz",
"integrity": "sha512-ubFqZMpd6V/wo+i2RQ1nAs0QnnguNP08dHDu1Sdwgt+raTjJ6tIneBo8Ot9twQmomu5tGVm9id6JcF7NdCn3eQ==",
"version": "3.44.0",
"resolved": "https://registry.npmjs.org/@taiga-ui/core/-/core-3.44.0.tgz",
"integrity": "sha512-rd8+uADy38iIBjoVvUs5fH2oDGBVb0S/eb/PynQB5vh5zddGFsg10mGfjqtUKoLCdrMmlIVfSJ2Fv0AbibsIaQ==",
"dependencies": {
"@taiga-ui/i18n": "^3.39.1",
"@taiga-ui/i18n": "^3.44.0",
"tslib": ">=2.0.0"
},
"peerDependencies": {
@@ -4135,45 +4096,63 @@
"@angular/router": ">=12.0.0",
"@ng-web-apis/common": ">=3.0.0",
"@ng-web-apis/mutation-observer": ">=3.0.0",
"@taiga-ui/cdk": ">=3.39.1",
"@taiga-ui/i18n": ">=3.39.1",
"@taiga-ui/cdk": ">=3.44.0",
"@taiga-ui/i18n": ">=3.44.0",
"@tinkoff/ng-event-plugins": ">=3.1.0",
"@tinkoff/ng-polymorpheus": ">=4.0.0",
"rxjs": ">=6.0.0"
}
},
"node_modules/@taiga-ui/experimental": {
"version": "3.44.0",
"resolved": "https://registry.npmjs.org/@taiga-ui/experimental/-/experimental-3.44.0.tgz",
"integrity": "sha512-fR//2I2FwPPomAyoJSTb+Mla/WOmSZyhnjBVqTZ1jAEbZEmEYwYFMWmWCCorfGiHQhJz0W9d+A22/04FEn94BA==",
"dependencies": {
"tslib": ">=2.0.0"
},
"peerDependencies": {
"@angular/common": ">=12.0.0",
"@angular/core": ">=12.0.0",
"@taiga-ui/cdk": ">=3.44.0",
"@taiga-ui/core": ">=3.44.0",
"@taiga-ui/kit": ">=3.44.0",
"@tinkoff/ng-polymorpheus": ">=4.0.0",
"rxjs": ">=6.0.0"
}
},
"node_modules/@taiga-ui/i18n": {
"version": "3.39.1",
"resolved": "https://registry.npmjs.org/@taiga-ui/i18n/-/i18n-3.39.1.tgz",
"integrity": "sha512-OoelgJCMZt5WdoT6ej+5ywip/7mBFU4AB2lQJTiO0hVCwhLvxQd6lEbQtKbt5uQzxZXGku+P4452DTP2zvW1mA==",
"version": "3.44.0",
"resolved": "https://registry.npmjs.org/@taiga-ui/i18n/-/i18n-3.44.0.tgz",
"integrity": "sha512-SzjCLKxhGicGEdTPcI6wCtJyoA+SdTZiimzvf1Xt03B+CCc/2rqsPL45XVlnVAwX4lyZUq0mHiA/OcxPlIme+Q==",
"dependencies": {
"tslib": ">=2.0.0"
},
"peerDependencies": {
"@angular/core": ">=12.0.0",
"@taiga-ui/cdk": ">=3.39.1"
"@ng-web-apis/common": ">=3.0.0",
"rxjs": ">=6.0.0"
}
},
"node_modules/@taiga-ui/icons": {
"version": "3.39.1",
"resolved": "https://registry.npmjs.org/@taiga-ui/icons/-/icons-3.39.1.tgz",
"integrity": "sha512-qlCeehk2EANlBNZY6/Ah2aXmmuWE/vveC44w85APIwWelxC+1JUFiGYu3mWqmUjpWy6UPNql8COmLpmldRICmw==",
"version": "3.44.0",
"resolved": "https://registry.npmjs.org/@taiga-ui/icons/-/icons-3.44.0.tgz",
"integrity": "sha512-hVWZfPQrGRG1MywuNwRh0jzOJsUFDMiRvdqZrLSs1iQBH/lwEQAZ2KoLHEgGt0GOTwK9DzgXIKVo4bwexs+EmA==",
"dependencies": {
"tslib": ">=2.0.0"
},
"peerDependencies": {
"@taiga-ui/cdk": ">=3.39.1"
"@taiga-ui/cdk": ">=3.44.0"
}
},
"node_modules/@taiga-ui/kit": {
"version": "3.39.1",
"resolved": "https://registry.npmjs.org/@taiga-ui/kit/-/kit-3.39.1.tgz",
"integrity": "sha512-VuXx74QWmAw/HPyw/yIt5+3kLAGhMDqwTARIPteLCnnmEdqT52tB6eulamVKBmEtRbq8TPa21JxKCyaQuNa5VQ==",
"version": "3.44.0",
"resolved": "https://registry.npmjs.org/@taiga-ui/kit/-/kit-3.44.0.tgz",
"integrity": "sha512-klWCWT9IizqJAzCc+XauiTFmX11Qz2zwxvfpLZwAtVWz/cmllf05gL5ynL0LIXhGrzu+2YVQRys9cej2yN2G9Q==",
"dependencies": {
"@maskito/angular": "1.4.0",
"@maskito/core": "1.4.0",
"@maskito/kit": "1.4.0",
"@ng-web-apis/intersection-observer": "3.1.1",
"@maskito/angular": "1.5.1",
"@maskito/core": "1.5.1",
"@maskito/kit": "1.5.1",
"@ng-web-apis/intersection-observer": "3.1.2",
"text-mask-core": "5.1.2",
"tslib": ">=2.0.0"
},
@@ -4185,9 +4164,9 @@
"@ng-web-apis/common": ">=3.0.0",
"@ng-web-apis/mutation-observer": ">=3.0.0",
"@ng-web-apis/resize-observer": ">=3.0.0",
"@taiga-ui/cdk": ">=3.39.1",
"@taiga-ui/core": ">=3.39.1",
"@taiga-ui/i18n": ">=3.39.1",
"@taiga-ui/cdk": ">=3.44.0",
"@taiga-ui/core": ">=3.44.0",
"@taiga-ui/i18n": ">=3.44.0",
"@tinkoff/ng-polymorpheus": ">=4.0.0",
"rxjs": ">=6.0.0"
}
@@ -14032,9 +14011,9 @@
}
},
"node_modules/tslib": {
"version": "2.6.1",
"resolved": "https://registry.npmjs.org/tslib/-/tslib-2.6.1.tgz",
"integrity": "sha512-t0hLfiEKfMUoqhG+U1oid7Pva4bbDPHYfJNiB7BiIjRkj1pyC++4N3huJfqY6aRH6VTB0rvtzQwjM4K6qpfOig=="
"version": "2.6.2",
"resolved": "https://registry.npmjs.org/tslib/-/tslib-2.6.2.tgz",
"integrity": "sha512-AEYxH93jGFPn/a2iVAwW87VuUIkR1FVUKB77NwMF7nBTDkDrrT/Hpt/IrCJ0QXhW27jTBDcf5ZY7w6RiqTMw2Q=="
},
"node_modules/tslint": {
"version": "6.1.3",

View File

@@ -44,11 +44,12 @@
"@materia-ui/ngx-monaco-editor": "^6.0.0",
"@start9labs/argon2": "^0.1.0",
"@start9labs/emver": "^0.1.5",
"@taiga-ui/addon-charts": "3.39.1",
"@taiga-ui/cdk": "3.39.1",
"@taiga-ui/core": "3.39.1",
"@taiga-ui/icons": "3.39.1",
"@taiga-ui/kit": "3.39.1",
"@taiga-ui/addon-charts": "3.44.0",
"@taiga-ui/cdk": "3.44.0",
"@taiga-ui/core": "3.44.0",
"@taiga-ui/experimental": "3.44.0",
"@taiga-ui/icons": "3.44.0",
"@taiga-ui/kit": "3.44.0",
"@tinkoff/ng-dompurify": "4.0.0",
"ansi-to-html": "^0.7.2",
"base64-js": "^1.5.1",

View File

@@ -2,12 +2,12 @@ import { CommonModule } from '@angular/common'
import { NgModule } from '@angular/core'
import { FormsModule } from '@angular/forms'
import { IonicModule } from '@ionic/angular'
import { ResponsiveColModule } from '@start9labs/shared'
import { ResponsiveColDirective } from '@start9labs/shared'
import { SearchComponent } from './search.component'
@NgModule({
imports: [IonicModule, FormsModule, CommonModule, ResponsiveColModule],
imports: [IonicModule, FormsModule, CommonModule, ResponsiveColDirective],
declarations: [SearchComponent],
exports: [SearchComponent],
})

View File

@@ -1,12 +1,12 @@
import { CommonModule } from '@angular/common'
import { NgModule } from '@angular/core'
import { IonicModule } from '@ionic/angular'
import { ResponsiveColModule } from '@start9labs/shared'
import { ResponsiveColDirective } from '@start9labs/shared'
import { SkeletonComponent } from './skeleton.component'
@NgModule({
imports: [CommonModule, IonicModule, ResponsiveColModule],
imports: [CommonModule, IonicModule, ResponsiveColDirective],
declarations: [SkeletonComponent],
exports: [SkeletonComponent],
})

View File

@@ -4,7 +4,7 @@ import { IonicModule } from '@ionic/angular'
import {
EmverPipesModule,
MarkdownPipeModule,
SafeLinksModule,
SafeLinksDirective,
TextSpinnerComponentModule,
} from '@start9labs/shared'
import { TuiElementModule } from '@taiga-ui/cdk'
@@ -21,7 +21,7 @@ import { ReleaseNotesComponent } from './release-notes.component'
MarkdownPipeModule,
TuiElementModule,
NgDompurifyModule,
SafeLinksModule,
SafeLinksDirective,
],
declarations: [ReleaseNotesComponent],
exports: [ReleaseNotesComponent],

View File

@@ -5,7 +5,7 @@ import { IonicModule } from '@ionic/angular'
import {
EmverPipesModule,
MarkdownPipeModule,
SafeLinksModule,
SafeLinksDirective,
} from '@start9labs/shared'
import { NgDompurifyModule } from '@tinkoff/ng-dompurify'
@@ -19,7 +19,7 @@ import { AboutComponent } from './about.component'
MarkdownPipeModule,
EmverPipesModule,
NgDompurifyModule,
SafeLinksModule,
SafeLinksDirective,
],
declarations: [AboutComponent],
exports: [AboutComponent],

View File

@@ -1,7 +1,7 @@
import { CommonModule } from '@angular/common'
import { NgModule } from '@angular/core'
import { IonicModule } from '@ionic/angular'
import { MarkdownModule, ResponsiveColModule } from '@start9labs/shared'
import { MarkdownModule, ResponsiveColDirective } from '@start9labs/shared'
import { AdditionalComponent } from './additional.component'
import {
@@ -16,7 +16,7 @@ import { TuiButtonModule } from '@taiga-ui/core'
CommonModule,
IonicModule,
MarkdownModule,
ResponsiveColModule,
ResponsiveColDirective,
TuiRadioListModule,
FormsModule,
TuiStringifyContentPipeModule,

View File

@@ -4,7 +4,7 @@ import { RouterModule } from '@angular/router'
import { IonicModule } from '@ionic/angular'
import {
EmverPipesModule,
ResponsiveColModule,
ResponsiveColDirective,
SharedPipesModule,
} from '@start9labs/shared'
@@ -17,7 +17,7 @@ import { DependenciesComponent } from './dependencies.component'
IonicModule,
SharedPipesModule,
EmverPipesModule,
ResponsiveColModule,
ResponsiveColDirective,
],
declarations: [DependenciesComponent],
exports: [DependenciesComponent],

View File

@@ -2,7 +2,7 @@ import { NgModule } from '@angular/core'
import { CommonModule } from '@angular/common'
import { IonicModule } from '@ionic/angular'
import { FormsModule } from '@angular/forms'
import { ResponsiveColModule } from '@start9labs/shared'
import { ResponsiveColDirective } from '@start9labs/shared'
import { SuccessPage } from './success.page'
import { PasswordPageModule } from '../../modals/password/password.module'
@@ -16,7 +16,7 @@ import { DownloadDocComponent } from './download-doc/download-doc.component'
IonicModule,
PasswordPageModule,
SuccessPageRoutingModule,
ResponsiveColModule,
ResponsiveColDirective,
],
declarations: [SuccessPage, DownloadDocComponent],
exports: [SuccessPage],

View File

@@ -4,7 +4,7 @@ import { IonicModule } from '@ionic/angular'
import { NgDompurifyModule } from '@tinkoff/ng-dompurify'
import { MarkdownPipeModule } from '../../pipes/markdown/markdown.module'
import { SafeLinksModule } from '../../directives/safe-links/safe-links.module'
import { SafeLinksDirective } from '../../directives/safe-links.directive'
import { TextSpinnerComponentModule } from '../text-spinner/text-spinner.component.module'
import { MarkdownComponent } from './markdown.component'
@@ -15,7 +15,7 @@ import { MarkdownComponent } from './markdown.component'
IonicModule,
MarkdownPipeModule,
TextSpinnerComponentModule,
SafeLinksModule,
SafeLinksDirective,
NgDompurifyModule,
],
exports: [MarkdownComponent],

View File

@@ -0,0 +1,60 @@
import {
Directive,
ElementRef,
HostListener,
inject,
NgZone,
} from '@angular/core'
import { DOCUMENT } from '@angular/common'
import { ANIMATION_FRAME } from '@ng-web-apis/common'
import { takeUntilDestroyed } from '@angular/core/rxjs-interop'
import { tuiZonefree } from '@taiga-ui/cdk'
import { filter } from 'rxjs'
const SIZE = 100
const SPEED = 15
@Directive({
selector: '[dragScroller]',
standalone: true,
})
export class DragScrollerDirective {
private readonly element: HTMLElement = inject(ElementRef).nativeElement
private dragging = false
private x = 0
private y = 0
private readonly sub = inject(ANIMATION_FRAME)
.pipe(
filter(() => this.dragging),
tuiZonefree(inject(NgZone)),
takeUntilDestroyed(),
)
.subscribe(() => {
this.element.scrollTop += this.y * SPEED
this.element.scrollLeft += this.x * SPEED
})
@HostListener('document:pointerdown.silent', ['true'])
@HostListener('document:pointerup.silent', ['false'])
onPointer(dragging: boolean) {
this.dragging = dragging
this.x = 0
this.y = 0
}
@HostListener('pointermove.silent', ['$event'])
onPointerMove(event: PointerEvent) {
if (!this.dragging) {
return
}
const { clientX, clientY } = event
const { top, left, right, bottom } = this.element.getBoundingClientRect()
const x = Math.min(clientX - left, SIZE) - Math.min(right - clientX, SIZE)
const y = Math.min(clientY - top, SIZE) - Math.min(bottom - clientY, SIZE)
this.x = x / SIZE
this.y = y / SIZE
}
}

View File

@@ -1,5 +1,7 @@
import {
Directive,
OnInit,
Optional,
ElementRef,
Inject,
InjectionToken,
@@ -8,10 +10,14 @@ import {
} from '@angular/core'
import { ResizeObserverService } from '@ng-web-apis/resize-observer'
import { distinctUntilChanged, map, Observable } from 'rxjs'
import { tuiZonefree } from '@taiga-ui/cdk'
import { tuiZonefree, TuiDestroyService } from '@taiga-ui/cdk'
import { IonCol } from '@ionic/angular'
import { takeUntil } from 'rxjs'
export type Step = 'xs' | 'sm' | 'md' | 'lg' | 'xl'
const SIZE: readonly Step[] = ['xl', 'lg', 'md', 'sm', 'xs']
/**
* Not exported:
* https://github.com/ionic-team/ionic-framework/blob/main/core/src/utils/media.ts
@@ -41,6 +47,7 @@ export const BREAKPOINTS = new InjectionToken<readonly [number, Step][]>(
selector: '[responsiveColViewport]',
exportAs: 'viewport',
providers: [ResizeObserverService],
standalone: true,
})
export class ResponsiveColViewportDirective extends Observable<Step> {
@Input()
@@ -65,3 +72,50 @@ export class ResponsiveColViewportDirective extends Observable<Step> {
tuiZonefree(this.zone),
)
}
@Directive({
selector: 'ion-col[responsiveCol]',
providers: [TuiDestroyService],
standalone: true,
})
export class ResponsiveColDirective implements OnInit {
readonly size: Record<Step, string | undefined> = {
xs: '12',
sm: '6',
md: '4',
lg: '3',
xl: '2',
}
constructor(
@Optional()
viewport$: ResponsiveColViewportDirective | null,
destroy$: TuiDestroyService,
private readonly col: IonCol,
) {
viewport$?.pipe(takeUntil(destroy$)).subscribe(size => {
const max = this.size[size] || this.findMax(size)
this.col.sizeLg = max
this.col.sizeMd = max
this.col.sizeSm = max
this.col.sizeXl = max
this.col.sizeXs = max
})
}
ngOnInit() {
this.size.lg = this.col.sizeLg
this.size.md = this.col.sizeMd
this.size.sm = this.col.sizeSm
this.size.xl = this.col.sizeXl
this.size.xs = this.col.sizeXs
}
private findMax(current: Step): string | undefined {
const start = SIZE.indexOf(current) - 1
const max = SIZE.find((size, i) => i > start && this.size[size]) || current
return this.size[max]
}
}

View File

@@ -1,56 +0,0 @@
import { Directive, OnInit, Optional } from '@angular/core'
import { TuiDestroyService } from '@taiga-ui/cdk'
import {
ResponsiveColViewportDirective,
Step,
} from './responsive-col-viewport.directive'
import { IonCol } from '@ionic/angular'
import { takeUntil } from 'rxjs'
const SIZE: readonly Step[] = ['xl', 'lg', 'md', 'sm', 'xs']
@Directive({
selector: 'ion-col[responsiveCol]',
providers: [TuiDestroyService],
})
export class ResponsiveColDirective implements OnInit {
readonly size: Record<Step, string | undefined> = {
xs: '12',
sm: '6',
md: '4',
lg: '3',
xl: '2',
}
constructor(
@Optional()
viewport$: ResponsiveColViewportDirective | null,
destroy$: TuiDestroyService,
private readonly col: IonCol,
) {
viewport$?.pipe(takeUntil(destroy$)).subscribe(size => {
const max = this.size[size] || this.findMax(size)
this.col.sizeLg = max
this.col.sizeMd = max
this.col.sizeSm = max
this.col.sizeXl = max
this.col.sizeXs = max
})
}
ngOnInit() {
this.size.lg = this.col.sizeLg
this.size.md = this.col.sizeMd
this.size.sm = this.col.sizeSm
this.size.xl = this.col.sizeXl
this.size.xs = this.col.sizeXs
}
private findMax(current: Step): string | undefined {
const start = SIZE.indexOf(current) - 1
const max = SIZE.find((size, i) => i > start && this.size[size]) || current
return this.size[max]
}
}

View File

@@ -1,10 +0,0 @@
import { NgModule } from '@angular/core'
import { ResponsiveColViewportDirective } from './responsive-col-viewport.directive'
import { ResponsiveColDirective } from './responsive-col.directive'
@NgModule({
declarations: [ResponsiveColDirective, ResponsiveColViewportDirective],
exports: [ResponsiveColDirective, ResponsiveColViewportDirective],
})
export class ResponsiveColModule {}

View File

@@ -4,6 +4,7 @@ import { DOCUMENT } from '@angular/common'
// TODO: Refactor to use `MutationObserver` so it works with dynamic content
@Directive({
selector: '[safeLinks]',
standalone: true,
})
export class SafeLinksDirective implements AfterViewInit {
constructor(

View File

@@ -1,8 +0,0 @@
import { NgModule } from '@angular/core'
import { SafeLinksDirective } from './safe-links.directive'
@NgModule({
declarations: [SafeLinksDirective],
exports: [SafeLinksDirective],
})
export class SafeLinksModule {}

View File

@@ -18,11 +18,9 @@ export * from './components/text-spinner/text-spinner.component.module'
export * from './components/ticker/ticker.component'
export * from './components/ticker/ticker.module'
export * from './directives/responsive-col/responsive-col.directive'
export * from './directives/responsive-col/responsive-col.module'
export * from './directives/responsive-col/responsive-col-viewport.directive'
export * from './directives/safe-links/safe-links.directive'
export * from './directives/safe-links/safe-links.module'
export * from './directives/drag-scroller.directive'
export * from './directives/responsive-col.directive'
export * from './directives/safe-links.directive'
export * from './mocks/get-setup-status'

View File

@@ -13,10 +13,10 @@ import { MonacoEditorModule } from '@materia-ui/ngx-monaco-editor'
import {
MarkdownModule,
DarkThemeModule,
ResponsiveColModule,
SharedPipesModule,
LightThemeModule,
LoadingModule,
ResponsiveColViewportDirective,
} from '@start9labs/shared'
import { AppComponent } from './app.component'
@@ -61,7 +61,7 @@ import { environment } from '../environments/environment'
TuiModeModule,
TuiThemeNightModule,
WidgetsPageModule,
ResponsiveColModule,
ResponsiveColViewportDirective,
DarkThemeModule,
LightThemeModule,
ServiceWorkerModule.register('ngsw-worker.js', {

View File

@@ -61,4 +61,9 @@ export class CardComponent {
this.navigation.addTab({ icon, title, routerLink })
}
@HostListener('pointerdown.prevent')
onDown() {
// Prevents Firefox from starting a native drag
}
}

View File

@@ -8,6 +8,7 @@ import {
import { tuiGetActualTarget, tuiIsElement, tuiPx } from '@taiga-ui/cdk'
import { DrawerComponent } from './drawer.component'
import { DesktopService } from '../../services/desktop.service'
import { TuiAlertService } from '@taiga-ui/core'
/**
* This directive is responsible for drag and drop of the drawer item.
@@ -17,10 +18,12 @@ import { DesktopService } from '../../services/desktop.service'
selector: '[drawerItem]',
standalone: true,
host: {
'[style.userSelect]': '"none"',
'[style.touchAction]': '"none"',
},
})
export class DrawerItemDirective {
private readonly alerts = inject(TuiAlertService)
private readonly desktop = inject(DesktopService)
private readonly drawer = inject(DrawerComponent)
private readonly element: HTMLElement = inject(ElementRef).nativeElement
@@ -31,11 +34,8 @@ export class DrawerItemDirective {
@Input()
drawerItem = ''
@HostListener('pointerdown.prevent.silent', ['$event'])
@HostListener('pointerdown.silent', ['$event'])
onStart(event: PointerEvent): void {
// This element is already on the desktop
if (this.desktop.items.includes(this.drawerItem)) return
const target = tuiGetActualTarget(event)
const { x, y, pointerId } = event
const { left, top } = this.element.getBoundingClientRect()
@@ -62,6 +62,15 @@ export class DrawerItemDirective {
onMove(x: number, y: number): void {
// This element is not dragged
if (Number.isNaN(this.x)) return
// This element is already on the desktop
if (this.desktop.items.includes(this.drawerItem)) {
this.onPointer()
this.alerts
.open('This item is already added', { status: 'warning' })
.subscribe()
return
}
this.process(x, y)
this.desktop.add('')

View File

@@ -46,7 +46,7 @@
</button>
</tui-opt-group>
<tui-opt-group>
<button tuiOption class="item" (click)="({})">
<button tuiOption class="item" (click)="logout()">
<tui-svg src="tuiIconLogOut"></tui-svg>
Logout
</button>

View File

@@ -1,10 +1,12 @@
import { ChangeDetectionStrategy, Component } from '@angular/core'
import { ChangeDetectionStrategy, Component, inject } from '@angular/core'
import {
TuiButtonModule,
TuiDataListModule,
TuiHostedDropdownModule,
TuiSvgModule,
} from '@taiga-ui/core'
import { ApiService } from 'src/app/services/api/embassy-api.service'
import { AuthService } from 'src/app/services/auth.service'
@Component({
selector: 'header-menu',
@@ -19,4 +21,12 @@ import {
TuiButtonModule,
],
})
export class HeaderMenuComponent {}
export class HeaderMenuComponent {
private readonly api = inject(ApiService)
private readonly auth = inject(AuthService)
logout() {
this.api.logout({}).catch(e => console.error('Failed to log out', e))
this.auth.setUnverified()
}
}

View File

@@ -27,8 +27,8 @@ export class ToDesktopItemPipe implements PipeTransform {
}
return {
icon: packages[id].icon,
title: packages[id].manifest.title,
icon: packages[id]?.icon,
title: packages[id]?.manifest.title,
routerLink,
}
}

View File

@@ -12,30 +12,32 @@
@tuiScaleIn
(pointerup)="onRemove()"
></tui-svg>
<tui-tiles
*ngIf="packages$ | async as packages"
class="tiles"
@tuiParentStop
[debounce]="500"
[order]="desktop.order"
(orderChange)="onReorder($event)"
>
<tui-tile
*ngFor="let item of desktop.items; let index = index"
class="item"
[style.order]="desktop.order.get(index)"
[desktopItem]="item"
<div dragScroller tuiFade="vertical" class="fade">
<tui-tiles
*ngIf="packages$ | async as packages"
class="tiles"
@tuiParentStop
[debounce]="500"
[order]="desktop.order"
(orderChange)="onReorder($event)"
>
<a
*ngIf="packages | toDesktopItem : item as desktopItem"
tuiTileHandle
appCard
@tuiFadeIn
[id]="item"
[title]="desktopItem.title"
[icon]="desktopItem.icon"
[routerLink]="desktopItem.routerLink"
></a>
</tui-tile>
</tui-tiles>
<tui-tile
*ngFor="let item of desktop.items; let index = index"
class="item"
[style.order]="desktop.order.get(index)"
[desktopItem]="item"
>
<a
*ngIf="packages | toDesktopItem : item as desktopItem"
tuiTileHandle
appCard
@tuiFadeIn
[id]="item"
[title]="desktopItem.title"
[icon]="desktopItem.icon"
[routerLink]="desktopItem.routerLink"
></a>
</tui-tile>
</tui-tiles>
</div>
</ng-template>

View File

@@ -6,9 +6,8 @@
align-content: center;
justify-content: center;
height: 100%;
max-width: 56rem;
max-width: calc(100vw - 4rem);
margin: 0 auto;
padding: 1rem 0;
}
.loader {
@@ -16,13 +15,30 @@
width: 10rem;
}
.fade {
@include scrollbar-hidden();
width: 100%;
height: calc(100% - 4rem);
display: flex;
flex-direction: column;
overflow: auto;
}
.tiles {
width: 100%;
min-height: 5.5rem;
justify-content: center;
grid-template-columns: repeat(auto-fit, 12.5rem);
grid-auto-rows: 5.5rem;
grid-auto-rows: min-content;
gap: 2rem;
margin: auto;
&::after {
content: '';
grid-column: 1;
height: 1rem;
order: 999;
}
}
.remove {
@@ -41,8 +57,12 @@
}
}
.item._dragged,
.item._empty {
border-radius: var(--tui-radius-l);
box-shadow: inset 0 0 0 0.5rem var(--tui-clear-active);
.item {
height: 5.5rem;
&._dragged,
&._empty {
border-radius: var(--tui-radius-l);
box-shadow: inset 0 0 0 0.5rem var(--tui-clear-active);
}
}

View File

@@ -1,7 +1,9 @@
import { CommonModule } from '@angular/common'
import { NgModule } from '@angular/core'
import { RouterModule, Routes } from '@angular/router'
import { DragScrollerDirective } from '@start9labs/shared'
import { TuiLoaderModule, TuiSvgModule } from '@taiga-ui/core'
import { TuiFadeModule } from '@taiga-ui/experimental'
import { TuiTilesModule } from '@taiga-ui/kit'
import { DesktopComponent } from './desktop.component'
import { CardComponent } from '../../components/card/card.component'
@@ -25,6 +27,8 @@ const ROUTES: Routes = [
TuiTilesModule,
ToDesktopItemPipe,
RouterModule.forChild(ROUTES),
TuiFadeModule,
DragScrollerDirective,
],
declarations: [DesktopComponent],
exports: [DesktopComponent],

View File

@@ -6,7 +6,7 @@ import { IonicModule } from '@ionic/angular'
import {
SharedPipesModule,
EmverPipesModule,
ResponsiveColModule,
ResponsiveColDirective,
} from '@start9labs/shared'
import {
FilterPackagesPipeModule,
@@ -45,7 +45,7 @@ const routes: Routes = [
SkeletonModule,
MarketplaceSettingsPageModule,
StoreIconComponentModule,
ResponsiveColModule,
ResponsiveColDirective,
],
declarations: [MarketplaceListPage],
exports: [MarketplaceListPage],

View File

@@ -5,7 +5,7 @@ import { IonicModule } from '@ionic/angular'
import { AppListPage } from './app-list.page'
import {
EmverPipesModule,
ResponsiveColModule,
ResponsiveColDirective,
TextSpinnerComponentModule,
TickerModule,
} from '@start9labs/shared'
@@ -35,7 +35,7 @@ const routes: Routes = [
RouterModule.forChild(routes),
BadgeMenuComponentModule,
WidgetListComponentModule,
ResponsiveColModule,
ResponsiveColDirective,
TickerModule,
LaunchMenuComponentModule,
],

View File

@@ -5,7 +5,7 @@ import { IonicModule } from '@ionic/angular'
import { AppShowPage } from './app-show.page'
import {
EmverPipesModule,
ResponsiveColModule,
ResponsiveColDirective,
SharedPipesModule,
} from '@start9labs/shared'
import { StatusComponentModule } from '../status/status.component.module'
@@ -59,7 +59,7 @@ const routes: Routes = [
RouterModule.forChild(routes),
AppConfigPageModule,
EmverPipesModule,
ResponsiveColModule,
ResponsiveColDirective,
SharedPipesModule,
InsecureWarningComponentModule,
LaunchMenuComponentModule,

View File

@@ -1,6 +1,6 @@
import { NgModule } from '@angular/core'
import { CommonModule } from '@angular/common'
import { MarkdownPipeModule, SafeLinksModule } from '@start9labs/shared'
import { MarkdownPipeModule, SafeLinksDirective } from '@start9labs/shared'
import { TuiButtonModule, TuiScrollbarModule } from '@taiga-ui/core'
import { TuiAutoFocusModule } from '@taiga-ui/cdk'
import { NgDompurifyModule } from '@tinkoff/ng-dompurify'
@@ -14,7 +14,7 @@ import { OSUpdatePage } from './os-update.page'
TuiButtonModule,
TuiAutoFocusModule,
TuiScrollbarModule,
SafeLinksModule,
SafeLinksDirective,
NgDompurifyModule,
],
exports: [OSUpdatePage],

View File

@@ -9,7 +9,7 @@ import {
import {
EmverPipesModule,
MarkdownPipeModule,
SafeLinksModule,
SafeLinksDirective,
SharedPipesModule,
} from '@start9labs/shared'
import { NgDompurifyModule } from '@tinkoff/ng-dompurify'
@@ -40,7 +40,7 @@ const routes: Routes = [
StoreIconComponentModule,
EmverPipesModule,
MimeTypePipeModule,
SafeLinksModule,
SafeLinksDirective,
NgDompurifyModule,
TuiProgressModule,
],

View File

@@ -2,14 +2,14 @@ import { NgModule } from '@angular/core'
import { CommonModule } from '@angular/common'
import { IonicModule } from '@ionic/angular'
import { RouterModule } from '@angular/router'
import { ResponsiveColModule } from '@start9labs/shared'
import { ResponsiveColDirective } from '@start9labs/shared'
import { AnyLinkComponent } from './any-link/any-link.component'
import { WidgetListComponent } from './widget-list.component'
import { WidgetCardComponent } from './widget-card/widget-card.component'
@NgModule({
declarations: [WidgetListComponent, WidgetCardComponent, AnyLinkComponent],
imports: [CommonModule, IonicModule, RouterModule, ResponsiveColModule],
imports: [CommonModule, IonicModule, RouterModule, ResponsiveColDirective],
exports: [WidgetListComponent],
})
export class WidgetListComponentModule {}