v1.2: overwrite confirm, transfer speed/ETA, settings + themes, fused macOS titlebar
- Overwrite confirmation: name-collision detection before enqueue; dialog shows source vs destination (size, mtime, 'newer' badge) with per-item Skip/Replace and batch Skip all / Replace all; type mismatches auto-skip with a toast; cancel aborts the whole operation - Transfer speed + ETA: UI computes smoothed bytes/sec from progress deltas (callback bus makes deltas meaningful); shown in the expanded queue rows and the status-bar summary; unit follows the speed-unit setting - Settings: bun-side SettingsStore (settings.json, 0600, atomic) + get/save RPC; SettingsService; gear popover on the tab row (theme segmented control, speed unit); persisted across restarts - Light theme: data-theme on <html> drives token overrides; absent = follow OS - macOS fused titlebar: hiddenInset + trafficLightOffset, tab row becomes the draggable titlebar (app-region drag/no-drag classes); other platforms keep a separate titlebar (gated by a platform value injected via window preload) - README: known-issues note for the upstream Bun/Electrobun FFI crash Verified: tsc + ui build clean; SettingsStore roundtrip + 0600 headless; app boots and the UI fetches settings over RPC at startup. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
This commit is contained in:
@@ -1,7 +1,9 @@
|
||||
import { Component, computed, inject } from '@angular/core';
|
||||
import { NgIcon } from '@ng-icons/core';
|
||||
import type { TransferSnapshot } from '@shared/types';
|
||||
import { formatSpeed } from '../format';
|
||||
import { PanelsService } from '../panels.service';
|
||||
import { SettingsService } from '../settings.service';
|
||||
import { TransfersService } from '../transfers.service';
|
||||
|
||||
@Component({
|
||||
@@ -20,7 +22,7 @@ import { TransfersService } from '../transfers.service';
|
||||
@if (transfers.currentJob(); as job) {
|
||||
<ng-icon name="mynaSpinner" size="0.8rem" class="shrink-0 animate-spin text-primary" />
|
||||
<span class="truncate">
|
||||
Copying {{ job.name }} · {{ percent(job) }}%
|
||||
Copying {{ job.name }} · {{ percent(job) }}%{{ speedSuffix(job) }}
|
||||
@if (transfers.queuedCount(); as queued) {
|
||||
· {{ queued }} queued
|
||||
}
|
||||
@@ -57,10 +59,16 @@ import { TransfersService } from '../transfers.service';
|
||||
export class StatusBar {
|
||||
readonly transfers = inject(TransfersService);
|
||||
readonly panels = inject(PanelsService);
|
||||
readonly settings = inject(SettingsService);
|
||||
readonly activePanel = computed(() => this.panels.get(this.panels.activeSide()));
|
||||
|
||||
percent(job: TransferSnapshot): number {
|
||||
if (!job.totalBytes) return 0;
|
||||
return Math.min(100, Math.round((job.doneBytes / job.totalBytes) * 100));
|
||||
}
|
||||
|
||||
speedSuffix(job: TransferSnapshot): string {
|
||||
const speed = this.transfers.speeds().get(job.id);
|
||||
return speed ? ` · ${formatSpeed(speed, this.settings.speedUnit())}` : '';
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user