Files
whisper_voice/src/ui/qml/Loader.qml
Your Name d509eb5efb WCAG: Review fixes - arrow keys, PageTab roles, AlertMessage
Add Up/Down arrow key navigation to Settings sidebar.
Add Accessible.role: Accessible.PageTab to all 5 tab pages.
Fix Loader status to use AlertMessage role per WCAG 4.1.3.
2026-02-18 21:10:21 +02:00

193 lines
6.3 KiB
QML

import QtQuick
import QtQuick.Controls
import QtQuick.Effects
ApplicationWindow {
id: root
FontLoader {
id: jetBrainsMono
source: "fonts/ttf/JetBrainsMono-Bold.ttf"
}
width: 400
height: 250
visible: true
flags: Qt.FramelessWindowHint | Qt.WindowStaysOnTopHint | Qt.Tool
color: "transparent"
title: "WhisperVoice"
Accessible.name: "WhisperVoice Loading"
Rectangle {
id: bgRect
anchors.fill: parent
anchors.margins: 20 // Space for shadow
radius: 16
color: "#1a1a20"
border.color: Qt.rgba(1, 1, 1, 0.22)
border.width: 1
// --- SHADOW & GLOW ---
layer.enabled: true
layer.effect: MultiEffect {
shadowEnabled: true
shadowColor: "#80000000"
shadowBlur: 1.0
shadowOpacity: 0.8
shadowVerticalOffset: 4
autoPaddingEnabled: true
}
// --- CONTENT ---
Column {
anchors.centerIn: parent
width: parent.width - 60
spacing: 24
// Logo / Icon Area
Item {
width: 60; height: 60
anchors.horizontalCenter: parent.horizontalCenter
Rectangle {
anchors.fill: parent
radius: 30
color: "transparent"
border.width: 2
border.color: "#00f2ff"
// Pulse Animation
SequentialAnimation on scale {
running: ui ? !ui.reduceMotion : true
loops: Animation.Infinite
NumberAnimation { from: 1.0; to: 1.1; duration: 1000; easing.type: Easing.InOutSine }
NumberAnimation { from: 1.1; to: 1.0; duration: 1000; easing.type: Easing.InOutSine }
}
}
Image {
source: "microphone.svg"
anchors.centerIn: parent
width: 32; height: 32
sourceSize: Qt.size(32, 32)
fillMode: Image.PreserveAspectFit
smooth: true
// Colorize
layer.enabled: true
layer.effect: MultiEffect {
colorization: 1.0
colorizationColor: "#00f2ff"
}
}
}
// Title
Column {
spacing: 4
anchors.horizontalCenter: parent.horizontalCenter
Text {
text: "WHISPER VOICE"
color: "#ffffff"
font.family: jetBrainsMono.name
font.pixelSize: 18
font.bold: true
font.letterSpacing: 3
anchors.horizontalCenter: parent.horizontalCenter
}
Text {
text: "AI TRANSCRIPTION ENGINE"
color: "#ABABAB"
font.family: jetBrainsMono.name
font.pixelSize: 10
font.letterSpacing: 2
anchors.horizontalCenter: parent.horizontalCenter
}
}
// Status & Progress
Column {
width: parent.width
spacing: 8
// Progress Bar Background
Rectangle {
width: parent.width
height: 4
color: "#252530"
radius: 2
clip: true
// Progress Fill
Rectangle {
width: (ui.downloadProgress / 100.0) * parent.width
height: parent.height
radius: 2
gradient: Gradient {
orientation: Gradient.Horizontal
GradientStop { position: 0.0; color: "#00f2ff" }
GradientStop { position: 1.0; color: "#00a0ff" }
}
Behavior on width {
NumberAnimation { duration: 250; easing.type: Easing.OutCubic }
}
// Shimmer effect on bar
Rectangle {
width: 20; height: parent.height
visible: ui ? !ui.reduceMotion : true
color: "#80ffffff"
x: -width
opacity: 0.5
rotation: 20
transformOrigin: Item.Center
NumberAnimation on x {
from: 0; to: parent.width + 50
duration: 1000
loops: Animation.Infinite
}
}
}
}
// Status Text
Text {
text: ui.loaderStatus
color: "#00f2ff"
font.family: jetBrainsMono.name
font.pixelSize: 11
font.bold: true
Accessible.role: Accessible.AlertMessage
Accessible.name: "Loading status: " + text
anchors.horizontalCenter: parent.horizontalCenter
opacity: 1.0
}
}
}
}
// Entry Animation
Component.onCompleted: {
bgRect.scale = 0.9
bgRect.opacity = 0
entryAnim.start()
}
ParallelAnimation {
id: entryAnim
NumberAnimation {
target: bgRect; property: "scale"
to: 1.0; duration: 600; easing.type: Easing.OutBack
}
NumberAnimation {
target: bgRect; property: "opacity"
to: 1.0; duration: 400
}
}
}