added installation progress tab
This commit is contained in:
parent
9e5457c2ec
commit
ad826b3b43
3 changed files with 254 additions and 76 deletions
208
main.go
208
main.go
|
@ -2,24 +2,32 @@ package main
|
|||
|
||||
import (
|
||||
"fmt"
|
||||
"math"
|
||||
"os"
|
||||
|
||||
rl "github.com/gen2brain/raylib-go/raylib"
|
||||
)
|
||||
|
||||
// Keep your global variables for steps and transitions
|
||||
var (
|
||||
transition = NewTransitionManager()
|
||||
currentStep = 0
|
||||
targetStep = 0
|
||||
useDefault = false
|
||||
|
||||
transition = NewTransitionManager()
|
||||
currentStep = 0
|
||||
targetStep = 0
|
||||
useDefault = false
|
||||
step1DefaultRect rl.Rectangle
|
||||
step1CustomRect rl.Rectangle
|
||||
|
||||
// Our global Installer from installer.go
|
||||
installer = NewInstaller()
|
||||
|
||||
// We no longer store circleToCenter or "display progress" here.
|
||||
// Instead, we use the new CircleAnimator:
|
||||
circleAnimator = NewCircleAnimator()
|
||||
|
||||
// textHoverFade => for the small circle’s info text in steps 0..2
|
||||
textHoverFade float32
|
||||
)
|
||||
|
||||
const finalStep = 3
|
||||
|
||||
func main() {
|
||||
monitor := rl.GetCurrentMonitor()
|
||||
screenW := rl.GetMonitorWidth(monitor)
|
||||
|
@ -31,16 +39,17 @@ func main() {
|
|||
|
||||
refreshRate := rl.GetMonitorRefreshRate(monitor)
|
||||
if refreshRate <= 0 {
|
||||
refreshRate = 60 // Fallback to 60 if detection fails
|
||||
refreshRate = 60
|
||||
}
|
||||
rl.SetTargetFPS(int32(refreshRate))
|
||||
|
||||
InitBackground(rl.GetScreenWidth(), rl.GetScreenHeight())
|
||||
|
||||
// Start the download+decompress in background immediately:
|
||||
// Start the download+decompress in background immediately
|
||||
installer.StartDownloadDecompress()
|
||||
|
||||
targetStep = 0
|
||||
// Initially step 0 => circle is top-right => circleAnimator.PosAlpha=0
|
||||
circleAnimator.SetStep(0)
|
||||
|
||||
for !rl.WindowShouldClose() {
|
||||
screenW = rl.GetScreenWidth()
|
||||
|
@ -54,24 +63,50 @@ func main() {
|
|||
nextX := int32(screenW - 150)
|
||||
nextY := prevY
|
||||
|
||||
// Update transition
|
||||
// Transition update
|
||||
oldAlpha, oldScale, oldOffsetX, newAlpha, newScale, newOffsetX := transition.Update()
|
||||
|
||||
if !transition.IsActive() && currentStep != targetStep {
|
||||
currentStep = targetStep
|
||||
// Update circleAnimator step so it moves (0 => top-right, 3 => center)
|
||||
circleAnimator.SetStep(currentStep)
|
||||
}
|
||||
|
||||
// Poll SPM progress for the GUI
|
||||
// Poll SPM progress
|
||||
installer.PollProgress()
|
||||
|
||||
// If an unrecoverable error occurred, you could handle it here:
|
||||
// (For now, we just print it in the console.)
|
||||
// If error
|
||||
if installer.LastError != nil {
|
||||
fmt.Println("SPM Error:", installer.LastError)
|
||||
// You might choose to show a popup or do something else
|
||||
}
|
||||
|
||||
// GUI input
|
||||
// Update circle animator every frame
|
||||
// This will ease the actual SPM progress => "DisplayProgress"
|
||||
circleAnimator.Update(installer.Progress)
|
||||
|
||||
// textHoverFade for step<3
|
||||
if currentStep < finalStep {
|
||||
topRightX := float32(screenW - 80)
|
||||
topRightY := float32(100)
|
||||
radius := float32(30)
|
||||
dx := mousePos.X - topRightX
|
||||
dy := mousePos.Y - topRightY
|
||||
dist := float32(math.Sqrt(float64(dx*dx + dy*dy)))
|
||||
if dist < radius+30 {
|
||||
textHoverFade += 0.1
|
||||
if textHoverFade > 1 {
|
||||
textHoverFade = 1
|
||||
}
|
||||
} else {
|
||||
textHoverFade -= 0.1
|
||||
if textHoverFade < 0 {
|
||||
textHoverFade = 0
|
||||
}
|
||||
}
|
||||
} else {
|
||||
textHoverFade = 0
|
||||
}
|
||||
|
||||
// Mouse input
|
||||
if !transition.IsActive() && rl.IsMouseButtonPressed(rl.MouseLeftButton) {
|
||||
handleInput(mousePos, screenW, screenH, buttonW, buttonH, prevX, prevY, nextX, nextY)
|
||||
}
|
||||
|
@ -89,7 +124,6 @@ func main() {
|
|||
oldStep = transition.oldStep
|
||||
newStep = transition.newStep
|
||||
}
|
||||
|
||||
phase := transition.GetPhase()
|
||||
if transition.IsActive() {
|
||||
if phase == TransitionOutFadeScale {
|
||||
|
@ -99,10 +133,11 @@ func main() {
|
|||
drawStep(newStep, screenW, screenH, mousePos, newAlpha, newScale, newOffsetX)
|
||||
}
|
||||
} else {
|
||||
drawStep(currentStep, screenW, screenH, mousePos, 1.0, 1.0, 0.0)
|
||||
drawStep(currentStep, screenW, screenH, mousePos, 1, 1, 0)
|
||||
}
|
||||
|
||||
if !transition.IsActive() {
|
||||
// Nav buttons if not final step
|
||||
if !transition.IsActive() && currentStep < finalStep {
|
||||
if currentStep > 0 && currentStep < 3 {
|
||||
drawButton("Previous", prevX, prevY, int32(buttonW), int32(buttonH), mousePos)
|
||||
}
|
||||
|
@ -113,33 +148,29 @@ func main() {
|
|||
}
|
||||
}
|
||||
|
||||
// Draw the semi-transparent loading circle if user is downloading or installing
|
||||
if installer.IsDownloading || installer.IsInstalling {
|
||||
drawInstallProgress(screenW, installer.Progress, installer.Task)
|
||||
}
|
||||
// Draw the circle
|
||||
drawInstallCircle(screenW, screenH, circleAnimator.PosAlpha, circleAnimator.DisplayProgress, installer.DoneInstall, textHoverFade)
|
||||
|
||||
rl.EndDrawing()
|
||||
}
|
||||
}
|
||||
|
||||
// handleInput acts on mouse clicks in each step
|
||||
func handleInput(mousePos rl.Vector2, screenW, screenH, buttonW, buttonH int,
|
||||
prevX, prevY, nextX, nextY int32) {
|
||||
|
||||
if currentStep == 0 {
|
||||
func handleInput(mousePos rl.Vector2, screenW, screenH, buttonW, buttonH int, prevX, prevY, nextX, nextY int32) {
|
||||
switch currentStep {
|
||||
case 0:
|
||||
if overRect(mousePos, step1DefaultRect) {
|
||||
// user clicked "Default" => do final install if not already installing
|
||||
useDefault = true
|
||||
if !installer.IsInstalling && !installer.DoneInstall {
|
||||
installer.FinalInstall()
|
||||
}
|
||||
fmt.Println("Installation started with default settings.")
|
||||
startTransition(currentStep, finalStep)
|
||||
}
|
||||
if overRect(mousePos, step1CustomRect) {
|
||||
useDefault = false
|
||||
startTransition(currentStep, 1)
|
||||
}
|
||||
} else if currentStep == 1 {
|
||||
|
||||
case 1:
|
||||
if overButton(mousePos, nextX, nextY, int32(buttonW), int32(buttonH)) {
|
||||
startTransition(currentStep, 2)
|
||||
}
|
||||
|
@ -149,14 +180,14 @@ func handleInput(mousePos rl.Vector2, screenW, screenH, buttonW, buttonH int,
|
|||
selectColor(mousePos)
|
||||
selectContrastIcon(mousePos)
|
||||
selectTheme(mousePos)
|
||||
} else if currentStep == 2 {
|
||||
|
||||
case 2:
|
||||
if overButton(mousePos, nextX, nextY, int32(buttonW), int32(buttonH)) {
|
||||
// user clicked "Finish" => final install if not already installing
|
||||
if !installer.IsInstalling && !installer.DoneInstall {
|
||||
installer.FinalInstall()
|
||||
}
|
||||
fmt.Printf("Installation started:\nDefault: %v\nColor: %s\nTheme: %s\nLayout: %s\n",
|
||||
useDefault, selectedColor, selectedTheme, selectedLayout)
|
||||
fmt.Printf("Installation started:\nDefault: %v\nColor: %s\nTheme: %s\nLayout: %s\n", useDefault, selectedColor, selectedTheme, selectedLayout)
|
||||
startTransition(currentStep, finalStep)
|
||||
}
|
||||
if overButton(mousePos, int32(prevX), int32(prevY), int32(buttonW), int32(buttonH)) {
|
||||
startTransition(currentStep, 1)
|
||||
|
@ -165,7 +196,6 @@ func handleInput(mousePos rl.Vector2, screenW, screenH, buttonW, buttonH int,
|
|||
}
|
||||
}
|
||||
|
||||
// drawHeader is your original function
|
||||
func drawHeader(screenW int) {
|
||||
title := "Spitfire Browser Installer"
|
||||
titleFontSize := int32(30)
|
||||
|
@ -174,37 +204,89 @@ func drawHeader(screenW int) {
|
|||
rl.DrawLine(50, 60, int32(screenW)-50, 60, rl.Fade(rl.White, 0.5))
|
||||
}
|
||||
|
||||
// drawInstallProgress displays a simple white circle with partial alpha,
|
||||
// plus the current task text below it, in the top-right area.
|
||||
func drawInstallProgress(screenW int, progress int, task string) {
|
||||
circleX := float32(screenW - 80)
|
||||
circleY := float32(100)
|
||||
radius := float32(30)
|
||||
|
||||
// Colors for the circle
|
||||
bgColor := rl.Color{R: 255, G: 255, B: 255, A: 80}
|
||||
fillColor := rl.Color{R: 255, G: 255, B: 255, A: 200}
|
||||
// Now we pass "displayProgress" (0..100) as a float, "posAlpha" in [0..1],
|
||||
// plus "doneInstall" to show the "Run App" button
|
||||
func drawInstallCircle(screenW, screenH int, posAlpha, displayProgress float32, doneInstall bool, hoverAlpha float32) {
|
||||
// Lerp position/radius
|
||||
topRight := rl.Vector2{X: float32(screenW - 80), Y: 100}
|
||||
center := rl.Vector2{X: float32(screenW) / 2, Y: float32(screenH)/2 - 50}
|
||||
x := lerp(topRight.X, center.X, posAlpha)
|
||||
y := lerp(topRight.Y, center.Y, posAlpha)
|
||||
r := lerp(30, 60, posAlpha)
|
||||
|
||||
// Draw background circle
|
||||
rl.DrawCircle(int32(circleX), int32(circleY), radius, bgColor)
|
||||
bgColor := rl.Color{255, 255, 255, 80}
|
||||
fillColor := rl.Color{255, 255, 255, 200}
|
||||
|
||||
// Draw progress arc
|
||||
angle := float32(progress) / 100.0 * 360.0
|
||||
rl.DrawCircleSector(
|
||||
rl.Vector2{X: circleX, Y: circleY},
|
||||
radius,
|
||||
0,
|
||||
angle,
|
||||
40,
|
||||
fillColor,
|
||||
)
|
||||
rl.DrawCircle(int32(x), int32(y), r, bgColor)
|
||||
angle := displayProgress / 100.0 * 360.0
|
||||
rl.DrawCircleSector(rl.Vector2{X: x, Y: y}, r, 0, angle, 60, fillColor)
|
||||
|
||||
// Print numeric progress
|
||||
txt := fmt.Sprintf("%3d%%", progress)
|
||||
rl.DrawText(txt, int32(circleX)-rl.MeasureText(txt, 18)/2, int32(circleY)-10, 18, rl.White)
|
||||
// Draw numeric progress
|
||||
txt := fmt.Sprintf("%3.0f%%", displayProgress)
|
||||
var fontSize int32 = 18
|
||||
if posAlpha > 0.5 {
|
||||
fontSize = 24 // bigger in final steps
|
||||
}
|
||||
txtW := rl.MeasureText(txt, fontSize)
|
||||
rl.DrawText(txt, int32(x)-txtW/2, int32(y)-(fontSize/2), fontSize, rl.White)
|
||||
|
||||
// Draw wrapped task text below the circle
|
||||
drawTextWrapped(task, int32(circleX)-100, int32(circleY)+40, 200, 18, rl.White)
|
||||
if currentStep < finalStep {
|
||||
// show the task text with "hoverAlpha"
|
||||
if hoverAlpha > 0 {
|
||||
drawTextWrappedAlpha(installer.Task, int32(x)-100, int32(y)+35, 200, 18, rl.White, hoverAlpha)
|
||||
}
|
||||
} else {
|
||||
// final step => always show text, lower so bigger circle won't overlap
|
||||
drawTextWrapped(installer.Task, int32(x)-100, int32(y+r+10), 200, 18, rl.White)
|
||||
if doneInstall {
|
||||
drawRunAppButton(x, y+r+80)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// "Run App" button logic is the same
|
||||
func drawRunAppButton(cx, cy float32) {
|
||||
w := float32(180)
|
||||
h := float32(50)
|
||||
rect := rl.Rectangle{X: cx - w/2, Y: cy, Width: w, Height: h}
|
||||
hovered := overRect(rl.GetMousePosition(), rect)
|
||||
drawRoundedRectButton(rect, "Start Spitfire", 1.0, hovered)
|
||||
if hovered && rl.IsMouseButtonPressed(rl.MouseLeftButton) {
|
||||
fmt.Println("Launching the app (placeholder)...")
|
||||
os.Exit(0)
|
||||
}
|
||||
}
|
||||
|
||||
// linear interpolation
|
||||
func lerp(a, b, t float32) float32 {
|
||||
return a + (b-a)*t
|
||||
}
|
||||
|
||||
// Helper for text wrapping with alpha
|
||||
func drawTextWrappedAlpha(text string, x, y, maxWidth, fontSize int32, color rl.Color, alpha float32) {
|
||||
words := splitIntoWords(text)
|
||||
line := ""
|
||||
offsetY := int32(0)
|
||||
|
||||
for _, word := range words {
|
||||
testLine := line + word + " "
|
||||
if rl.MeasureText(testLine, fontSize) > int32(maxWidth) {
|
||||
drawColoredText(line, x, y+offsetY, fontSize, color)
|
||||
line = word + " "
|
||||
offsetY += fontSize + 2
|
||||
} else {
|
||||
line = testLine
|
||||
}
|
||||
}
|
||||
if line != "" {
|
||||
drawColoredText(line, x, y+offsetY, fontSize, color)
|
||||
}
|
||||
}
|
||||
|
||||
// Same as drawTextWrapped, just using a color param
|
||||
func drawColoredText(text string, x, y, fontSize int32, color rl.Color) {
|
||||
rl.DrawText(text, x, y, fontSize, color)
|
||||
}
|
||||
|
||||
// Custom function to draw text with wrapping
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue