| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245 |
- /* eslint-disable @typescript-eslint/explicit-module-boundary-types */
- import { Component, Input, HostListener, HostBinding, ViewChildren, ViewChild } from '@angular/core'
- import { trigger, style, animate, transition, state } from '@angular/animations'
- import { NgbDropdown, NgbModal } from '@ng-bootstrap/ng-bootstrap'
- import { CdkDragDrop, moveItemInArray } from '@angular/cdk/drag-drop'
- import { HostAppService, Platform } from '../api/hostApp'
- import { HotkeysService } from '../services/hotkeys.service'
- import { Logger, LogService } from '../services/log.service'
- import { ConfigService } from '../services/config.service'
- import { ThemesService } from '../services/themes.service'
- import { UpdaterService } from '../services/updater.service'
- import { CommandService } from '../services/commands.service'
- import { BaseTabComponent } from './baseTab.component'
- import { SafeModeModalComponent } from './safeModeModal.component'
- import { TabBodyComponent } from './tabBody.component'
- import { SplitTabComponent } from './splitTab.component'
- import { AppService, Command, CommandLocation, FileTransfer, HostWindowService, PlatformService } from '../api'
- import { CommonModule } from '@angular/common'
- function makeTabAnimation (dimension: string, size: number) {
- return [
- state('in', style({
- 'flex-basis': '{{size}}',
- [dimension]: '{{size}}',
- }), {
- params: { size: `${size}px` },
- }),
- transition(':enter', [
- style({
- 'flex-basis': '1px',
- [dimension]: '1px',
- }),
- animate('250ms ease-out', style({
- 'flex-basis': '{{size}}',
- [dimension]: '{{size}}',
- })),
- ]),
- transition(':leave', [
- style({
- 'flex-basis': 'auto',
- 'padding-left': '*',
- 'padding-right': '*',
- [dimension]: '*',
- }),
- animate('250ms ease-in-out', style({
- 'padding-left': 0,
- 'padding-right': 0,
- [dimension]: '0',
- })),
- ]),
- ]
- }
- /** @hidden */
- @Component({
- imports: [CommonModule],
- standalone: true,
- selector: 'app-root',
- template: require('./appRoot.component.pug'),
- styles: [require('./appRoot.component.scss')],
- animations: [
- trigger('animateTab', makeTabAnimation('width', 200)),
- ],
- })
- export class AppRootComponent {
- Platform = Platform
- @Input() ready = false
- @Input() leftToolbarButtons: Command[]
- @Input() rightToolbarButtons: Command[]
- @HostBinding('class.platform-win32') platformClassWindows = process.platform === 'win32'
- @HostBinding('class.platform-darwin') platformClassMacOS = process.platform === 'darwin'
- @HostBinding('class.platform-linux') platformClassLinux = process.platform === 'linux'
- @HostBinding('class.no-tabs') noTabs = true
- @ViewChildren(TabBodyComponent) tabBodies: TabBodyComponent[]
- @ViewChild('activeTransfersDropdown') activeTransfersDropdown: NgbDropdown
- unsortedTabs: BaseTabComponent[] = []
- updatesAvailable = false
- activeTransfers: FileTransfer[] = []
- private logger: Logger
- constructor (
- private hotkeys: HotkeysService,
- private updater: UpdaterService,
- private commands: CommandService,
- public hostWindow: HostWindowService,
- public hostApp: HostAppService,
- public config: ConfigService,
- public app: AppService,
- platform: PlatformService,
- log: LogService,
- ngbModal: NgbModal,
- _themes: ThemesService,
- ) {
- this.logger = log.create('main')
- this.logger.info('v', platform.getAppVersion())
- this.hotkeys.hotkey$.subscribe((hotkey: string) => {
- if (hotkey.startsWith('tab-')) {
- const index = parseInt(hotkey.split('-')[1])
- if (index <= this.app.tabs.length) {
- this.app.selectTab(this.app.tabs[index - 1])
- }
- }
- if (this.app.activeTab) {
- if (hotkey === 'close-tab') {
- this.app.closeTab(this.app.activeTab, true)
- }
- if (hotkey === 'toggle-last-tab') {
- this.app.toggleLastTab()
- }
- if (hotkey === 'next-tab') {
- this.app.nextTab()
- }
- if (hotkey === 'previous-tab') {
- this.app.previousTab()
- }
- if (hotkey === 'move-tab-left') {
- this.app.moveSelectedTabLeft()
- }
- if (hotkey === 'move-tab-right') {
- this.app.moveSelectedTabRight()
- }
- if (hotkey === 'duplicate-tab') {
- this.app.duplicateTab(this.app.activeTab)
- }
- if (hotkey === 'restart-tab') {
- this.app.duplicateTab(this.app.activeTab)
- this.app.closeTab(this.app.activeTab, true)
- }
- if (hotkey === 'explode-tab' && this.app.activeTab instanceof SplitTabComponent) {
- this.app.explodeTab(this.app.activeTab)
- }
- if (hotkey === 'combine-tabs' && this.app.activeTab instanceof SplitTabComponent) {
- this.app.combineTabsInto(this.app.activeTab)
- }
- }
- if (hotkey === 'reopen-tab') {
- this.app.reopenLastTab()
- }
- if (hotkey === 'toggle-fullscreen') {
- hostWindow.toggleFullscreen()
- }
- })
- this.hostWindow.windowCloseRequest$.subscribe(async () => {
- this.app.closeWindow()
- })
- if (window['safeModeReason']) {
- ngbModal.open(SafeModeModalComponent)
- }
- this.app.tabOpened$.subscribe(tab => {
- this.unsortedTabs.push(tab)
- this.noTabs = false
- this.app.emitTabDragEnded()
- })
- this.app.tabRemoved$.subscribe(tab => {
- for (const tabBody of this.tabBodies) {
- if (tabBody.tab === tab) {
- tabBody.detach()
- }
- }
- this.unsortedTabs = this.unsortedTabs.filter(x => x !== tab)
- this.noTabs = app.tabs.length === 0
- this.app.emitTabDragEnded()
- })
- platform.fileTransferStarted$.subscribe(transfer => {
- this.activeTransfers.push(transfer)
- this.activeTransfersDropdown.open()
- })
- config.ready$.toPromise().then(async () => {
- this.leftToolbarButtons = await this.getToolbarButtons(false)
- this.rightToolbarButtons = await this.getToolbarButtons(true)
- setInterval(() => {
- if (this.config.store.enableAutomaticUpdates) {
- this.updater.check().then(available => {
- this.updatesAvailable = available
- })
- }
- }, 3600 * 12 * 1000)
- })
- }
- async ngOnInit () {
- this.config.ready$.toPromise().then(() => {
- this.ready = true
- this.app.emitReady()
- })
- }
- @HostListener('dragover')
- onDragOver () {
- return false
- }
- @HostListener('drop')
- onDrop () {
- return false
- }
- hasVerticalTabs () {
- return this.config.store.appearance.tabsLocation === 'left' || this.config.store.appearance.tabsLocation === 'right'
- }
- get targetTabSize (): any {
- if (this.hasVerticalTabs()) {
- return '*'
- }
- return this.config.store.appearance.flexTabs ? '*' : '200px'
- }
- onTabsReordered (event: CdkDragDrop<BaseTabComponent[]>) {
- const tab: BaseTabComponent = event.item.data
- if (!this.app.tabs.includes(tab)) {
- if (tab.parent instanceof SplitTabComponent) {
- tab.parent.removeTab(tab)
- this.app.wrapAndAddTab(tab)
- }
- }
- moveItemInArray(this.app.tabs, event.previousIndex, event.currentIndex)
- this.app.emitTabsChanged()
- }
- onTransfersChange () {
- if (this.activeTransfers.length === 0) {
- this.activeTransfersDropdown.close()
- }
- }
- @HostBinding('class.vibrant') get isVibrant () {
- return this.config.store?.appearance.vibrancy
- }
- private async getToolbarButtons (aboveZero: boolean): Promise<Command[]> {
- return (await this.commands.getCommands({ tab: this.app.activeTab ?? undefined }))
- .filter(x => x.locations?.includes(aboveZero ? CommandLocation.RightToolbar : CommandLocation.LeftToolbar))
- }
- }
|